Home/Server & Website Managed Operations/WordPress Security Hardening Checklist: Actionable Steps from File Permissions to Login Protection
Server & Website Managed Operations

WordPress Security Hardening Checklist: Actionable Steps from File Permissions to Login Protection

In the vast majority of WordPress site breaches, it is not due to fatal vulnerabilities in the WordPress core, but rather because several critical security boundaries remain open: overly permissive file permissions, unlimited login attempts on the admin panel, and PHP execution capabilities within the upload directory.

Below is a checklist organized from bottom to top that you can implement directly. Each item specifies what to do, why it matters, and how to verify its effectiveness.

1. File Permissions

# Directories 755, Files 644
find /var/www/html -type d -exec chmod 755 {} ;
find /var/www/html -type f -exec chmod 644 {} ;

# Tighten wp-config.php to 600 (contains database credentials)
chmod 600 /var/www/html/wp-config.php

# Change ownership to the web service user
chown -R nginx:nginx /var/www/html

Avoid using 777 permissions. While it may resolve “write failed” errors, the cost is that any local user can modify your site files—this simply shifts the problem to a more severe form.

2. Disable Online File Editing

// wp-config.php
define( 'DISALLOW_FILE_EDIT', true );

If the “Theme File Editor” in the backend is exploited, an attacker with backend access can directly write Webshells. Moreover, a single typo can take down the entire site. This line removes that entry point.

3. Disable PHP Execution in Upload Directory

# Nginx: Do not parse PHP in the upload directory
location ~* ^/wp-content/uploads/.*.php$ {
    deny all;
}

# Also block hidden execution methods
location ~* ^/wp-content/uploads/.*.(php|php5|phtml)$ {
    return 403;
}
# Apache: Place .htaccess in wp-content/uploads
<Files *.php>
    Deny from all
</Files>

This is the highest ROI measure: most upload-based intrusions rely on the ability to execute uploaded PHP files. Disabling execution means that even if a file is uploaded, it remains inert.

4. Backend Login Protection

# Limit login attempts (fail2ban example)
# /etc/fail2ban/jail.local
[wordpress]
enabled  = true
filter   = wordpress
logpath  = /var/log/nginx/access.log
maxretry = 5
findtime = 600
bantime  = 3600
  • Strong passwords + Two-Factor Authentication (2FA): Mandatory for administrator accounts
  • Do not use ‘admin’ as the username: This is the lowest-hanging fruit for brute-force attacks
  • Restrict wp-admin access by source: For sites with fixed office IPs, add an IP whitelist directly
# Allow only specific IPs to access the backend
location ~ ^/wp-admin {
    allow YourIP;
    deny  all;
}

5. Close Unnecessary Entry Points

# Disable XML-RPC (if not used)
location = /xmlrpc.php {
    deny all;
}

XML-RPC is often used for brute-force amplification—a single request can attempt numerous password combinations. If your site does not need it (no client-side publishing, no Jetpack integration), disable it directly.

// wp-config.php: Force backend to use HTTPS
define( 'FORCE_SSL_ADMIN', true );

6. Reduce Information Exposure

// Remove version number from headers
remove_action( 'wp_head', 'wp_generator' );
# Hide Nginx version number
# In the http block of nginx.conf
server_tokens off;

The value of exposing version numbers lies in this: attackers can directly search for known vulnerabilities based on the version, without needing to probe. This is not defense, but merely increasing the attacker’s cost.

7. Updates and Backups

# Check for pending updates
wp core check-update
wp plugin list --update=available
wp theme  list --update=available

# Verify if core files have been tampered with (very useful)
wp core verify-checksums

# Update (backup first)
wp core update
wp plugin update --all

wp core verify-checksums is worth remembering separately: it compares local core files against official checksums, directly telling you which files have been modified. When suspecting a breach, this is the fastest way to locate the issue.

Decision Tree

Hardening Priority (follow this order when time is limited)
├─ ① Disable PHP execution in upload directory    ← Highest ROI, takes ~10 mins
├─ ② Tighten file permissions + set wp-config to 600
├─ ③ Enable DISALLOW_FILE_EDIT
├─ ④ Backend login protection (strong password + 2FA + rate limiting)
├─ ⑤ Disable XML-RPC
└─ ⑥ Regular updates + verified recoverable backups

Suspected Breach
├─ wp core verify-checksums  → Check if core files were modified
├─ find -mtime -7 to find recent changes → Locate intrusion timeframe
└─ Check cron jobs and accounts          → Look for persistent backdoors

Scenario Analysis: Strong Password, Yet Still Compromised

Symptom: A WordPress site suddenly displays abnormal promotional content.
There are no suspicious operations in the backend, and the password appears complex. Initial suspicion points to account leakage.

  1. Don’t rush to change the password; first check login logs for anomalies → Review backend login records and security logs.
    Discovering a large volume of failed attempts in a short period indicates automated brute-forcing rather than credential leakage.
  2. Confirm if the login entry has protection → The backend address was fully open,
    with no frequency limits, effectively allowing unlimited attempts.
  3. Stop the bleeding: Secure the login entry first → Restrict backend access sources and add frequency limits.
    Brute-forcing stops immediately. Do this step first, because without closing the entry, subsequent hardening measures will be continuously probed.
  4. Determine what the attacker has accessed → Check recently added files and accounts,
    focusing on whether there are executable files in the upload directory.
  5. Close the gap: Disable script execution in the upload directory → This is the most common path attackers use to gain further privileges after accessing the backend.
    Block script parsing for this directory at the web layer.
  6. Implement long-term measures → Enable 2FA, disable online editing, and adjust account policies to least privilege.
# Typical characteristics of backend brute-forcing: massive POST requests to the same path in a short time
awk '{print $1, $7}' access.log | grep -i 'wp-login|xmlrpc' | sort | uniq -c | sort -rn | head

# Nginx layer: Limit backend access frequency
# limit_req_zone $binary_remote_addr zone=login:10m rate=10r/m;
# location = /wp-login.php { limit_req zone=login burst=5 nodelay; include fastcgi_params; ... }

# Disable PHP execution in upload directory (most critical action)
# location ~* ^/wp-content/uploads/.*.php$ { deny all; }

# Disable online file editing in backend
# In wp-config.php: define( 'DISALLOW_FILE_EDIT', true );

Root Cause: The backend login entry had neither frequency limits nor source restrictions.
Crucially, the most important remediation measure—disabling script execution in the upload directory—was not configured at the time,
allowing the attacker to directly write executable files after gaining backend access.

Two Key Takeaways:

  • The order of hardening is “close the entry first, then deepen defenses.”
    Without restricting backend access frequency, remaining hardening measures will be systematically mapped out during continuous probing.
  • Disabling script execution in the upload directory has higher priority than most other hardening items.
    It corresponds precisely to the path “how to further compromise the server after the backend falls,”
    offering extremely low cost yet frequently overlooked.

Comparison of Impact and Cost for Seven Hardening Measures

Hardening Measure Blocks What Consequence of Not Doing Cost
File Permissions 644/755 Webshell injection A single upload point grants write access Negligible
Disable Online Editing Direct modification of theme files via backend Backend access equals server file write access Offline theme editing required
Disable PHP Execution in Upload Dir Execution of image-malware uploads Highest frequency breach path Low
Backend Rate Limiting / 2FA Brute-force login Weak passwords lead to immediate compromise One extra step for login
Disable XML-RPC Brute-force amplification and probing DDoS traffic, username enumeration Some clients may fail
Hide Version Number Vulnerability scanning by version Becomes an easy target for automated scanners Low
Auto Updates + Backups Exploitation of known vulnerabilities Patches released but never applied Must be able to rollback before updating

If you can only do three things, do these: Disable PHP execution in the upload directory, protect backend login, and enable auto-updates with rollback-capable backups.
They correspond respectively to “the most commonly exploited entry,” “the easiest-to-guess entry,” and “the escape route in case of incident.”

It is worth noting the DISALLOW_FILE_EDIT measure. It does not block external attackers initially,
but rather the step taken after “the backend has already fallen.” Once an attacker obtains admin credentials, the fastest way to gain server control
is to modify theme files in the backend to write a shell; disabling online editing cuts off this path.

# Confirm upload directory has no executable permissions (Nginx layer)
location ~* ^/wp-content/uploads/.*.php$ {
    deny all;
}

8 Common Pitfalls

  1. Using 777 to fix permission errors: Effectively opens site files for writing to everyone.
  2. Adding security plugins without changing configurations: Plugins cannot manage server-level issues like file permissions or upload directory execution.
  3. Leaving the backend file editor enabled: A single character error causes a white screen, and you may lose backend access.
  4. Allowing PHP execution in the upload directory: This is the decisive condition for successful upload-based intrusions.
  5. Using ‘admin’ as the username: Lowers the difficulty of brute-forcing to the minimum.
  6. Ignoring XML-RPC: Leaving it open when unused creates an entry point for brute-force amplification.
  7. Never updating plugins: Plugin vulnerabilities are a primary source of breaches, far more common than core vulnerabilities.
  8. Having backups but never verifying recovery: Discovering backups are unusable during an actual incident is the worst-case scenario.

Real Customer Feedback (From Cloud Market Reviews and Consultations for Similar Products)

The following excerpts are from real buyer reviews and consultations for similar O&M services on Alibaba Cloud / Tencent Cloud / Huawei Cloud Cloud Markets (service providers include our store and peers, provided solely for reference of real feedback, not fictitious tickets from this site):

10***09 2024-03-18 5.0 Convenient & Stable | Clean Interface | Comprehensive After-sales (User did not fill in review content)

FREE CHECKUP

Free server checkup

We will send a problem checklist and remediation advice within one business day — no obligation to engage.

135 410 16684
Weekdays Mon – Fri 10:00 – 22:00 (UTC+8) · 7×24 emergency response
Call now
CONTACT

Contact Us

How can we help?

* Required