This is from September of 2015. It's a honey pot capture I had saved because it looked interesting, but I did not look at it in detail until July, 2019. It has a Vigilante Software Cleaner cookie in it.
The IP address isn't worth looking at 4 years after the capture, but the method of transfer is.
The attacker(s) used the URL http://stratigery.com/wp-content/themes/twentytwelve/marsel.php
,
a URL accessed 1187 times between 2015-09-18 and 2018-09-24, by 320 distinct IP addresses.
The HTTP request comes with HTTP parameters named "a" and "p1", and a cookie with name "d8670190bc460b6abebf276d20db5892". The parameters are typical for an access of an instance of Web Shell by oRb, the most common web shell. The cookie's name is the MD5 hash of the host name used in the URL, "stratigery.com". The cookie's value of "63a9f0ea7bb98050796b649e85481845", is the MD5 hash of the string "root", a common enough WSO password. An attacker used that cookie value as late as 2019-07-18T09:30:29.742-0600, the day before I write this.
The request arrived with an extra cookie with name and value of "227e948fdbaaeccbbb7b3f42fbe848e8". This is the cookie that code the Vigilante Malware Cleaner would install on any WSO instances it found on stratigery.com. This is the earliest honey pot request I've still got that has such a cookie. It appears that the Vigilance Committee was doing its work in mid-2015, and potentially selling WSO web shell access to other people.
The "a" HTTP parameter has a value of "RC", which will invoke immediate PHP code eval in WSO instances version 2.2 and up. Note that my honey pot caught an instance of WSO version 2.1 as late as March 2018, so there's really no guarantee that a given WSO installation will support "a=RC" immediate code eval.
The HTTP parameter named "p1" should contain PHP code for WSO to eval, and it does.
The HTTP request carried a file download as well as the HTTP POST data. This suggests a programmatic access of the URL.
The file would have gotten uploaded as "scenery_4.jpg".
The code uploaded for eval is barely obfuscated at all,
only having a wrapper of eval(gzinflate(base64_decode("7X1...");
The Linux file
command reports this about the "image" file:
JPEG image data, JFIF standard 1.02, resolution (DPI),
density 180x180, segment length 16,
Exif Standard: [TIFF image data, little-endian, direntries=13,
manufacturer=Canon, model=Canon EOS 300D DIGITAL,
orientation=upper-left, xresolution=199, yresolution=207,
resolutionunit=2, software=Adobe Photoshop CS Windows,
datetime=2004:10:26 18:28:42]
It's not an image file, despite having a JPEG header. No image viewer I tried would render it, all claiming that it had various errors.
The "image" file that would have been "scenery_4.jpg" is actually Xor-encoded bytes of a serialized PHP array. The code uploaded for eval would have trimmed bytes between two markers, each marker a 2-byte value, 0xffda for start, and 0xffd9 for the end marker. Those are "start of scan" and "end of image" JPEG markers, apparently.
The Xor-encoding key bytes are the ASCII values of the string
stratigery.com/wp-content/themes/twentytwelve/marsel.php
.
The attackers seem to have used an Xor-key individualized for each
site they attacked.
I edited function type1_send()
in the immediate-eval-code to obtain decode the image file,
a small program that decodes the data in the image file,
and prints it out.
This seemed like the easiest way to obtain the decoded bytes.
The attacker(s) obfuscation left their original code intact: they did not rename variables, eliminate extraneous while space, or any of the other methods that attacker(s) use to obscure their code and its function.
We see consistently "snake_case" named functions and variables. The code looks good, but has both ASCII space and ASCII tab indentation. It mostly has Unix-style newline line endings, but a few stray carriage-return characters appear. This indicates that a lot of cut-n-paste programming went on, but the programmer took some care to make the pasted code appear consistent.
The code includes 3 object-oriented class definitions, classes PHPMailer, phpmailerException and SMTP. This code is obviously borrowed. Class SMTP 5.2.10 dates to May, 2015, consistent with the date of this attack.
I give this code a grade of B - workmanlike, and solid. It's consistent with the way PHP is usually deployed, built on a foundation of utility classes and code.
The deobfuscated data looks like this:
array(6) {
["e"]=>
array(1) {
["#fec691067cad63a1f115c5d21f8c01bb#"]=>
string(27) "[email protected]"
}
["f"]=>
array(1) {
[0]=>
string(48) ""Desiree Nichols" <[email protected]>"
}
["ak"]=>
string(10) "[AUTH_KEY]"
["lt"]=>
int(1)
["l"]=>
string(247) "<html>
<body>
{well|oh} {hello|hey|hey there|hello there} {mister|sir|cutie}{,|..|...} if {your|you're|ur} {single|still single|willing|up to it|down for it} and {free|avail|available|around} we {could|can} meetup for fun?? [FTEIL]
</body>
</html>"
["s"]=>
array(1) {
[0]=>
string(4) "info"
}
}
Pretty clearly some email spamming material, a fake from address, a destination address, and a template to customize the email body.
There's a problem in the spamming code. Looks like a cut-n-paste got done twice. The file(s)-accompanying the download get processed twice, once without actually decoding them, near the beginning of the code, and a second time twoards the bottom of the code. My guess is that encoded-accompanying-files are a later add-on. Originally the "image files" contained only the template for spam email's bodies.
The spamming code gets eval'ed by the destination WSO instance.
The looks through any files that arrived along
with the POST request.
If the files have ".jpg" in their file name,
the spamming code uses the accompaying file(s) as data,
passing the file name to function type1_send()
,
which is the "business logic" of this malware.
After decoding and deserializing the data in the "image file",
function type1_send()
checks the value of the key "ak"
in the deserialized PHP array.
Above, you can see that 'ak' has the value "[AUTH_KEY]".
type1_send()
checks if this is present, and does not proceed
if it isn't.
It checks the data to see if some entity has "authorized" the spam.
There may be a problem with the code if the deserialized array has a key named 'c'
in it. It looks like it would try to serialize and base64-encode an array named $res
which is not mentioned otherwise in type1_send()
.
This looks like stray code left behind during a refactor.
The data sent along in this capture didn't include a key named 'c', so it probably would have worked.
After that, function type1_send()
creates an email from
the data in the deserialized array.
Array key | Meaning |
---|---|
e | "uid", To address |
s | Array of email Subject strings |
l | message body template |
f | Array of From addresses |
lt | text or HTML email selector |
The "macro expansion" gets run over email subject, body and from address
function alter_macros()
- partially create string by choosing from alternative phrases. The above data could end up with a partially filled in string like this: oh hey cutie... if you're still single and free we could meetup for fun?? [FTEIL]- Insert a random number if substrings like
[RAND-12-45]
appear. The random number should be between 12 and 45 in this case. - Insert another random number if substrings like
[NUM-5]
appear. I believe that substring would put a random number between 1000 and 9999.
The message body gets one more substitution:
The substring [FTEIL]
gets replaced by the "uid",
in this email data, the string "#fec691067cad63a1f115c5d21f8c01bb#".
function type1_send()
returns a serialized array that contains any SMTP erros,
and a count of "good" and "bad" emails, where "good" emails did not cause a problem
in the code of function sendSmtpMail()
.
This has all the features we've come to hate over the years:
- A randomly-chosen email body that has a come-on in it.
- An obviously wrong "from" address
- Randomly-chosen strings of digits, probably in an attempt to pass signature scanners and such.
This particular email seems odd in that it isn't advertising anything. No URLs would appear in the email body. Based on the body template and the "from address", the senders probably intended this email as a cold-call, an introduction to see who they could get to respond to it, and then try to get cash from those responders in other ways.