Securing your PHP file upload scripts.

slacker3

New Member
Messages
146
Reaction score
6
Points
0
Since there is not much documentation on this topic i want to give you some suggestions about how to handle file uploads in PHP. This tutorial will just describe how to identify file formats and size.


First of all you may want to allow only certain file formats to be uploaded. Allowing the upload of PHP/html/etc. files is a really BAD idea since it can get you owned in just a few seconds.. :biggrin:

So the first step is to create a WHITELIST of file formats allowed to be uploaded. Please note that you still can't trust the file content, it can still contain anything.

File extensions (like .exe, .com, .txt and so on) can be easily changed, don't rely on them solely. A good alternate way to identify file formats is by the so called "magic number" which is just a 2-byte (or longer) identifier at the beginning of a file.


What wikipedia says about magic numbers:
http://en.wikipedia.org/wiki/File_format#Magic_number

a short overview of different magic numbers in files:
http://en.wikipedia.org/wiki/Magic_number_(programming)#Magic_numbers_in_files




Now some sample code..
Here the magic number will be checked to allow only files in the libpcap format.

as http://wiki.wireshark.org/Development/LibpcapFileFormat says about the libpcap file header:
Code:
  typedef struct pcap_hdr_s {
        guint32 magic_number;   /* magic number */
        guint16 version_major;  /* major version number */
        guint16 version_minor;  /* minor version number */
        gint32  thiszone;       /* GMT to local correction */
        guint32 sigfigs;        /* accuracy of timestamps */
        guint32 snaplen;        /* max length of captured packets, in octets */
        guint32 network;        /* data link type */
} pcap_hdr_t;
magic_number:
used to detect the file format itself and the byte
ordering. The writing application writes 0xa1b2c3d4 with it's native
byte ordering format into this field. The reading application will read
either 0xa1b2c3d4 (identical) or 0xd4c3b2a1 (swapped). If the reading
application reads the swapped 0xd4c3b2a1 value, it knows that all the
following fields will have to be swapped too.



..so we just have to check for:

PHP:
    if ( is_uploaded_file ( $_FILES['file']['tmp_name'] ) )
    {
      print 'uploaded ' . $_FILES['file']['size'] . ' bytes <br />';

      $filehandle = fopen($_FILES['file']['tmp_name'],"r");

      // get file's magic number
      $MNUMBER =  bin2hex(fread($filehandle,4));
      // check if libpcap
      if ("$MNUMBER" != "a1b2c3d4" && $MNUMBER != "d4c3b2a1") {
         print 'bad file format ! <br />';
      exit;
      }
...
to allow only the upload of files in the libpcap file format.




to check for the size of the uploaded file:
PHP:
        if ($_FILES['file']['size'] > 8388608)
           print 'file size limit reached ! <br />';
 
Last edited:

jacob3

New Member
Messages
3
Reaction score
0
Points
0
Hi slacker,
That's interesting .. good idea!

Another additional way to secure uploads would be to make sure they're ALL in a separate directory and add a .htaccess file:

Code:
RemoveHandler .cgi .php .html 
AddType application/octet-stream .cgi .php .html
including whatever file types you're concerned about. This should prevent anybody running any scripts on the server (accidently OR on purpose). Anyone who tries any URL in that directory should only be able to download one of those mimetypes specified.


Do you like it?? :lockd: ;)

Perhaps more importantly, if you read the x10hosting TOS, you shouldn't give ANYBODY authority to upload to the server except for yourself :biggrin:

Even better!
 
Last edited:

slacker3

New Member
Messages
146
Reaction score
6
Points
0
That's fine. :) :lockd: <-- also i like this.. uhm.. :biggrin:

Of course there are several things to take care of, just checking for four bytes in an uploaded file is not enough. Thank you for adding useful information to this little tutorial.
 
Last edited:
Top