Do you offer reseller hosting or just host WordPress websites in general? WordPress can be one of the trickiest things to host if you choose to do it the cost effective way by hosting it yourself and handling the security pitfalls yourself.
I have spoken in the past about the benefits of utilising Cloudflare for security purposes. Cloudflare is an easy way for you to limit DDoS attempts, block countries you’re not interested in exposing your website to or throttle connections based on their behaviour in a number of general ways.
But what do you do when you find out, yup, I’ve been hacked.
Well, recently I found myself in this situation and it sucked, I had to manually go through and learn some techniques to deal with it and lock everything back down. So I thought I’d share some tidbits of useful information that benefited me through the process.
File Integrity – The WordPress Core
So how do you know whether or not your WordPress files and/or folders have been compromised? Well, there’s this wonderful thing in software called a checksum, the digital file fingerprint, which is used to check if the data is accurate/unchanged. On your server, you can download the WP Core library and this will allow you to run some commands on your server via the CLI to speak directly with WordPress. This tutorial assumes you know how to go about installing wp core on your server, if not, ask ChatGPT, keep up.
Once you have wp core installed, here’s a neat little bash script you can create on your server that you can run to check the integrity of all of your WordPress websites in one go:
#!/bin/bash
# Define the path to the directories containing the WordPress sites
SITES_PATH="/home/forge"
# Loop through each site directory and run the verify-checksums command
for site in "$SITES_PATH"/*/public; do
if [ -d "$site" ]; then # Ensure it is a directory
echo "Checking $site..."
cd "$site"
if [ -f wp-config.php ]; then # Check if wp-config.php exists to assume it's a WP site
wp core verify-checksums
else
echo "Skipped $site: No wp-config.php found."
fi
echo "-----------------------------------"
fi
done
The script above assumes you have a public folder inside of each directory, if you do not, then remove the /public part (or replace it with what your folder structure adheres to). Change your home default directory too obviously, or it won’t be able to execute.
Running the script above in the appropriate location with the appropriate instruction will result in output similar to:
Now, when you’ve run the above, you can, at a glance, see if there are; a) Intrusive files that don’t belong in your WordPress installation, and b) core WordPress files that have been modified or have code injected into them, let’s address each scenario.
So for intrusive files that don’t belong (should not exist), that’s easy – delete them.
For the latter, this is a cumbersome and laborious undertaking to edit files and remove the injections. Historically you would FTP / cPanel your way in and replace the files from a fresh WordPress installation. But one again, there’s a simple command you can enter once you navigate to the affected WordPress installation:
wp core download --skip-content --force
–skip-content ensures that it doesn’t download the default themes and plugins, and importantly, doesn’t overwrite the wp-config.php affectively disconnecting you from your database.
–force is used to overwrite the existing WordPress core files with the fresh ones from the download.
Voila! Your WordPress is refreshed and renewed with the latest core, the hacked files are replaced and you are now free to run the check bash script once more to establish which files to delete.
Final Checks
So now that you have cleaned up the mess, it’s time to just ensure the windows and doors are locked. You can run wp user list to see if there are any new users, and you can proceed to delete those users too, if there are (as there were in my case) nefarious new admin users. Now change all of the database passwords, adjust them inside of wp-config.php, if you want to be neurotic you can generate new salts for WordPress.
Inside of the WordPress directory you can run this command to ensure files, folders and the all important config file have the appropriate permission levels:
find . -type d -exec chmod 755 {} \; && find . -type f -exec chmod 644 {} \; && chmod 600 wp-config.php
Updates and Security
If you’re using Nginx, you can edit your /etc/nginx/sites-available/catch-all to include this block:
Install Wordfence
If you don’t have these (or similar) installed already, use Fail2Ban, IPTables and of course Cloudflare. Or bots will run you down and win eventually.
Set up Google Recaptcha
Update all plugins and themes – because those folders aren’t traversed by the checks above.
Delete any themes that you aren’t using, while you’re at it, themes can be as vulnerable as plugins.
Don’t have de-activated plugins sitting around either, all code is still executable, even if it is in the waiting room.
location ~* /wp-content/uploads/ { location ~ \.php$ { deny all; } }
*This will prevent code execution when a file is uploaded via nefarious means.
Go spend time with your family, the Internet sucks.