Whether your WordPress website has been hacked and you’re currently in damage control, or whether you’re preparing for the worst, this article will guide you through the process of cleaning a hacked WordPress website. The process is documented in an easy to follow step-by-step format to help you accomplish the following:
- Gain back control of your WordPress website
- Identify the likely source of the infection
- Find the infection & malicious code
- Remove any malware, backdoors and web shells
- Remove your domain from any malware lists such as the Google Safe Browsing database
- Prevent a recurrence
Is your hacked WordPress website really hacked?
Sometimes it’s pretty clear when a WordPress site has been hacked, for example, if your website has been defaced. In other cases, it may not be so clear-cut. Before embarking on a WordPress clean-up process, confirm that your WordPress website has actually been hacked, and it is not an unrelated technical issue. Read the article how to check if my WordPress is hacked to determine if your website or blog was hacked or not.
Gain back control
Gaining back control starts depending on how much access you may have lost as a result of an attack. For instance, upon gaining access to a server, an attacker may rotate credentials to lock out legitimate users from accessing the server, or perhaps they may change the WordPress admin password to prevent a WordPress admin from logging in.
While this will very much depend on your setup, your hosting provider will most likely be able to help with recovering access to a shared hosting environment or a Virtual Private Server (VPS) running your website. If you lost access to the WordPress admin, follow the official WordPress guide on resetting your admin password.
Taking a backup
Even if you have a WordPress backup solution in place, make a backup of the current WordPress website. Taking a WordPress backup at this stage is very important for a number of reasons, including the following.
- A backup allows you to analyze the infection at a later stage,
- Some hosting providers may resort to deleting hacked websites as a precautionary measure to prevent it from spreading malware or spam — depending on your hosting provider this may happen without warning,
- If you do not have a backup strategy currently in place, you may be able to salvage some of the website content from this backup before things get worse.
Additionally, if you are running WordPress on a Virtual Private Server (VPS), consider taking a snapshot of the entire virtual machine if possible (bear in mind this is usually associated with an extra cost). When taking snapshots, keep in mind that if you are using any external volumes to host your WordPress installation (e.g. network attached storage), you should also take a copy of any volumes that store the main WordPress installation, wp-content, your MySQL database, as well as any web server access and error logs.
Restoring from a backup
If you have a backup strategy in place, now is the time to put it in action. Assuming you have access to a recent backup, restoring may be the fastest way to get yourself back online–make no mistake however, while restoring from a backup of your WordPress site may remove an infection and allow you to be operational again, it does not solve why you got hacked in the first place.
If your WordPress website got hacked as a result of an exploited vulnerability or security flaw, it is an essential next step to try hard to figure out what happened (if possible).
What if I don’t have a backup, or I can’t restore my backup successfully?
If you don’t have a backup you can restore successfully, depending on the gravity of the situation you may want to put your WordPress website into maintenance mode to allow you to work on restoring your site whilst letting visitors know they should check back later. In the meantime, continue following the rest of this guide. By putting your website in maintenance mode, through the use of the wp_maintenance()1 function, WordPress will return a 503 HTTP status code. A 503 status indicates to Google and other crawlers that something went wrong on the page, and they should check back later.
A 503 HTTP response is important for SEO since it will prevent damage to your search rankings in the event of your website being temporarily down. For more information about the 503 HTTP status code and its importance in SEO, check out Yoast’s article on the topic.
Identify how WordPress got hacked
Once your site is back up, the next thing on the agenda is to find out as much as you can about what happened, that is, which security weakness the attacker exploited to gain access to your WordPress installation.
Checking the activity logs, web server and FTP server logs
If you keep a WordPress activity log, this might be the best place from where to start your analysis. See if you can identify any suspicious behavior. Look for events of newly created users, or user password changes. Also check if any WordPress, plugins or theme files were modified.
You should also take a look at the web server, FTP server and operating system log files for unusual or suspicious behavior. While this may be somewhat of an overwhelming process, you’ll want to start by checking if there is strange traffic coming from a single IP address. You can do this using a variety of utility shell scripts and one liners. For a real-time view on your web server logs, GoAccess might come in handy.
Unused and outdated WordPress plugins and themes
Check the list of installed plugins, both from the WordPress dashboard and in the directory /wp-content/plugins/. Are all the WordPress plugins being used? Are they all up-to-date? Check the themes and the themes directory /wp-content/themes/ as well. You should only have one theme installed, the one which you are using. If you are using a child theme you will have two directories.
Unused WordPress code and installations
Leftover and unused code is another common problem. Sometimes developers and sysadmins update files directly on the server and take a backup of the original file with an extension such as .old, .orig or .bak. Attackers frequently take advantage of this bad practice and tools to look for such backup files are widely and readily available.
The way this works is by an attacker trying to access files such as index.php.old. Usually, .php files are configured to be executed by the PHP interpreter, but by adding a .old (or other) extension to the end of the file causes the web server to serve the file to the user. By simply being able to guess a backup file’s name, an attacker may be able to download the source code which may contain sensitive information, or may provide the attacker with hints on what to exploit.
A similar problem is retaining old installations of WordPress. When sysadmins rebuild their websites they sometimes leave copies of old WordPress installations in an /old/ subdirectory. These old installations of WordPress would typically still be accessible over the internet, and therefore a juicy target for an attacker to exploit known vulnerabilities in old versions of WordPress along with any plugins.
It is advisable to remove any unused code, WordPress installations, WordPress plugins, WordPress themes and any other old or unused files (remember that you can always turn to your backup if you need to restore something you accidentally deleted). Your website should only contain files you need. Anything else that is extra or unused should be treated as an additional attack surface.
WordPress users and roles
Verify that all WordPress users are used. Are there any new suspicious ones? Check that all the roles are intact. If you follow the WordPress users and roles guidelines you should only have one user with a WordPress administrator role.
Shared hosting providers
If your WordPress is running on a shared hosting provider, the source of the hack could be another website that happened to be running on the same server as yours. In this case, the most likely scenario would be that the attacker would have managed to escalate their privileges. Then as a consequence, gain access to the whole server, and in turn to your WordPress website. If you suspect such an attack took place, the best recourse would be to immediately get in touch with your hosting provider, after backing up your website.
.htaccess files (directory level Apache HTTP Server configuration files) are also a common target for hackers. They are typically used to redirect users to other spam, phishing, or otherwise malicious websites. Check all the .htaccess files on your server, even those which are not being used by WordPress. Some of the redirects can be difficult to spot.
Pay particular attention to configuration that redirects HTTP requests based on specific User Agent strings–attackers may be targeting specific devices (e.g. mobile users), or even engaging in black hat SEO by configuring your web server to respond differently to search engine crawlers.
If possible, consider adopting global configuration as opposed to relying on .htaccess files within Apache HTTP Server. Not only do .htaccess files degrade performance, but they open your WordPress website up to a variety of security vulnerabilities if an attacker is ever in a position to read, or worst still, write the contents of these files. As per the Apache HTTP Server documentation2, the use of .htaccess files can be disabled completely by setting the AllowOverride directive to none in the main httpd.conf file.
Checking other point of entries
There are several other points of entries on a web server. Make sure you check all of them, such as FTP servers, SSH, the web server etc.
Find the WordPress infection and malicious code
Before You Start: A WordPress hack typically involves the insertion of code in a WordPress theme, plugin or core file. Hence, to proceed with a clean-up, you should be comfortable with modifying code. If you are not, hire WordPress security professionals.
Once you identify the hackers’ point of entry, typically it is relatively easy to find the infection. Though just in case you haven’t found the infection yet, there are several methods you can use to find the infection. Here are a few.
Checking which files were modified in the last few days
Ideally, you should be using a WordPress file monitor plugin that monitors files across your WordPress installation for changes and immediately alerts you. If you do not have a File Integrity Monitoring (FIM) plugin, you will have to look for file changes manually.
If you have SSH access to your server, check which files in your WordPress website have changed recently. Typically, it would be advisable to start looking for changes within the last five days of the hack being noticed, broadening your search as necessary. To do so, navigate to the directory where your WordPress website is located and use the find command.
find .mtime -5 –ls
The above command lists (-ls) all the files which have been modified (.mtime) in the last five days (-5). If the list is too long, use the less pager to browse and search through the list with more ease.
find .mtime -5 –ls | less
If you have recently updated a plugin or theme, any related file changes will show up in your search results. Logs, debug files are also updated frequently, so they will show up in your results as well. As a result, you may have to do some extensive filtering of the results to find file-changes of interest. Note that specialized plugins such as the WordPress File Changes Monitor plugin for WordPress are specifically designed to weed-out such false positives for you automatically. The plugin is purposely built for WordPress and can identify a file change from a WordPress core, plugin or theme updates, install or uninstall.
Checking all HTML files
In WordPress there are very few HTML files and hackers like to take advantage of them. Search through your website for all HTML files and analyze their content. Make sure all HTML files you have on your website are legitimate, and you know what they are used for.
An easy way to list all HTML files in your WordPress directory (and subdirectories) is to use the following command.
find . -type f -name '*.html'
Searching for infection text
If your website has been defaced, or some text is showing up on your website as a result of the infection, look for it with the grep tool. For example if you’ve seen the text “hacked by”, navigate to the root directory of the website and issue the following command.
grep –Ril &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;hacked by&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;
The above command will return a list of files that include the content “hacked by”. Once you have the list of infected files you can analyze the code and remove the infection.
What do the grep switches mean?
- -R indicates to grep to search recursively (searches through the whole directory structure, including all subdirectories and symbolic links).
- -i indicates to grep that the search should be case-insensitive (i.e. to ignore the capitalization of the search term). This is very important in Linux/Unix environments, since unlike in Windows, Linux file systems are case-sensitive.
- -l indicates to grep that it should return the filename, rather than the file contents. When your WordPress site gets hacked this is other malicious code to look for.
Apart from the obvious “hacked by” string, below is a list of code and text phrases that are typically used in hacked WordPress websites. You can use the grep tool to look for the following:
A quick way of achieving this using grep is via the following grep command which looks for files recursively (follows any symbolic links), searches for the strings that match the specified PCRE regular expression3, and returns the text match as well as the line number where the match occurred.
grep -RPn &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;(base64_decode|is_admin|eval|gzuncompress|passthru|exec|shell_exec|assert|str_rot13|system|phpinfo|chmod|mkdir|fopen|fclose|readfile) *(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;
NOTE: Some of this code can also be used in legitimate code, so analyze the code properly and understand how it is being used before flagging something as an infection or hack.
Compare the files with an original WordPress install
This is an old school method, and even though it is somewhat time-consuming, it works wonders. Compare the files of your website with those of an untampered website. Therefore, if you have a backup copy of your website, compare the tampered website. If not, install a new copy of WordPress and the plugins you have on the infected website on a different host and compare them.
There are several tools you can use to compare files. In this example, we use a commercial tool called Beyond Compare, though there are several free alternatives. Below are some screenshots of a sample comparison.
When comparing the root directories of two WordPress websites, the tool highlights the difference in the content of the file index.php, the new .htaccess and wp-config.php files, and differences in the subdirectories.
By double-clicking the file index.php we can see what the differences are.
What to look for in a WordPress file comparison?
Look for files which are not part of the WordPress core. Most infections add files to the root of the WordPress installation or to the wp-content directory. If the hack is a result of a vulnerable plugin, the files of the plugin might have been modified.
Clean the WordPress hack
It is time to start cleaning up by following the below procedure, once you know the source of the WordPress hack and found the infection.
Finding the infection automatically with a WordPress service
If the above seems too much to handle, do not despair. There are several WordPress security services and plugins which you can use to scan your website for malware and other infections. Just search online for “WordPress malware removal service” and choose the one that fits your technical and financial requirements.
Do however note that such plugins have a limited list of malware signatures that they look for. As such, if the attack that affected your WordPress website is not as common, these plugins might fail to identify the infection. It is not unheard of for us to receive feedback from WordPress administrators whose WordPress website fell victim to an attack that WordPress malware plugins did not identify anything wrong.
The takeaway here is that effective security controls involve having several layers of defenses and detection. While manual analysis is almost always the best way forward when you can do it; these plugins should not be underestimated either–they can still be used and will come in handy at some point.
Restoring your WordPress from backup
If you have a backup of your WordPress website or blog, restore it. It is always much easier than manually cleaning the code.
Changing all passwords, delete unused users and verify WordPress users roles
Change all the passwords of all your users and services including WordPress, CPanel, MySQL, FTP and your own personal computer. Check the list of users on your FTP, WordPress, MySQL and any other service to confirm that all users are legitimate. If there are any users which are no longer being used, delete them. Check that all WordPress users have the correct roles and permissions.
Upgrading WordPress core, plugins, themes and other software
Make sure you’re running the most up-to-date version of all the software required to run your WordPress website. This is not just limited to WordPress itself, but also extends to any plugins, themes, as well as operating system patches, PHP, MySQL and web server (e.g. Apache HTTP Server or Nginx) and any FTP server you may be running.
Backuping your WordPress website
Once at this stage, before removing the actual infected code take a backup of your WordPress website.
Remove the Google Safe Browsing malware alert
If your website was deny-listed by Google Safe Browsing, you can submit your website for a security review with Google to remove the alert.
Once you remove the WordPress hack…
Congratulations, you recovered your WordPress website from a hack. Now you must make sure that it does not happen again. Here are some tips on what you should do:
- Install a WordPress activity log plugin to keep track of everything that is happening on your WordPress website.
- If you do not have a backup solution in place, get one.
- Use a WordPress security scanning service.
- Rotate database and admin passwords, and force strong WordPress password security.
- Always keep your WordPress, WordPress plugins, themes and any other software you use up to date.
- Remove any unused files such as old WordPress installations, unused WordPress plugins and themes (including unused default WordPress themes). Unused components and software add unnecessary attack surface and should ideally be removed.
- Follow our WordPress security hardening guide to make sure you take care of every possible security issue on your website.