Attackers are always looking for new ways to conceal their malware and evade detection, whether it’s through new forms of obfuscation, concatenation, or — in this case — unorthodox use of image file extensions. One of the most common backdoors that we have observed over the last few months has been designed to evade detection by placing the payload in an image file and requiring some additional tricks to unlock it.
In this post we’ll explore how this backdoor works, what sorts of malware we’ve seen in conjunction with it, as well as how to prevent your website from becoming infected.
Contents:
Backdoor analysis
The malware described in this post is not exactly new; we first detected it back in 2019 within a compromised Drupal environment. However, over the last few months it appears to have surged in popularity among attackers.
This backdoor tends to be uploaded into WordPress environments as a bogus/fake plugin with the following names:
./wp-content/plugins/core-stab ./wp-content/plugins/task-controller
In fact, over the last three months alone these fake plugins account for nearly 15,000 separate detections in our malware logs. It is one of the most commonly identified backdoors that we have seen over the last period — and we presume it’s likely bundled into a popular attack-kit used by threat actors to compromise WordPress websites.
The backdoor consists of two files lodged within the following bogus plugin directories:
- ./wp-content/plugins/core-stab/index.php
- ./wp-content/plugins/core-stab/front/front.jpeg
- ./wp-content/plugins/task-controller/index.php
- ./wp-content/plugins/task-controller/application/front.jpg
With the index.php file containing nothing but the following code:
Malware footprint
The footprint of this malware is tiny; all it does is include the front.jpeg file — nothing more. To make it appear more legitimate, attackers have also included the typical fake plugin information pretending to be an official WordPress file.
Although many malicious plugins go out of their way to hide themselves from view in the WordPress administrator interface, interestingly this infection makes no such attempt:
The core-stab and task-controller plugins contain two separate malicious samples which appear to work together to assist attackers in further compromising environments. Before we take a look at each of them and see what we find, let’s briefly explain why they’ve configured their backdoors in this way.
Why bother with a jpeg?
You might be wondering why the attackers bother with this extra step of including the image, rather than just uploading a good old fashioned malicious PHP script or webshell. The answer lies in how many security scanners work.
For performance reasons security scans will often not scan image files by default. Many WordPress websites (especially ones that have been on the web for many years) contain hundreds — or even thousands — of image files and scanning them all would add a tremendous amount of time to a security scan.
Also, image files by themselves are not executable and (generally speaking) aren’t regarded as a risk. For this reason, most standard security scans will focus on the types of files where malware most often tends to reside:
- .php
- .js
- .html
- .htaccess
- etc..
Scanning every single file on the server (including media files, archives, huge log files, sql dumps, etc) is often not feasible, especially when many websites reside in shared environments with limited system resources.
Moreover, the @include found within this backdoor’s index.php file is quite generic and some security scans may not be able to flag it without causing many false positives. Keeping the malicious footprint within the PHP index file as small and generic as possible and placing the main backdoor contents within the image file allows the backdoor to evade detection from some security scans running on default settings.
Nevertheless, this trick will not prevent detection from scanners that consider including PHP code from a file with an image extension — which should be considered a red flag.
Although it’s not uncommon for attackers to abuse file-upload scripts with bogus image files which contain malware this example is a little bit different. Instead of trying to skirt around allowed file extensions they are placing their payload within files which may be missed during some security scans.
core-stab
Now let’s take a look at the malicious plugins themselves. The first (and smaller) malicious plugin “core-stab” includes that front.jpeg “image” file which contains both PHP code and some binary data.
Here we have an obfuscated remote code execution backdoor encoded using a number of different functions: the first and most obvious one being hex2bin (concatenated as “he” . “x2bin”).
When the first array is decoded into human-readable format we can see it’s (ab)using the following functions:
fopen
fseek
tmpfile
stream_get_meta_data
fwrite
stream_get_contents
fclose
__halt_compiler
gzinflate
Since this is a .jpeg file you may be inclined to think that the gibberish in the rest of the file is just fake image data to throw you off. However, in fact it is compressed binary data which actually contains the actual backdoor:
This is how hackers verify presence of the backdoor on infected sites:
35.241.156.161 - - [12/Jan/2023:22:56:48 +0300] "GET /wp-content/plugins/core-stab/ HTTP/1.0" 404 58553 "https://<redacted>/wp-content/plugins/core-stab/index.php" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36"
task-controller
The second malicious plugin is a lot more interesting and still makes use of the same bogus image inclusion in the index file.
Upon inspecting the image file we see the same hex2bin-encoded array used except with a lot more encoded binary data:
Once extracted we can see there’s a lot more to work with:
One very interesting chunk of code near the bottom of the file, once decoded, looks like this:
But why is it there and what is it doing?
There’s a couple of key features in these decoded contents: It appears that the code first, and by default, pretends that the page doesn’t exist so it shows the 404 Not Found message and nothing else. The <body oncontextmenu=”return false”> tag makes it impossible to use the right-click context menu to view the HTML source code of the page. In addition, it blocks keyboard shortcuts to work with clipboard and CTRL+U to open the current page’s source code.
What’s the point of the backdoor that only pretends to be a 404 error page? There should be some secret to it.
Indeed, the script also specifies that if the user is holding down the “CTRL” key when they click on the web page it will write a form which requests a text input with the name _us (different versions of the backdoor have different names) with a submit button.
We can confirm this by accessing the index.php malicious plugin file directly. Here’s what it looks like when accessed normally:
It returns a “404 Not Found” page. However, when we hold the CTRL key on the keyboard and click our left mouse button, look what we get instead:
Here is our secret “konami code”! We now have a login prompt to what is likely a malicious webshell. The input value in the form is used to decrypt the second part of the backdoor to proceed further.
Other variations of the backdoors
It’s worth mentioning that these backdoors do not always load additional code from image files. At some point all the PHP was in the same index.php file. In addition to the core-stab and task-controller, the attackers also used fake plugins with names: core-builder , lite-cache , core-engine.
For example, the simple core stab backdoor used to look like this (we still find this variation in the wild):
Furthermore, the “konami code backdoor” is also not always placed as fake WordPress plugins. There are many alternative locations and filenames for it, including but not limited to:
- wp-frame.php
- wp-admin/menu-cron.php
- wp-admin/about-core.php
- wp-admin/field.php
- wp-admin/includes/update-core.php
- wp-admin/images/class.api.php
- wp-includes/css/update.php
- wp-includes/js/index.php
- wp-includes/js/themes.php
- wp-includes/images/update.php
- wp-includes/Text/Diff/type.php
- wp-admin/images/themes.php
- wp-content/viewer.php
- wp-content/plugins/gp-premium/hooks/functions/engine.php
- wp-content/plugins/contact-form-7/includes/block-editor/data.php
- wp-content/plugins/wordpresss3cll/viewer.php
- wp-content/themes/twentytwentythree/styles/load-settings.php
- wp-content/themes/documentation/bridge/module.php
- image/module.php
- rest-api.php
- class.api.php
- app.php
What next, and how do I protect my website?
The backdoors discussed in this post are most closely associated with the NDSW/NDSX malware that serves SocGholish fake browser updates. The coding style of these backdoors are very similar to the PHP component of the NDSW malware. Indeed, we often find them together.
On the other hand, for such a massive malware campaign as NDSW/NDSX (one of the top detected malware in 2022) it is not uncommon to see sites infected with different types of malware at the same time. This results in detections for multiple different backdoors and payloads belonging to different attacks and campaigns on the same site — making it difficult to tell for sure which attack created what.
As for how the attackers are able to compromise the websites: Modern attackers do not limit themselves to one single vulnerability or attack vector. Their tools are largely automated and look for any and all known vulnerabilities to compromise websites with. Compromised wp-admin panels are also a very common cause of website infection, though, and once an attacker has admin access they can do just about whatever they want, including installing sneaky malicious plugins like the one described here.
For these reasons we always recommend that website owners practice defence in depth: Take every possible precaution to stymie the attackers’ ability to compromise your website. Although, keep in mind that each layer of security can sometimes cause inconvenience for the website owner. You’ll need to use your judgement to weigh the security needs of your organisation with the level of inconvenience that may be caused.
Mitigation steps
If you operate a WordPress website and want to protect yourself from attacks you can take the following precautions to help mitigate risk:
- Keep your website fully patched and up to date
- Use 2FA for improved access control on your administrator panel
- Use strong and robust passwords
- Place your website behind a firewall for proactive security
- Review even more hardening measures for your WordPress website here
If you see “core-stab” or “task-controller“ show up in your wp-admin list of plugins then this is definitely a sign of compromise. You can follow our how to clean up a hacked website guide for step by step instructions on removing backdoors and other malware.
But if you need assistance cleaning up an infection on your website — we’re here to help!