Skip to content

Instantly share code, notes, and snippets.

@ericrasch
Last active February 17, 2022 09:17
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save ericrasch/9a5db40951c2b0306c8d to your computer and use it in GitHub Desktop.
Save ericrasch/9a5db40951c2b0306c8d to your computer and use it in GitHub Desktop.
Hardening & Improving WordPress Security

A shortened, actionable version of the full punchlist

  1. Sync your entire live site down to your local repo
  2. Change the WordPress default admin user + generate a new password
  3. Remove any users that aren’t supposed to be there, or that are no longer in use
  4. Update WordPress (in case you need to update it manually: https://gist.github.com/ericrasch/4192dc480398a896d4d58b5afe08a1d0)
  5. Update all WordPress plugins
  6. Remove unused plugins
  7. Remove unused themes
  8. Remove most .php/..php5/.html/.phtml/.txt files from the /wp-content/uploads foler.
  9. Run grep -R --exclude="*.js" -e 'eval(' .|cut -c -80 in the command line of the site's root folder to help find evil code
  10. Add this to the wp-config.php file: define( 'DISALLOW_FILE_EDIT', true );
  11. I highly recommend deleting the /xml-rpc.php file as an additional step to this: Disable XML-RPC access by adding this plugin to the /mu-plugins folder: https://gist.github.com/ericrasch/bda89f60042dd433037b
  12. Add this to your .htaccess for additional file security
  13. Add these .htaccess files to both the /wp-content and /wp-includes folders
  14. Run this sql command UPDATE wp_posts SET ping_status="closed"; in a database editing app like Sequel Pro (but only if you know what you're doing).
  15. change the table prefix in the wp-config.php file using the iThemes Security plugin
  16. Install WP-Optimize and clean up the database locally, but there's no need to commit this (or iThemes) to a repo and/or exist on a live site (unless you're intending to keep iThemes on your site)
  17. If you're using the Genesis WordPress Skeleton Framework, run the genesis:up:mirror command to automatically sync/delete the hacked files within the /wp-content/uploads/ folder.

Must do... first thing

  1. Sync your entire live site down to your local repo to see if there are any new files on the live server that may/may not have added indicating your site has been exploited.
  2. change the WordPress default admin user + password
    • create another Super Admin user
    • If you're running your site as a company, use companyname_admin for the username and contact+sitedomainwithextension@companyname.com for the email (Staff Writers will work for a name and Staff as a nickname; just make sure you know what's being displayed publicly) and generate a password
    • login as that user
    • delete the base admin user and auto-reassign all Post/Pages from that user to the new admin user you just created
    • If your company keeps track of multiple logins for your website(s), be sure to update those records, too.
  3. Go to your WordPress admin panel and remove any admin/editor users that aren’t supposed to be there, or that are no longer in use.
  4. Re-run the WordPress update tool (to overwrite all the files with a clean copy)
  5. Update all WordPress plugins. To see if an installed plugin has a known vulnerability, use the following plugins to check them:
  6. Remove unused plugins. Hackers can still files/issues within inactive plugins.
  7. Remove unused themes. Hackers can still files/issues within inactive themes.
  8. Remove most .php/..php5/.html/.phtml/.txt files from the /wp-content/uploads foler. There's generally only 1 index.php in that foler.
  9. Run grep -R --exclude="*.js" -e 'eval(' .|cut -c -80 in the command line of the site's root folder to help find evil code (source: http://halfelf.org/2013/evaluating-evil/ which also gives a good snapshot of a clean WP install)

Second steps

  1. Scan your site/database with the following plugins:
  2. disallow file edits from with a theme
    • add this to the wp-config.php file: define( 'DISALLOW_FILE_EDIT', true );
  3. disable XML-RPC access

If you're not using the Genesis WordPress Skeleton Framework, then do the following:

  1. Edit your .htaccess for additional file security by using the Solid Base .htaccess
    • be sure to change line #101 CHANGETHENAMEOFYOURWEBSITEHERE.com where you need to reference your own website's domain
  2. Add these .htaccess files to both the /wp-content and /wp-includes folders

If you have the time/skill to mess with the database

  1. change the db username + password
  2. block old posts from trackback spammers:
    • run this sql command: UPDATE wp_posts SET ping_status="closed";
  3. change the table prefix in the wp-config.php file
    • $table_prefix = 'wp_';
    • consider installing to do this for you iThemes Security plugin to change this automatically
  4. look for malicious cron jobs running on your server
    • one cron job we found recreated the .cache.php file every hour and at 00:27 minutes, so just deleting the file wasn't enough

Untested, but recommended

  • Change permissions on core files:
    • chmod .htaccess to 444
    • chmod wp-config.php to 400
  • Consider enabling Two-Factor Authentication

Further Steps

Plugins that helped:

Plugins that didn't help:

Some of these worked just fine, but they required more digging to find out the actual issues on the site and/or were handled better by the plugins listed above. Others required you to create an account to even begin to use them.

<Files *.php>
deny from all
</Files>
<Files *.php>
deny from all
</Files>
<Files wp-tinymce.php>
allow from all
</Files>
<Files ms-files.php>
allow from all
</Files>
@wpsecureops
Copy link

Hi @ericrasch.
We always try to keep our plugins as helpful as possible (but not bloated with unneeded features), so we wonder, can you share a bit more details on why our plugin "WPSecureOps Easy Firewall" was not working for you? :)

Thanks!
WPSecureOps Team

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment