0

I'm busy coding a PHP file for secure file uploading of images such as .jpg, .jpeg, .png, .bmp, and .gif

Here is the code:

$realname = $_FILES['userfile']['name'];

if(!preg_match("/(\.jpg|\.png|\.gif|\.bmp|\.jpeg)$/i",$realname)) {
          die();
}

Is there a way to bypass this check to be able to upload a .php file? I've heard of the file.php%00.jpg trick, but that is secured from. Does anyone know of any other methods? Or is the code above safe?

Qantas 94 Heavy
  • 15,750
  • 31
  • 68
  • 83
John
  • 1
  • 4
    since file extensions are meaningless, check the actual file type –  Aug 15 '13 at 20:51
  • sure, `ren nastyvirus.php cutekittens.jpg` and off you go. Thankfully, most servers don't treat .jpg files as PHP scripts, so the raw code would just be send to the client, unlike a php file, which would be executed. Never based security decisions off something a user provided. use server-side file-type determination, e.g. fileinfo, to see if it's really an image, or just something PRETENDING to be an image. – Marc B Aug 15 '13 at 20:53
  • @Dagon The server uses the file name extension to decide how to handle the file. You can embed PHP code in a perfectly valid image file so better make sure you don’t allow `.php`. – Gumbo Aug 15 '13 at 21:01
  • The server *may* do that, its not the only option. –  Aug 15 '13 at 21:02
  • @Dagon So what other options you think are there? – Gumbo Aug 15 '13 at 21:03
  • @Gumbo `AddHandler x-httpd-php .bmp .gif .jpg` in the .htaccess file? Stupid, but possible. – Grim... Aug 15 '13 at 21:05
  • i can tell Apache to serve files with the 2nd letter Z as php if i wanted to, or all files in directory K or files with the date of last friday etc –  Aug 15 '13 at 21:05
  • @Dagon So the file’s name actually *is* the only clue for the web server to distinguish how to handle a file. There is no directive that says “check the file contents instead of its name”. – Gumbo Aug 15 '13 at 21:09
  • no not just name, any of the environment variables are also available. i don't know what point you are tying to make here? –  Aug 15 '13 at 21:12
  • @Dagon My point is that it’s foolish to check just the file’s content as the server doesn’t care about it when deciding how to process the file on a request. Thus your suggestion “file extensions are meaningless” is highly dangerous. – Gumbo Aug 15 '13 at 21:20
  • i (and the 4 upvoters) can but disagree. ;-) –  Aug 15 '13 at 21:22
  • a good post here: http://stackoverflow.com/questions/4166762/php-image-upload-security-check-list – James Aug 15 '13 at 21:29

1 Answers1

0

To answer the question: yes.

But you're in luck, I just wrote this:

function checkImageFileIsImage($filepath) {
    $type = exif_imagetype($filepath);
    $allowedTypes = array(
        1,  // [] gif
        2,  // [] jpg
        3   // [] png
    );

    if (!in_array($type, $allowedTypes)) {
        return false;
    }
    return true;
}

Take a look at http://php.net/manual/en/function.exif-imagetype.php for more file types.

Grim...
  • 16,518
  • 7
  • 45
  • 61
  • Thanks for the answer, but could you provide an example of how my code could be bypassed? It will help me learn more. – John Aug 15 '13 at 21:02
  • Neither John's code nor Grim's is "secure" - http://php.webtutor.pl/en/2011/05/13/php-code-injection-a-simple-virus-written-in-php-and-carried-in-a-jpeg-image/ – symcbean Aug 15 '13 at 21:06
  • @symcbean Thanks, that's interesting stuff. Using GD to make a copy of the image gets around that problem. – Grim... Aug 15 '13 at 21:12
  • @symcbean Although I've tried several different methods and I can't get that exploit to "work". Has it been patched in PHP, maybe? – Grim... Aug 15 '13 at 21:16
  • No it's not a vulnerability in PHP, hence not something which can be fixed by PHP. And you've only been trying for 10 minutes. – symcbean Aug 15 '13 at 21:30
  • I just did this: echo "" >>bad.png original file still loads as an image, but now executes the code when processed with PHP – symcbean Aug 15 '13 at 21:33