As 2020 continues to be the worst year in almost anybody’s lifetime, allow me to take this opportunity to stoke the fires of your existential dread even further. As a sequel to my last blog post earlier this year about the credit card swiper that I found on a WordPress ecommerce website using WooCommerce, today I found another very noteworthy infection of the same variety.
Credit Card Skimmer in /facebook-for-woocommerce/
The story starts the same way it always does: The client notified us that their customer’s credit cards were being compromised shortly after using their website to purchase a product. After our initial scans came up clean, it was time to do a deep dive into the website files and database to see what I could find.
As is customary in such cases, my first step was to run an integrity check of the core files, plugins, and themes. The only obviously questionable file was a script called login.php in the site root, which does exactly what you would expect:
This by itself would of course not cause any such credit card compromise, unless the client was storing their customer’s payment data in plain text in their database (which, incidentally, is something that I came across on another website recently, but that’s another story altogether). Nothing else jumped out at me, until my colleague and fellow security analyst Hemã noticed the following file come up in the plugin integrity check:
./wp-content/plugins/facebook-for-woocommerce/facebook-for-woocommerce.php
cURL Used to Send Compromised Payment Details to Russia
Running a diff check against a fresh copy in the WordPress plugin repository, we noticed that there is a lot of code that definitely does not belong. Let’s take a closer look at the injection and check out exactly what it’s doing.
The first thing that I noticed was the usage of the strrev function in PHP, which reverses a string or the contents of a variable. What that results in is line 72 returning /options/ and line 95 returning https://localhostnametable[.]com — our exfiltration domain where the payment details are transferred to via cURL to servers hosted in Russia). The file also contains hard-coded references to the compromised website (which we have blurred out for obvious reasons).
This file ended up taking me down a very deep rabbit hole and uncovered quite a few additional new samples for our research team.
JavaScript Injections & Obfuscation Techniques
Before I continue, I’d like to point out that the attackers have been using a clever tactic to hide their malware in some of these cases (this is not the first time I have seen this, nor will it be the last). Most injections are quite obvious to spot and frequently will show up on their checkout page as javascript. It’s also very common for JavaScript injections to utilise the atob JavaScript method to obfuscate themselves, but again, this is also very easy to spot.
Malware injected directly into the PHP files, on the other hand, does not show up externally on the website — neither on the checkout page nor anywhere else — rendering it a little more tricky to track down. Moreover, if the attackers do the obvious thing and infect the WooCommerce plugin files directly then remediation would be trivial (just reinstall WooCommerce). But in this case, all the infected files have been planted in plugins that were not directly related to the checkout process.
Given that the above malware used the strrev function to obfuscate its functionality, it behooved me to check to see if the attacker had used this tactic elsewhere. Sure enough, querying the files for strrev yielded six more new pieces of malware. Most (but not all) of them were injected into plugins from the open source WordPress repository. Since Automattic (the parent company of WordPress) strictly forbids the use of obfuscation in the repository, it was an immediate and glaring red flag to see that function scattered throughout the files.
Malicious Payloads Found in Other WordPress Plugins
Let’s take a look at some of the other malware that was found on the compromised website.
Another injection using the same domain, but in this case it appears to be siphoning off login details. This gives them more chances of keeping their malicious code in the website, while making it harder to detect, clean, and protect it against potential updates that could take place on some plugins.
Series of Backdoors
This injection hides the use of wp_set_auth_cookie and wp_set_current_user and acts as a backdoor of sorts.
Interestingly, we can see the strrev function being used to hide added_to_cart_product_tab as well as administrator, get_users, and wp-load.php which seems to try to grab the administrator users and also acts as something of a backdoor.
There were a couple other injections using strrev but you get the idea so far.
Not wanting to dispel the possibility that there might be malware injected that didn’t use the strrev function, I decided to use a little old-school trick that we discuss in our guide on fixing a hacked WordPress site: checking for recently modified files.
Backdoors Concealed among Plugin Updates
I checked the last modified date on some of the malicious injections that I had already removed and it seems that they were all listed as having been modified roughly three and a half months ago (this might seem like a while for a credit card swiper to go unnoticed, but you’d be surprised how common this is). So the next obvious step would be to gather a list of all files modified in this time period.
As you can imagine, the list was long, but it’s actually very easy to spot instances of plugin and theme updates since they are conveniently grouped together.
After removing all of the obvious instances of component updates, it led me to eventually come across this malicious snippet of code:
Yet another administrator user backdoor.
Most attacks that we see against WordPress websites are opportunistic attempts at grabbing low-hanging fruit. The malware is often all in one line, looks very sloppy, and is injected at the very top or very bottom of files (since that is much easier).
This particular injection, however, seems purpose-built for this website, and the hard-coded values found peppered in the files supports this conclusion. The attackers clearly put some time into the malicious snippets and its placement within the files. Everything was nicely formatted and easy to miss if you were just taking a quick glance over the code. There were also enough instances of multiple payloads and backdoors that it would have been very easy for them to reinfect the site had only a couple of these injections been found and removed.
Conclusion & Mitigation Steps
2020 appears to be the year of the credit card swiper, and more and more of this malware seems to be targeting WordPress.
If you are an ecommerce store owner, be sure to have your website placed behind a firewall, disable file editing from wp-admin, use long and complex passwords, and employ file integrity monitoring. To further harden your environment and mitigate risk, you can also restrict your admin panel with 2FA or some other additional protection, avoid hosting other websites in the same environment (due to cross-site contamination) and — most importantly — always keep your plugins and themes up to date with the most recent versions.