Detecting Hidden Backdoors in PHP OPcache

Share this…

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.


Dangerous index.php.bin

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 thatcurrent 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 helpfind (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.

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  :

OPcache Malware Hunter
OPcache Malware Hunter

If a potentially infected file is found, the malware hunter will generate an HTML report containing more information.

Potentially infected files
Potentially infected files

Browse to the generated hunt_report folder and open the index.html  page :

Main report page

Clicking on any link will open the report for that file showing the differences between the original file and the potentially infected file :

Example report
Example report

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

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.

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 :

Syntax tree extract
Syntax tree extract

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.

Pseudocode extract

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:

Disassembled classes and functions

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:

Original Source Code


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.