Analysis of a Simple PHP Backdoor

Published: 2017-02-28
Last Updated: 2017-02-28 08:25:30 UTC
by Xavier Mertens (Version: 1)
0 comment(s)

With the huge surface attack provided by CMS like Drupal or Wordpress, webshells remain a classic attack scenario. A few months ago, I wrote a diary about the power of webshells[1]. A few days ago, a friend of mine asked me some help about an incident he was investigating. A website was compromised (no magic - very bad admin password) and a backdoor was dropped. He sent a copy of the malicious file. It was quite small (only 5250 bytes) and nicely obfuscated:

<?php ${"\x47L\x4f\x42\x41L\x53"}["\x62u\x6d\x66\x7a\x78"]="a\x75\x74h";${"\x47LOBAL\x53"}["\x71\x70b\x78\x67\x70\x69\x65\x71b\x78"]="\x76\x61\x6c\x75\x65";${"GLO\x42\x41\x4c\x53"}

The file was already uploaded on VT one month ago[2] and had a detection score of 0/54. I decided to have a deep look at the file and to deobfuscate it. Several steps were required:

Step 1 - Lot of characters are replaced by their hexadecimal encoding (\xx).  Such characters can be replaced with a few lines of Python:

f = open(’sample.php')
w = open(’sample-out', ‘w’)
d =
d2 = d.strip()

The result is:

<?php ${"GLOBALS"}["bumfzx"]="auth";${"GLOBALS"}["qpbxgpieqbx"]="value";${"GLOBALS"}["enyputhdlkk"]="key”;

Step 2 - We see that the PHP code makes references to variables using the ${“GLOBALS”} notification[3]. This helps us to better understant the script and we can replace the global variables with their equivalent defined at the beginning of the script:

${“GLOBALS”}[“foo”] = “bar”;

Could be read as:


We can search/replace all occurrences of global variables to make the code more readable.

The last step was to beautify the code to make it human readable. The final backdoor version is available on pastebin[4]. In the code, you can see the $auth variable used to encrypt/decrypt the payload passed to the backdoor. Surprisingly, I found many occurrences of the same string on Google. This reveals that the code is not new and has already been referenced one year ago around July 2015. Practically, what does it do?

Compared to full-features webshell, there are no nice features here. It just accepts PHP commands that are passed to an eval(). Data are passed through a POST HTTP request or cookies. The following arguments must be passed to the script:

‘ak’ is the authentication key, ‘a’ is the command and ‘d’ contains the PHP commands to execute. They are two commands available: 

‘i’ returns the PHP and script versions:

    [ak] => authentication key;
    [a] => i

‘e’ executes the code passed in ‘d’ via eval():

    [ak] => authentication key;
    [d] => system("uname -a");
    [a] => e
Linux shiva 3.8.0-29-generic #42~precise1-Ubuntu SMP Wed Aug 14 16:19:23 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux

What can we learn from this backdoor?

  • Don’t loose time by reversing what has already by performed. Google for some strings in the obfuscated code to find relevant material.
  • Most of them are used by “script kiddies” who don’t even take the time to change the encryption keys.
  • It is not easy to detect with classic log files.

Such backdoor is stealthy and not easy to spot in classic web servers log files: No POST data not cookies are not logged/stored in log files. You can log POST data using modsecurity[5]. You can also search for peaks of POST requests in your log files.


Xavier Mertens (@xme)
ISC Handler - Freelance Security Consultant

0 comment(s)


Diary Archives