Where attacks come from
WordPress powers a large share of the web, so attackers target it with automated tools. They rarely find a flaw in WordPress core, which is well reviewed and updated quickly. Nearly all successful attacks use one of these:
- an outdated or abandoned plugin or theme with a known flaw;
- a weak, reused or leaked password;
- too many people with admin rights, or accounts of former staff;
- a pirated ("nulled") theme or plugin that arrives with a backdoor;
- a hosting account with weak settings or shared credentials.
Hardening means closing these doors, plus keeping a backup so you can recover when something still goes wrong. It is a routine, not a one-time job.
1. Keep everything updated
Updates fix security holes, and attackers read the release notes too. Check what is outdated:
wp core check-update
wp plugin list --update=available --fields=name,version,update_version
wp theme list --fields=name,status,updateThese commands ask wordpress.org for the latest versions, so they need an internet connection and are not run for this lesson. On a site that is up to date you see a message such as Success: WordPress is at the latest version. and empty tables; when an update exists, the tables list it with the new version number.
On a live site, take a backup, update (wp plugin update --all, wp theme update --all, wp core update), and look at the site. WordPress applies minor core security releases automatically; for plugins you can enable automatic updates per plugin in the dashboard. Also delete plugins and themes you do not use: an inactive plugin can still be attacked, because its files are on the server.
2. Strong logins and least privilege
- Use long, unique passwords from a password manager, and switch on two-factor authentication with a reputable plugin.
- Avoid the username
admin, and never publish usernames if you can help it. - Give people the lowest role that lets them work. Review the list regularly:
wp user list --fields=ID,user_login,roles
wp user list --role=administrator --format=count+----+------------+---------------+
| ID | user_login | roles |
+----+------------+---------------+
| 1 | admin | administrator |
+----+------------+---------------+
1- Remove accounts that nobody uses, and set up separate accounts instead of sharing one.
- Limit login attempts (a security plugin or your host's firewall) and consider a firewall service in front of the site.
3. Lock down wp-config.php
wp-config.php holds the database password and secret keys. Treat it like a key to the building:
// Remove the theme/plugin file editors from the dashboard.
define( 'DISALLOW_FILE_EDIT', true );
// Optionally also block installing and updating from the dashboard (use deployment or WP-CLI instead).
// define( 'DISALLOW_FILE_MODS', true );
// Force HTTPS for logins and admin.
define( 'FORCE_SSL_ADMIN', true );
// Never show errors to visitors on a live site; log them instead.
define( 'WP_DEBUG', false );
define( 'WP_DEBUG_DISPLAY', false );
define( 'WP_DEBUG_LOG', true );Also: keep the file readable only by the web server user (permissions 640 or 600), keep the secret keys unique (wp config shuffle-salts generates new ones, and logs everyone out), and never commit it to a public repository. The file can be placed one folder above the web root; WordPress still finds it.
4. Check that files have not been changed
WordPress publishes a checksum for every core file, and the plugin directory does the same for plugins. Compare your files with them:
wp core verify-checksumsSuccess: WordPress installation verifies against checksums.Files that differ, or extra files in core folders, show up as warnings. That is how you find injected code after a hack. For plugins hosted on wordpress.org:
wp plugin verify-checksums --all(Plugins that do not come from wordpress.org, such as custom or paid plugins, cannot be checked this way.)
5. Safe file permissions and uploads
- Folders
755and files644; nothing should be777(writable by everyone). - The web server needs to write only to
wp-content/uploads(and caches), not to core or plugin code, unless you update from the dashboard. - Block PHP execution in the uploads folder through the web server configuration, because uploads should only hold images and documents.
- Use HTTPS everywhere, with the site address set to
https://in Settings → General.
6. Backups you can restore
A backup has two parts: the database (all content and settings) and the files (wp-content: themes, plugins and uploads; the core files can be downloaded again). WP-CLI exports the database in one command:
wp db export /path/to/backups/site-2026-03-01.sqlWordPress prints "Success: Exported to '/path/to/backups/site-2026-03-01.sql'." Back up the files with your host's tools or tar/rsync. To prove that a restore works, import the dump into a test database and look at the result. Here that is done on the lesson's own database, by changing a title, importing the earlier export, and reading the title again:
wp db export backup.sql --quiet
wp post update 1 --post_title="Changed after backup"
wp post get 1 --field=post_title
wp db import backup.sql
wp post get 1 --field=post_titleSuccess: Updated post 1.
Changed after backup
Success: Imported from 'backup.sql'.
Hello world!The import brought the original title back. In real life:
- take backups automatically (daily for active sites, hourly for shops), with a plugin or the host's tool;
- keep several generations (daily for a week, weekly for a month);
- store copies off the server (cloud storage or another host), encrypted if they hold private data;
- test a restore regularly, and write the steps down, including the order (files, database, then search-replace if the address changed; see Moving a site from local to live).
7. Know what to do if you are hacked
- Put the site in maintenance mode or take it offline, and change all passwords (WordPress, hosting, database, FTP/SSH) from a clean computer.
- Restore a clean backup from before the problem, or reinstall core files and compare plugins and themes with fresh downloads.
- Check users for unknown administrators, and look for strange files in uploads,
mu-pluginsand the root. - Find how they got in (usually an outdated plugin) and fix that, or it happens again.
- Update everything, change the secret keys, and watch the logs.
Monitoring
- Turn on Site Health (Tools → Site Health) and read its suggestions.
- Get alerts for downtime and for new administrator accounts or changed files.
- Keep a short log of what you update and when.
Common mistakes
- Never updating "because it might break something". Test on a staging copy, but do update.
- Backups on the same server only, or backups never tested.
- Shared admin accounts and weak passwords.
- Nulled themes and plugins.
- Leaving a test plugin or the file editor enabled on a live site.
Exercise
Write a short weekly checklist (five items) for a small business site that you maintain.
Show one possible answer
- Take or confirm the automatic backup, and check it is stored off the server.
- Update core, plugins and themes (staging first for big changes), then click through the main pages and forms.
- Review the user list; remove unused accounts and check there are no unknown administrators.
- Run
wp core verify-checksumsand look at Site Health for warnings. - Check uptime and the error log, and note what changed in a log file.
Once a quarter, restore a backup to a test site to prove that it works.
Key points
- Most hacked sites run outdated software, weak passwords or abandoned plugins; updating and removing unused code removes most of the risk.
- Use strong unique passwords with two-factor authentication, limit administrators, and set DISALLOW_FILE_EDIT in wp-config.php.
- wp core verify-checksums and wp plugin verify-checksums compare files with the official copies to find changes.
- A backup is only real if you have restored it: take database and files backups off the server, on a schedule, and test the restore.