Running a network of WordPress servers is demanding work, and today was a long day. The security landscape is always evolving, and attacks against WordPress site are constant. But for one site on my network today, I had to repel an attack in real-time.
How the attack started
We run multiple log scanners, file scanners and malware hunters on the network. So alarm bells started ringing when the hacker began deploying suspicious PHP files in unusual places.
But that’s a bit odd – people can’t simply deploy random PHP files on WordPress sites. They need to either exploit a software vulnerability (e.g. an out-of-date plugin) or, as in this case, exploit a vulnerable administrator account. Analysis of the log files show the hacker logged-in to the site through the front door (no brute-force necessary).
I guess there’s only so much we can as system administrators. But if the client uses lax password security, bad things will happen. ::sigh::
Real-time response
The first things the hacker deployed were files like this:
Defunct (an executable)
ALFA_DATA/
pip.php
pearl.reax (extension changes)
zteam/
shit.phpThese files stood out in the root directory and were easy to delete. But the hacker was able to create additional backdoors, so they must still have access to the site.
- I needed to scramble all administrator passwords. This didn’t help much, because the hacker was now using these backdoors to log in. But it would remove the initial attack vector and stop it being exploited again in the future.
- I Edited wp-config.php to change the security keys. This was as easy as editing file text file tweaking the long strings for
AUTH_KEY,LOGGED_IN_KEY, etc. Tweaking each of those by a few characters was enough to invalidate all existing login sessions – effectively logging everyone of the site.
The next step was to check WP Core was still intact, by validating the checksums with WP CLI.
# Validate core file checksums wp core verify-checksums
That was OK – I didn’t need to re-install WP core.
Hunting for backdoors
Now, to find those wretched backdoors.
Although I’ve written tools and pattern-matching rules to help with this, it was useful having access to new malware PHP files. I analysed shit.php and the other files to check for identifiable patterns. Most of the PHP backdoor files contained comments in Indonesian (thanks, Google Translate). So a quick bit of command-line grep magic…
# Search for PHP files with Indonesian comments. grep -Enr '(Password salah|Gagal mengambil)' --include='*.php'
…and a sprinkling of find…
# Find unusual perl file names
find . -type f | grep -E 'perl\.\w{3,}+'Watching for new activity
The final task was to watch the logs… like a hawk. Website access and error logs are a treasure trove of information. We can use grep to search the logs for unusual activity, and tail to “follow” the logs in real-time.
# Search the access logs for access to the login page grep 'POST /wp-login\.php' access.log # Follow the access log in real-time, use [Ctrl][C] to stop tail -f access.log
Using grep to scan the access logs for POST requests to wp-login.php was the crucial link. By picking up the iP addresses from these requests, I was able to filter the access log for just those addresses. For example:
# List all IP addresses that POSTed to the login page. grep 'POST /wp-login\.php' access.log | cut -d' ' -f1 | sort -u # Take any of those IP addresses and look at its traffic grep '123.123.123.123' access.log
By looking through the hacker’s access log traffic, I saw how they navigated around the admin area. The first thing they did was reset admin user account passwords, then install a WP File Manager plugin. That’s how they uploaded their first payloads.
It then looks like they created a WordPress Application Password for one of the admin users, which they were able to use to interact with the site even after I’d reset all admin login passwords.
Summary of the tidy-up
In short… I took the following actions:
- Scrambled all admin passwords
- Reset all the security key strings in wp-config.php
- Located and deleted all suspicious PHP files
- Scanned the logs for hacker IP addresses
- Blocked the hacker’s IP addresses in the firewall
I repeated the following steps from start-to-finish several times, until there were no new signs of compromise on the site.
As annoying as these things can be, it was great to see the malware scanners did their job. And it was a great opportunity to analyse a modern attack, to improve my security tools.
But it was a long day.
