php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #37467 PHP Payload in JPG Exif Header is Executed by PHP
Submitted: 2006-05-16 21:25 UTC Modified: 2006-05-16 22:11 UTC
From: paul at castlecops dot com Assigned:
Status: Not a bug Package: EXIF related
PHP Version: 4.4.2 OS: Linux
Private report: No CVE-ID: None
 [2006-05-16 21:25 UTC] paul at castlecops dot com
Description:
------------
Affected Versions: PHP 5.1.4 and 4.4.2
The PHP server evaluates code inside a technically valid JPEG's technically valid Exif header.  It'll evaluate it even if exif is not compiled into PHP.

Reproduce code:
---------------
I need to attach it.

Expected result:
----------------
The POC jpg will write a file to the filesystem and include whatever PHP code there is.  Anything is possible given the permissions of the web server.

Actual result:
--------------
The POC jpg will write a file to the filesystem and include whatever PHP code there is.  Anything is possible given the permissions of the web server.

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2006-05-16 21:29 UTC] tony2001@php.net
Thank you for this bug report. To properly diagnose the problem, we
need a short but complete example script to be able to reproduce
this bug ourselves. 

A proper reproducing script starts with <?php and ends with ?>,
is max. 10-20 lines long and does not require any external 
resources such as databases, etc.

If possible, make the script source available online and provide
an URL to it here. Try to avoid embedding huge scripts into the report.


 [2006-05-16 21:32 UTC] paul at castlecops dot com
I have discussed this issue with Nir Yariv and Nora@Cali from Zend and was asked to open a report.  Further information can be obtained from them including the JPG poc.  Firewall companies and ISPs are already denying this JPG poc transmission across its networks.

I repeat: exif functions are not required, nor is exif required to be compiled into PHP.  It can be entirely disabled.  getimagesize() doesn't flag this file as false because it is a valid JPEG.  The Exif header in it are also valid.

PHP should not permit itself to process PHP payloads inside JPEGs (or TIFFs for that matter as these both allow Exif).

The original article that had something to do with this is found at techworld:

www.techworld.com/security/news/index.cfm?NewsID=3514

A followup POC is also available here:

retrogod.altervista.org/phpbb_2020_admin_xpl.html
 [2006-05-16 21:34 UTC] paul at castlecops dot com
@tony2001:

Nir should have a copy I emailed him.  Please let me know your email so I can send a copy immediately.
 [2006-05-16 21:43 UTC] pajoye@php.net
Paul, we do not know Nir neither Poc. We are php.net, not Zend.

Now, if you want us to help you to fix this problem, we need:

- a short PHP script to reproduce your problem (using only 
  the image and exif functions)
- a set of images

Please reopen this bug only if you provide these two things. If you can't provide them, leave it bogus and ask Nir to explain you what we need. Thank you.
 [2006-05-16 21:43 UTC] tony2001@php.net
Please provide short and complete reproduce script.
20Kb exploits, which are actually exploits for some particular application, not PHP itself, aren't really useful and do not prove anything.

>Nir should have a copy I emailed him.  Please let me know 
>your email so I can send a copy immediately.

My email is tony2001@php.net.
 [2006-05-16 21:48 UTC] paul at castlecops dot com
Tony I have sent you the jpg poc just now.  I can post the PHP code that generates the JPG, but that is 76 lines. The bulk of that code which generates this payload jpg uses chr().
 [2006-05-16 21:50 UTC] paul at castlecops dot com
@pajoe: "Paul, we do not know Nir neither Poc. We are php.net, not Zend."

"Poc" is proof of concept.  I suspect you meant Nora?  Tony should now have the jpg poc.  Open it in notepad to see the PHP code.  If you read the exif headers, this is what you'll see:

 FILE.FileName: phpJ4OyEi
 FILE.FileDateTime: 1147625054
 FILE.FileSize: 552
 FILE.FileType: 2
 FILE.MimeType: image/jpeg
 FILE.SectionsFound: COMMENT
 COMPUTED.html: width="1" height="1"
 COMPUTED.Height: 1
 COMPUTED.Width: 1
 COMPUTED.IsColor: 1
 COMMENT.0: "); fclose($fp); chmod("suntzu.php",777); ?>
 [2006-05-16 21:57 UTC] tony2001@php.net
I don't have the image because of this:
unzip 128jpeg.zip
Archive:  128jpeg.zip
   skipping: 1287789650446751fbaed81.jpg  unsupported compression method 99

But anyway this is bogus, since the file contains VALID PHP code and PHP has no reasons not to execute it if it was include()'d. Fix your code.
 [2006-05-16 22:01 UTC] paul at castlecops dot com
"Fix your code"?

You have got to be joking.  The PHP code inside the jpg I sent you is a "PROOF OF CONCEPT".  PHP executes the code within this JPG and _creates_ a file on the filesystem.  Hackers are going to love this as a foothold to gain entry to a machine.

How is this not a PHP issue?

Also I have resent to you a link to the raw jpg.  Please grab it so I can remove it.
 [2006-05-16 22:02 UTC] paul at castlecops dot com
May I also add, "my code" isn't affected.  Several PHP web based applications (for forums, galleries, wiki, etc) are affected by this.  I have made contact with these vendors and some have reported it isn't their problem but PHP's.  If you aren't going to fix the processing of PHP code inside JPEGs...
 [2006-05-16 22:05 UTC] paul at castlecops dot com
And one more afterthought:

"since the file contains VALID PHP code and PHP
has no reasons not to execute it if it was include()'d."

That's just it. A JPEG is an image, not an executable PHP page.  PHP pages are typically "html" or "php", and not JPEG.  A hacker would work on uploading the JPEG to a server and then thru nefarious means try to get that servers PHP to execute the JPEG which would lead to compromise.

JPEGs are images, not PHP payloads.
 [2006-05-16 22:11 UTC] tony2001@php.net
Try this:
Create a "file.<some undefined extension>", put in there:
----
blah<?php phpinfo(); ?>
----

include() it from some another PHP script.
Name me at least one reason why this file is not valid and should not be executed. Binary data? Well, Unicode data is not ASCII also. .jpg extension? Since when PHP checks the extension? Or do you think .inc is not a valid extension?
The code is perfectly valid and PHP does what it used to do: executes it.

It's your fault that your application executes data from user input, not PHP.
Hence bogus.

 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Tue Apr 16 17:01:30 2024 UTC