Friday, August 3, 2007

'Safe' remote file inclusion

As mentioned in my previous post: "PHP Image uploaders", It is possible to embed PHP code in a normal jpeg image. With the valid extension this will upload in any image upload script. It will be treated like any normal image. The embedded PHP code will stay untouched unless the image is resized or pulled through imageMagick / GDlib for any reason. These libs will not trigger any errors, they just strip of the excess data (meaning the embedded PHP code ;)

When executing or including these PHP files. The image data blob will be printed to the screen, this is slightly annoying.. but the PHP code will also be executed. Some black hat readers might see the opportunity here. When you find a remote file inclusion, and you want to inject some PHP code, its often tricky to host in on:
1. Your own server
2. A 'hacked' server (which i don't know anything about)

So a simple option might be: write your PHP script, embed into a jpeg file, and host it on any open image upload server. I tested it on imageshack, and it seems to work there. The only requirement is that the file should not be resized or changed in any way.

After this you can include the .jpg file. And the PHP code embedded in the image will be executed.

Here is a simple test you can run:
Get your favorite image.. called image.jpg and go a little something like this:
$ echo "< ?php phpinfo(); ? >" >> image.jpg
$ echo "< ?php include('image.jpg') ? >" > test.php


Now open test.php in your browser, and behold! phpinfo() output.. with a bunch of nasty binary characters above it.

Here is a demo file containing phpinfo(): http://img258.imageshack.us/img258/3822/gnarfmh9.jpg

3 comments:

Anonymous said...

Thanks for this post. It made me research a bit with a small system used at many universities in germany: http://user.informatik.uni-goettingen.de/~jagricol/hacks/studip/imageproxy/

johannes

MagicalTux said...

Another way to do that is to write a file that looks like an image.

Example:

echo "GIF89a< ?php phpinfo(); ? >" >file.gif

php > var_dump(getimagesize('file.gif'));
array(6) {
[0]=>
int(16188)
[1]=>
int(26736)
[2]=>
int(1)
[3]=>
string(28) "width="16188" height="26736""
["channels"]=>
int(3)
["mime"]=>
string(9) "image/gif"
}

You get the idea... checking if a file is really an image with getimagesize() is useless.

Viper-7 said...

How about, just don't do something stupid like using include to output an image...

PHP has readfile() which will output the file's contents without interpreting the data, and better yet, you should look into X-SendFile which lets you instruct your webserver to send a static file (which may be outside your webroot) to a client.

No PHP code will be processed with either of these methods.