One morning a client contacted me because his website had some cool new sweepstakes on his WordPress instance. Unfortunately, he also told me that this is probably not from him, but his site is probably compromised. So, nothing to win here. This means I have to see what exactly happened and how this can be reverted.
I was contacted on September 5, 2023. With all known details, one of which was a password change on one of the admin accounts. This password change was on the 12th of May. This means the attacker was undetected for 116 days! You might think, that this is the long timeframe, which I would tell you: Yes! you are right. However, it is still below the average of 287 days until a breach is detected.
Since the breach is at least 116 days old there is no point in restoring a backup until I know exactly when the attacker got into the system. So it is time to do some forensics on the system.
Step 1 - Lockdown
Since this is a crime scene, the first thing I need to do is lock the system down. This is to prevent users from falling for the scam and avoid further damage to the customer's reputation.
A simple Basic Authentication on the whole website is enough here.
With the site locked for everyone else, I can begin to gather more information about what happened.
Step 2 - Forensics
With access to the cPanel, I'm going to download the current state of the WordPress instance. This is so I can run a local scan and other intel gathering locally, without breaking anything online.
After installing the instance on a virtual machine, I'm starting a scan with wp-scan and letting it do its thing.
In the meantime, it is time to dig into logs. Luckily I've got a date of a strange event: Admin password change on the 12th of May.
Looking inside the access logs on this date, I can see a lot of the usual noise and something that is out of the ordinary:
18.104.22.168 - - [12/May/2023:16:26:56 +0200] "GET / HTTP/1.1" 301 487 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36" … 22.214.171.124 - - [12/May/2023:16:27:21 +0200] "GET /about-us HTTP/1.1" 404 126301 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36" 126.96.36.199 - - [12/May/2023:16:27:21 +0200] "GET /terms-of- service HTTP/1.1" 404 126335 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36" >> 188.8.131.52 - - [12/May/2023:16:27:22 +0200] "GET /?343=1 HTTP/1.1" 200 236590 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36" 184.108.40.206 - - [12/May/2023:16:27:23 +0200] "POST /wp-admin/admin-ajax.php HTTP/1.1" 200 5901 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36" 220.127.116.11 - - [12/May/2023:16:27:24 +0200] "POST /wp-admin/admin-ajax.php HTTP/1.1" 200 5921 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36" >> 18.104.22.168 - - [12/May/2023:16:27:24 +0200] "POST /wp- login.php HTTP/1.1" 200 17358 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:102.0) Gecko/20100101 Firefox/102.0"
As you can see there was an enumeration process going on from the IP
22.214.171.124 and in the last entry a successful login. Interesting.
So how was this possible? Take a closer look at the entries above, especially this one:
126.96.36.199 - - [12/May/2023:16:27:22 +0200] "GET /?343=1 ...
Searching for this request will lead to this article. Which describes a vulnerability in
Essential Addons for Elementor. Give it a read to know the details of this.
Going back to wp-scan I'm getting a lot of outdated plugins warning, one of which is the
Essential Addons for Elementor Plugin. Seems like we've got a match.
Checking the signature of this with the created files, I can confirm, that this is the attack that led to the breach:
Step 3 - Remediation
The best thing you can do in this situation is to install a clean WordPress and point it to the current database. But before I can do that, I also need to make sure, that the database is not contaminated with malware.
A quick way to do this is, to download the SQL dump, open it with a code editor and search for the following:
If you find any of these entries inside your dump, take a closer look at them. This might be another way for the hacker to get back into your WordPress instance. You can read more about this topic here.
In this case, there was nothing to be found, so I proceeded with installing WordPress in a subfolder.
After confirming that the new WordPress is up and running I deleted the old WordPress files.
Step 4 - Hardening
Now that everything seems to be cleared, I need to make sure, this won't happen in the future again. This means hardening the system.
For this, I've installed Wordfence. This plugin is a great plugin when it comes to hardening WordPress and notifying certain events.
Wordfence also offers the ability to enable 2FA. Which every User with Admin privileges is now required to have.
Next, I've instructed the team to remove all unused plugins. An easy step, but a powerful one.
The last and most important one: I've enabled automatic updates on all plugins, themes and WordPress itself. I know that this might break the site from time to time, but I can assure you that a
div slightly offset is far better than a breached website.
The breach of this WordPress site emphasized the importance of timely software updates and vigilant cybersecurity measures.
This incident, rooted in an outdated plugin, could have been avoided with regular updates. So make sure to implement at least automatic updates!
I can also highly recommend installing Wordfence on your WordPress site, to have an extra layer of security.
It's crucial to remember that maintaining software up-to-date is an essential defence against cyber threats, underlining the necessity to keep your software updated to ensure optimal site security.