How to clean up a hacked WordPress site (Complete Guide)

Is your website loading slowly? Redirects? Popups? Can’t login? Strange folders? Files with weird names? Huge number of failed/deferred emails that you didn’t even send?

These are just some of the most common symptoms of a hacked WordPress website.

If you are experiencing some of these problems – do not panic! In this guide, I’ll show you how to identify if your WordPress website is compromised, teach you which steps you need to take in order to clean a WordPress website from malware and how to better protect it in the future.

CONTENT

BACKUP – First aid for a compromised website

Restoring a website from a backup can be a quick fix but the main issue is that you don’t know for sure when the website was infected and is it safe to restore it from a backup. Cybercriminals could have infected the website months or even years ago and stayed undetected. Just because you just started noticing some strange behavior doesn’t mean that the problem just started occurring.

Even backups can contain malicious code so even if you restore a website from its backup make sure to perform a detailed analysis of all restored files afterwards.

Most (decent) hosting providers nowadays keep backups of your entire cPanel account 30 days in the past so as a last resort you can always ask your hosting provider to restore your account.

Do not rely heavily on your hosting provider to perform backup for you, use a free WordPress plugin such as UpDraft to schedule remote backups on your own.

TIP: Check the last modified date of infected files and restore a backup older than that date.

Aldo restoring a website from the backup does fix the consequences of a security breach, the problem is still present – vulnerable WordPress website. After restoring a backup its necessary to further improve the overall WordPress security in order to avoid the same problem in the future.

Scan files with Virus Scanner

Most hosting providers nowdays automatically block well-known exploits and vulnerabilities using a  web application firewall (WAF) such as Comodo WAF or ModSecurity.

On any shared packages you can perform regular scans of your hosting account through cPanel » Virus Scanner:

cPanel Virus Scanner

Go through the logs of Virus Scanner and if any infected files are found review each of them manually and see how they interact with your WordPress website, then clean them of any malicious content.

For example, most exploited files contain random strings (often known as obfuscated code) that are used to distribute SPAM from your account. Here are examples of the most commonly used WordPress malware.

obfuscated code inside wp-comments-post.php file

In this example, at the beginning of the file, another PHP code was injected that loads additional malicious code that is executed every time your website is loaded, so in order to clean the code you need to delete the first part between PHP tags. So that only the original WordPress code is left:

original wp-comments-post.php file

Cleaning a WordPress website

If you are noticing strange folders and files that weren’t there just days ago, the smartest thing to do is to delete all the data that can be reinstalled and start from scratch.

Keep the uploads folder which contains all your media files and nothing else. You can reinstall everything else> WordPress, theme and plugins.

  • wp-content/uploads folder contains all your media files (images)
  • wp-config.php configuration file that you need to connect to the database

Cleaning a WordPress database

🔴 How to check and clean a MySQL database from SQL injections and WordPress malware?

The best way to check if your database is compromised is to download the whole database from PHPMyAdmin, open it in any text editor and just go through it manually.

To download your database (create a database dump) from your cPanel account open PHPMyAdmin and from the database list on the left select your database.

Open a database in PHPMyAdmin

In case you have multiple WordPress websites on the same cPanel account you will have more than one database. To check which database is used for the website you can open its wp-config.php file and find the DB name under define(‘DB_NAME’, ‘database_name’);

After selecting database name on the left, click on the “Export” link and then the “Go” button.

Export a database from PHPMyAdmin

The whole database will be downloaded as a db-name.sql file which you can easily open in any text editor (such as Notepad++) and go through its content.

WordPress dump opened up in Notepad++

If you have root access (SSH) to the server you can export the database with mysqldump command:

mysqldump -u username-here -p db-name > /home/cpanel-username/file-name.sql

What are you looking for? Anything suspicious. And what is suspicious? Well, anything that doesn’t look like it belongs in a WordPress database. Most commonly it’s some of these functions:

  • eval()
  • base64_decode()
  • gzinflate()
  • error_reporting(0)
  • shell_exec()
  • str_rot13()

Again, if you have terminal access you can grep for any of these codes, here is my grep code:

grep -l -Ei \
-e 'eval[ ]?\(' \
-e 'base64_decode[ ]?\(' \
-e 'gzinflate[ ]?\(' \
-e 'error_reporting[ ]?\((0|off)\)' \
-e 'shell_exec[ ]?\(' \
-e 'str_rot13[ ]?\(' \
$filename

And for looping through a list of files in /home/dbdumps use the following:

for filename in $(ls /home/dbdumps); do
grep -l -Ei \
-e 'eval[ ]?\(' \
-e 'base64_decode[ ]?\(' \
-e 'gzinflate[ ]?\(' \
-e 'error_reporting[ ]?\((0|off)\)' \
-e 'shell_exec[ ]?\(' \
-e 'str_rot13[ ]?\(' \
$filename
done

If you find any suspicious code in the database you can easily Google it or check on the WordPress forums if it belongs to WordPress or not.

You should remove any suspicious content from the .sql file, save it and reupload it back into your database using PHPMyAdmin.

To import the database back in, if you have root access (SSH) run the following command:

mysql -u username-here -p db-name < /PATH and FILENAME.sql

If not, use PHPMyAdmin, but before importing back the database .sql file you need to drop all existing tables from the database.

You can do this by selecting the database, then all tables inside using the “Check all” link below all tables and under “With selected:” choose “Drop“. Click the Go button to confirm the deletion and now you can import back the database.

Drop tables from a database

Once again select your database name on the left, then click on the “Import” link from the menu, select the checked .sql file, and “Go” button.

Import a database into PHPMyAdmin

After a importing you should see a message saying that tables imported successfully.

After removing all old WordPress files (except the wp-content/uploads folder and wp-config.php file), checking and if necessary cleaning up the database, you can now move to the next step and reinstall WordPress.

Re-Installing WordPress

Step 1. Download WordPress

Download a fresh WordPress installation from WordPress.org website.

Download WordPress from WordPress.org

Step 2. Upload WordPress

If you are using cPanel, you can use the File Manager to upload previously downloaded .zip file.

Simply go into the folder where your WordPress website is installed (it’s root directory), click on the Upload link from the menu, select the .zip file and wait for the upload to finish.

Step 3. Extract (UnZip) WordPress

Go back to the folder where you’ve uploaded it, right-click on the .zip file then Extract and Extract File(s).

Extract WordPress in cPanel

Step 4. Move Uploads folder into wordpress/wp-content

Potom se vratite nazad u root folder domena (za glavni domen to je public_html) i uđite u folder wp-content. Iz ovog foldera prebacite folder uploads u tek dodatu WordPress instalaciju.

Right-click on the uploads folder and choose Move to folder then type /WORDPRESS into the path, for example turning public_html/wp-content into public_html/wordpress/wp-content

Move uploads folder to wordpress/wp-content

Step 5. Delete the now empty wp-content folder

After moving the uploads folder from the old wp-content folder to the newly wordpress/wp-content folder, it’s necessary to delete the old wp-content folder.

Delete empty wp-content folder

Step 6. Move files from /wordpress folder to domain root

After moving the old uploads folder into the newly created wordpress folder, you need to move all the content from the wordpress folder to one folder above (domain root). Simply go into the wordpress folder, select all files and fodlers, right-click on any of them, then move to folder, and from the path remove /WORDPRESS.

move wordpress files from the new installation

That’s it, if you’ve followed all of the steps above you’ve now successfully reinstalled WordPress and can safely log into your wp-admin area. Since you didn’t remove the wp-config.php file, the website is connected to the database and since we left the /uploads folder, all images are still there.

Re-install WordPress Theme

After reinstalling WordPress CMS you need to reinstall the active theme and all plugins.

Log into your wp-admin dashboard and install the theme that you were using. Make sure to install a fresh copy of the theme, DO NOT REUSE THE OLD THEME FOLDER AS IT MAY CONTAIN MALICIOUS FILES.

Installing a theme in WordPress

Re-install WordPress Plugins

The same goes for your WordPress plugins, reinstall all of them and DO NOT REUSE OLD FILES. If you are unsure which plugins you’ve used, after opening the Plugins page for the first/time you will see error messages stating that all plugins were deleted because their folders do not longer exist. You can use that list as a reference and re install all the plugins from the error messages.

WordPress deactivate all plugins

After installing all WordPress themes and plugins you may need to re-configure some plugins.

And finally, open your website and re-check if everything works as it’s used to.

How to further improve WordPress security

After cleaning up and reinstalling WordPress it’s necessary to further increase the overall WordPress security in order to avoid the problem from recurring in the future.

These are some of the widely recommended security measurements for WordPress websites:

  • Get a half-decent hosting
  • Configure a Security plugin
  • Limit access to the dashboard
  • Auto-update WordPress
  • Schedule remote Backups

Hosting

A decent hosting is a must-have for any website’s security. You can make your WordPress website bulletproof but all that can be in vain if someone can access your hosting account, upload malicious files and run shell scripts under your name.

From your hosting panel (cPanel) you can furthermore strengthen up your WordPress installation using .htaccess and wp-config.php configuration files and permissions. 

Modify Permissions

You can view folder&file permissions from cPanel’s File Manager, for WordPress the following permissions are recommended:

  • / 0755
  • wp-includes 0755
  • wp-admin 0755  
  • wp-admin/js 0755
  • wp-content 0755
  • wp-content/themes 0755
  • wp-content/plugins 0755
  • wp-content/uploads 0755
  • wp-config.php 0400  
  • .htaccess 0444

Double-click on the permission to change it.

WordPress folder permissions

And if you have root access to the server (SSH) or cPanel Terminal you can run the following commands:

find . -type d -exec chmod 0755 {} \; # set all folders to 755
find . -type f -exec chmod 0644 {} \; # set all files to 644

Change Passwords

Consider changing the passwords of your hosting account after all the infected files are cleaned.

  • Change WordPress admin password
Change WordPress admin password
  • Delete all other Admin users
Delete WP admin users
  • Change FTP password (for the main FTP account on cPanel password is the same as for the cPanel account).
Change FTP password
  • Change MySQL password (make sure to replace the password inside the wp-config.php file).
Change MySQL Password

Regenerate Salts

WordPress uses “Salts” – randomly generated hashes to store and verify user cookies.

To logoff all WordPress users you can replace current salts inside the wp-config.php file.

You can generate new salts here: https://api.wordpress.org/secret-key/1.1/salt/

WordPress salts

Setup a Security Plugin

WordPress has a lot of additional features that need to be blocked because they are widely used for hacking purposes. One of those features is XML-RPC that is nowadays mostly used for brute-force and dictionary-type attacks.

After years of using it, I personally recommend the iThemes Security plugin that among other things also does the following:

  • limiting or completely blocking access to xmlrpc.php
  • logging all login attempts and other user activity
  • limiting access using .htaccess file (site-based firewall)
  • forcing the usage of strong passwords and 2FA
  • scheduling remote database backups

After installing the iThemes Security plugin you will see a list of security recommendations for your website:

iThemes security checklist

Apart from activating these recommended features I also recommend turning on the following modules:

  • 404 Detection
  • File Change Detection
  • SSL
iThemes Security plugin

These modules do not need any special configuration and just run out-of-the-box but the following modules should be additionally configured:

  • System Tweaks
  • WordPress Tweaks
WordPress tweaks iThemes Security Plugin

I recommend turning on all features for these two modules but keep in mind that some of the features that you are disabling may be required by other plugins such as JetBackup and ContactForm7, so check their functionality afterwards and make sure that everything works as it’s supposed.

Limit access to wp-admin

The most common security recommendation for WordPress is to completely disable access or at least hide the /wp-admin and wp-login.php pages.

WPS Hide Login is a simple WordPress plugin that does just that: renames the login URL and redirect all requests to wp-admin dashboard.

WPS Hide Login WordPress plugin

Regular Updates

WordPress 5.6.2 is available! Please update now.
  • Always use the latest version of WordPress, auto/update all plugins, and regularly update the theme as soon as the new version rolls-out
  • Remove all WordPress themes and plugins that you don’t use. These plugins are almost never updated and that can lead to serious security issues.
  • Never, I repeat never use nulled premium WordPress themes and plugins – because they come with backdoors and malware.

Scheduled Backups

Backups are super important because they can save you a lot of time and money

Never keep backups on the same location as your website!


It’s important not to skip any step while cleaning your WordPress website, no matter how small and insignificant it may seem. By skipping any of the steps you run at the risk of leaving a way in for the hackers again.

BONUS: How to remove the “Deceptive site ahead” warning

If Google detected phishing or malware content on your website during a regular scan of your website it will definitely hurt your search rankings but also a “Deceptive site ahead” warning will be shown to all visitors.

deceptive site ahead warning for a WordPress website

Here is a guide on how to request a review from Google: https://developers.google.com/web/fundamentals/security/hacked/request_review

After submitting a request for review if Google confirms that your website no longer contains any malware or phishing content, you will receive an email stating that the deceptive site ahead is removed.

I will clean malware or malicious code and repair hacked websites

Leave a Comment