Preventing Hacking Via Image Upload PHP

Discussions of secure PHP coding. Security in software is important, so don't be afraid to ask. And when answering: be anal. Nitpick. No security vulnerability is too small.

Moderator: General Moderators

Post Reply
henllys22
Forum Newbie
Posts: 1
Joined: Tue Mar 09, 2010 10:42 am

Preventing Hacking Via Image Upload PHP

Post by henllys22 »

Hi my site was hacked recently by somebody called Xavier. He or she appeared to have uploaded an index.jpg and an index.php file which over wrote the index.html file in my web site.

He did this using a Php script that allows users of the site to upload images to the site using the move uploaded file function.

Can anyone advise me on the best way to prevent a re-occurrance of this. Should I use the htmlentities function or alike.

Thanks
User avatar
Darhazer
DevNet Resident
Posts: 1011
Joined: Thu May 14, 2009 3:00 pm
Location: HellCity, Bulgaria

Re: Preventing Hacking Via Image Upload PHP

Post by Darhazer »

Store uploaded files in a secure location (either outside document root or in a folder, to which you've denied access via .htaccess file) and use a script to stream the file to the user, so no file will be executed on the server.
User avatar
Ragnis
Forum Commoner
Posts: 31
Joined: Thu Nov 13, 2008 12:35 pm
Location: Saaremaa, Estonia, Europe, Asia, Planet Earth, The Solar System, Milky way.

Re: Preventing Hacking Via Image Upload PHP

Post by Ragnis »

But you can just check the file extension before saving the file.
So nobody won't be able to upload php files.
minorDemocritus
Forum Commoner
Posts: 96
Joined: Thu Apr 01, 2010 7:28 pm
Location: Chicagoland, IL, USA

Re: Preventing Hacking Via Image Upload PHP

Post by minorDemocritus »

Darhazer wrote:Store uploaded files in a secure location (either outside document root or in a folder, to which you've denied access via .htaccess file) and use a script to stream the file to the user, so no file will be executed on the server.
Good advice.
Ragnis wrote:But you can just check the file extension before saving the file.
So nobody won't be able to upload php files.
Simple extension checking seems like it would be easily defeated, unless further validation was done.


henllys22,

You've posted a fairly weak description of the upload form. A detailed description would be helpful, pseudocode would be more helpful, and the code itself would be the most helpful.
User avatar
kaisellgren
DevNet Resident
Posts: 1675
Joined: Sat Jan 07, 2006 5:52 am
Location: Lahti, Finland.

Re: Preventing Hacking Via Image Upload PHP

Post by kaisellgren »

A couple of things to remember:
  • Limit the amount of bytes to upload per user so your server won't run out of space.
  • Limit the amount of files to upload per user so your server won't run out of inodes.
  • Store the files above your document root so that they aren't directly accessible.
  • Serve your files through a PHP-proxy script, write something like:

    Code: Select all

    $data = file_get_contents('/home/account/files/file.png');
    header('Content-Type: image/png');
    header('Content-Length: '.strlen($data));
    header('X-Content-Type-Options: nosniff');
    echo $data;
  • Rename uploaded files to have a completely random name without an extension. If you need to store the filename (and extension/type), store the details in the database.
  • If needed, serve files only when the user has a permission to have it.
  • Never include/execute the files you uploaded. This means no include or require in PHP. No HTML script tags or stylesheet tags including them. No Apache Include commands including them. And so forth.
  • If at all possible, serve the files from other origin. This eliminates origin issues that occur with Flash mostly. Using a different port, a domain name or an IP-address is also fine. Serving from sub-domains is dangerous and with IP-addresses the implementation gets slightly harder (i.e., you can't serve files via the domain, only via IP and you can't serve the site via IP, but via the domain).
  • Beware of LFI and RFI. Rename the filenames before using the filename within functions like fopen(), read(), etc. and validate/sanitize any directory values as needed.
The better you follow my rules, the better you are doing.
User avatar
timWebUK
Forum Contributor
Posts: 239
Joined: Thu Oct 29, 2009 6:48 am
Location: UK

Re: Preventing Hacking Via Image Upload PHP

Post by timWebUK »

Kaisell, I've been reading about how certain filetypes have a specific sequence of bytecode in the header. How can I read these through PHP so that I can store the files without extensions?

Also, can a file be spoofed by containing PNG bytes at the start, but then containing PHP? Any preventative tactics?
User avatar
kaisellgren
DevNet Resident
Posts: 1675
Joined: Sat Jan 07, 2006 5:52 am
Location: Lahti, Finland.

Re: Preventing Hacking Via Image Upload PHP

Post by kaisellgren »

timWebUK wrote:Kaisell, I've been reading about how certain filetypes have a specific sequence of bytecode in the header. How can I read these through PHP so that I can store the files without extensions?
If you are expecting a certain type of file (e.g. an image), then store it without an extension and serve it as an image. If the uploaded file had a .png extension, then serve it as a PNG-image.
timWebUK wrote:Also, can a file be spoofed by containing PNG bytes at the start, but then containing PHP? Any preventative tactics?
Yes. Save your time and believe me that inspecting files to make sure they are "safe" is useless. Any file could be malicious in some contexts. You simply can't trust the contents of files. That's why you need to take the precautions I listed above.
User avatar
timWebUK
Forum Contributor
Posts: 239
Joined: Thu Oct 29, 2009 6:48 am
Location: UK

Re: Preventing Hacking Via Image Upload PHP

Post by timWebUK »

What's the best way to filter off the extension? If you remove the last 4 characters, this could easily be bypassed by naming a file 'hello.php.php'... any ideas?

Checking the filename for the actual string .php, could that be problematic too?
User avatar
flying_circus
Forum Regular
Posts: 732
Joined: Wed Mar 05, 2008 10:23 pm
Location: Sunriver, OR

Re: Preventing Hacking Via Image Upload PHP

Post by flying_circus »

The first thing that comes to mind is explode('.', $filename); though, I'd be interested to see what Kai has to say.
User avatar
kaisellgren
DevNet Resident
Posts: 1675
Joined: Sat Jan 07, 2006 5:52 am
Location: Lahti, Finland.

Re: Preventing Hacking Via Image Upload PHP

Post by kaisellgren »

There's no reason to strip off extensions, just rename the entire filename to random. After the file has been uploaded, you can save the filename in the database, and after that you rename the entire filename to random. When you are serving the file, you output its contents and the name as the one you saved in your database. For example:

Code: Select all

$data =  file_get_contents('/home/account/files/file.zip');
header('Content-Type: application/octet-stream');
header('Content-Length: '.strlen($data));
header('Content-Disposition: attachment; filename='.$filenameFromDb);
header('X-Content-Type-Options: nosniff');
echo $data;
Remember: $filenameFromDb has to be filtered or you are vulnerable to header injections.
timWebUK wrote:Checking the filename for the actual string .php, could that be problematic too?
That would be useless.
Post Reply