On December 1, 2023, several security researchers reported about a new phishing campaign targeting WordPress administrators.
WordPress sites owners had started receiving emails from WordPress.com with the following message:
“The WordPress Security Team has discovered a Remove Code Execution (RCE) vulnerability on your site, which allows attackers to execute malwares and steal your data, user details and more …”
They urged webmasters to “immediately use the CVE-2023-45124 Patch, a plugin launched by the WordPress Team”.
A link in the email leads to a website that looks like the official WordPress plugin repository. The plugin page reiterates that there is a critical vulnerability and they need to download and install this plugin to patch “the security hole that allowed unauthorized code execution”.
However, as you might expect, the downloaded plugin doesn’t actually patch anything. On the contrary, it creates a malicious administrator and backdoor.
In this post we’ll analyze this attack from lure emails to the fake plugins and provide information on what has changed after the initial reports from Randy McEoin, WordFence, and PatchStack when the attackers switched from CVE-2023-45124 to CVE-2023-46182.
Contents:
CVE stands for Common Vulnerabilities and Exposures. It’s a list of publicly disclosed security issues where each vulnerability has a unique id. The id format is CVE-<year-of-disclosure>-<unique-number>.
The phishing email mentions CVE-2023-45124 (and later CVE-2023-46182). Are these vulnerabilities real? Well, you can check it on CVE.org site: https://www.cve.org/CVERecord?id=CVE-2023-45124.
This page says that such a CVE indeed exists but it is “reserved” and the details are not public. CVE-2023-46182 is also currently in the “reserved” state. It means that someone discovered a vulnerability and reported it to a CVE Numbering Authority (CNA) but the details will be published later (for example, when the vendor acknowledges the vulnerability and creates a patch.)
So, this part of the email potentially sounds legit. It looks like WordPress is trying to mitigate the issue before it goes public. Right? Not so fast.
The CVE does exist but we can’t tell what product it relates to. Hypothetically, it can be WordPress, but as easily it can be any other software product from operating system to some tiny component of relatively unknown CMS.
And apparently, attackers have decided to exploit the “reserved” status of CVEs that can be easily found in the registry by simple enumeration.
Most phishing emails (including this one) are not expected by the recipients (which is usually the first sign of phishing).
These particular emails seem to be quite generic and lack any personalization. They don’t mention names and site addresses. (Also a sign of phishing).
According to @rmceoin, the subjects vary from email to email and contain wording that create sense of urgency (another sign of phishing):
The email itself also has this language: “… we urge you to immediately …”
Yet another sign of phishing is style and grammar errors. You can immediately see “WordPress” is spelled without capitalization of “P” which is considered a misnomer in the WordPress community. The core wp-includes/formatting.php file even has a function capital_P_dangit() that automatically changes incorrectly capitalized spelling to “WordPress”. Additionally, the word “malwares” may be acceptable when your grandma talks about problems with her computer, but the WordPress Security team knows that this word is uncountable.
Fake “from” address. While the display part of the “from” address “WordPress.org” (which I doubt is ever used by real WordPress) looks legit, the actual address is no-reply@mail-wordpress[.]org (alternative domains: @email-wordpress[.]org or @webmail-wordpress[.]org). These domains contain the “wordpress.org” part but they don’t belong to WordPress.org. They all were created on November 27, 2023 at exactly the same time.
And as with every phishing email, this one also has a call to action. In this case it’s a big “Download plugin” button, which opens a shortened Bitly link that hides the actual destination (another sign of phishing). The “unsubscribe” link leads to the same bit.ly address with an added #unsubscribe anchor that doesn’t change anything.
Now, let’s check what happens if someone finds the phishing email plausible enough to click on the “Download Plugin” button.
If you add + at the end of bit.ly links, you can get some basic information about the link. Here’s the link that Randy McEoin shared on Mastodon.
We can see that the link was created on Nov 29, 2023, just two days after the registration of fake WordPress email domains.
It leads to hxxps://en-ca-wordpress[.]org/plugins/human-verification-challenge/3rx1ow9?continue.
Again, the domain name ends with “wordpress.org” which should give it credibility. En-ca is the language code for Canadian English. And the real wordpress.org site actually localizes experience for visitors from different countries. Canadian visitors are redirected to en-ca.wordpress.org which is only one character different from the phishing en-ca-wordpress[.]org so this looks like a clever choice of a domain name.
To capitalize on this idea, this attack uses domains for 6 English language locales:
In addition to that, attackers also use:
Most likely related Unicode domains:
The actual location of these sites is hidden by the CloudFlare firewall.
Analysis of these bit.ly links reveals that the campaign utilizes multiple shortened links pointing to each of these domains. All of them were created within a few minutes on November 29, 2023 and were randomly used during the same wave of the attack on December 1, 2023.
This approach is supposed to help sustain the activity of the campaign past possible blocking of individual shortened links and phishing domains.
The malicious sites are quite interesting. First of all, Bitly links in the phishing emails open a special “/plugins/human-verification-challenge/xxxxxxx?continue” URL with the hCaptcha challenge.
If you open any other URL without visiting this page first, you’ll get redirected to the blank “plugins/human-verification-challenge/invalid” page.
This helps prevent discovery of the phishing pages by bots and researchers who only know the domain names.
For real human visitors, this page pretends to belong to “wordpress.org” that is “checking if the site connection is secure“ (mimics the older versions of CloudFlare hCaptcha challenge). In addition to CAPTCHA, this page also contains a statcounter script to get some analytics on the site visitors.
Once the CAPTCHA is solved, visitors get redirected to the “/plugins/cve-2023-45124/” page that looks like a typical plugin page from the official WordPress plugin repository.
Note, that while the URL says CVE-2023-45124, the page mentions CVE-2023-46182. The attackers had updated the CVE id in the HTML code but forgot to change the URL.
Let’s see what other interesting and suspicious details we can find here.
On the page we can find multiple attributions of this plugin to the WordPress team (although again without correct P capitalization).
It’s developed “By WordPress ✓” with a check mark, as if it’s a verified account (there’s no such thing actually). The plugin icon is also a WordPress logo with the “verified” check mark.
Above the metadata we can see a section stating:
“Official Plugin
This plugin is an official release from WordPress”.
No other plugin in the repository has this status. Even the Classic Editor plugin whose description says that it’s “an official plugin maintained by the WordPress team” has a “Community Plugin” status, not “Official plugin”.
At the bottom of the description we find another “Brought to you by WordPress ✓”.
Of course, such attribution should immediately make it look trustworthy. So does other fake data in the right sidebar such as 500,000+ installations in the last 2 days and the 5 star rating.
On the description page we can see the FAQ and Contributors & Developers sections:
Both sections appear to be slightly trimmed copies of the Jetpack plugin sections, where the bad actors replaced “Jetpack” with “WordPress Patch CVE-2023-46182”
The same happened to the “Reviews” section:
These are not fake reviews from fake users. These are real reviews of the Jetpack plugin made by real users. On the phishing sites, these real reviews are just modified to say “Wordpress” instead of “Jetpack.”
Jetpack was not the only inspiration for the phishing plugin pages. The Development tab contains Changelog that represents three random items taken from Wordfence changelog.
The Changelog date is not real. It is dynamically changed to “two days ago” using this JavaScript:
There are many other minor glitches that can tell that the site is not real. For example, the top menu doesn’t match the current version of the top menu on WordPress.org.
Once you download the .zip from the phishing site and install it, you still need to activate it in the Plugins tab of the WordPress admin interface.
When you click “Activate”, the Patch tab is created and you get automatically redirected there.
This Patch tab informs you the “CVE-2023-46182 has been patched successfully” and if you return to the Plugins tab, you will not find the “Wordpress Patch CVE-2023-46182” plugin there. One might think that it makes sense since you no longer need this plugin once the “patch” is installed.
However, this is just a visible part of this plugin behavior. The invisible part is quite different.
The malicious plugin consists of three files:
WordPressPatch.php creates the Patch menu in the WordPress Admin Interface.
The comment at the top reveals that it was created using the tutorial on the CreateIT site.
Security.php is an HTML page that the “Patch” menu loads.
All it does is add some fade-in visual effects to gradually show the “CVE-2023-46182 has been patched successfully” message. No PHP code whatsoever, thus no actual patching of WordPress.
So far this plugin looks like benign snake oil. However, the real nastiness is hidden in the main plugin file wpress-security-wordpress.php.
Its metadata attributes the plugin to www.wordpress.org and describes it as a patch for CVE-2023-46182. So far, so good.
Below we see that wp-head action is assigned to the InitScan function. It means that the plugin is going to scan something every time any site page is being generated. Can this be the way the patch works?
In the InitScan function we see that it actually expects some GET parameters from the visitor.
The “uppll” parameter initiates the installScanner() function and the “scan_admin=1” initiates the scanAdministrators() function. That’s getting suspicious.
When we inspect these functions, we realize that what they actually do is upload a backdoor and create a malicious admin user.
The initial version of this plugin uploaded the wp-autoload.php webshell and the malicious administrator with the login wpsecuritypatch.
Recent versions have adopted a more elaborate and less predictable naming convention for files and usernames.
The function with the misleading name getTemporaryPrivileges creates a string based on the base64-encoded first 7 characters of the SHA-256 hash of the siteurl. This string is used as the username of the malicious admin user. While it is still possible to calculate this username, it is significantly less predictable than the previously used wpsecuritypatch.
To generate the backdoor filename, the plugin uses another function with a misleading name getScannerName()
function getScannerName() { return strtolower('wp-'.getTemporaryPrivileges(getTemporaryPrivileges()).'.php'); }
It uses two getTemporaryPrivileges functions in a row. The result of the first one is used as a salt of the hash in the second one, which makes the result even less predictable.
The filenames will depend on the actual URL specified as the WordPress siteurl. Just a small change in the URL will produce a completely different filename. Here are some examples of the backdoor filenames, for common variations of the same site URLs.
In all variants the filename begins with wp- followed by 10 random characters. This file is uploaded both into the plugin directory and into the site root directory.
The base64-encoded source code of the uploaded file is fetched from a third-party site: hxxps://wpsrv[.]zip/runscan. It’s a so-called “P.A.S. Fork v. 1.3 Shell” — a full featured web shell whose previous version we described in this blog post. It is used by multiple attackers. This year alone, we’ve removed this webshell from over 225,000 files on compromised websites.
Another interesting function is wpress_plugin_activate() which is executed when the plugin is activated.
The purpose of this function is to install the backdoors immediately upon plugin activation and report it back to the attackers. The report is sent using the GET request to hxxps://wpsrv[.]zip/wpapi?siteurl= along with the following base64-encoded data:
Instead of the wpgate[.]zip site, the plugin may interchangeably use one of these domains
To appear more legitimate, at the end of the plugin activation process the wpress_plugin_activate() function redirects the user to a fake “patched successfully” page created by the security.php file.
As we already mentioned, once you activate the malicious plugin you will no longer be able to find it on the “Plugins” page of the WordPress admin interface. You won’t find the malicious admin user on the “Users” page, either.
Plugin functions WP_BD($user_search) and WPS_Plugin() are responsible for this behavior. These functions are attached to the pre_user_query and pre_current_active_plugins action hooks respectively and filter out the malicious user and the fake plugin from the lists before WordPress displays them.
This self-concealing behavior is typical to all sorts of fake plugins that we find on compromised websites. This year alone we cleaned over 2,000 files that hide malicious admin users in WordPress admin interface (most commonly found in functions.php of the current theme or in fake plugins like wp-update, 10web-manager, wp-tech-support, wp-zexit, etc).
As it happens with most large scale phishing campaigns, soon enough, most of its malicious domains were blocked by security providers and were reported to CloudFlare who eventually blocked them.
Some of the domains have since moved to 193.32.162[.]240, however.
This was an unusual phishing campaign that was interesting to investigate. It’s a good example of how bad actors design lure emails and phishing sites and what they are trying to achieve as a result.
Interestingly enough, all these massive efforts didn’t seem to result in massive infections. At least we haven’t found the fake CVE patch plugins on any sites that we worked on this December. There may be several reasons why.
Nonetheless, WordPress site owners should stay vigilant and double-check information from any unexpected email before doing what it asks. For example, in case of these fake patch emails, if you don’t immediately notice the glitches, you might still want to search the information about it on WordPress official site and its support forums.
If you have accidentally installed the malicious plugin, you should delete it from disk (remember it will not be visible in the WordPress admin panel). Directories to remove from will be wp-content/plugins/cve-2023-46182 or wp-content/plugins/cve-2023-45124.
Then, review and remove any unwanted WordPress users. The ones created by this plugin have usernames either wpsecuritypatch or a random string consisting of a mix of 10 uppercase and lowercase characters.
Finally search for the uploaded P.A.S. Fork webshell. The filename should be either wp-autoload.php or wp-xxxxxxxxxx.php (x is for random characters). This file should be either in the WordPress root directory or in the fake plugin directory
After installing backdoors, attackers can use them to install additional malware on your site, so make sure to thoroughly scan your website at the client and server levels to detect all indicators of compromise and malicious code. And remember: we’re always available 24/7 if you need help to clean up malware on a hacked website.