WordPress Site Security Audit
A security audit is not installing Wordfence and clicking "Scan". It is a systematic check of all attack vectors: outdated software, incorrect access rights, vulnerabilities in theme and plugin code, server configuration, leaked credentials.
Reconnaissance: What an Attacker Sees
# Check from external observer perspective
curl -I https://yourdomain.com/wp-json/
curl -s https://yourdomain.com/wp-json/wp/v2/users | python3 -m json.tool
# REST API by default exposes user list
# WPScan scanning (specialized tool)
wpscan --url https://yourdomain.com \
--enumerate u,p,t,cb \
--api-token YOUR_WPSCAN_TOKEN
# u - users, p - plugins, t - themes, cb - config backups
WPScan is free for 25 API requests per day. Shows: WordPress version, plugin list with versions, known CVEs, enumerated users.
Audit Checklist
Versions and Updates:
- WordPress core — current version
- All plugins — current versions
- PHP — 8.1+, PHP 7.x — EOL since December 2022
- MySQL/MariaDB — current version
Authentication:
- Login
adminis not used - Administrator passwords: check haveibeenpwned.com
- 2FA enabled for all administrators
- Password brute force attempts blocked (rate limiting)
- XML-RPC disabled or protected
File Permissions:
# Correct permissions
find /var/www/yourdomain.com -type d -exec chmod 755 {} \;
find /var/www/yourdomain.com -type f -exec chmod 644 {} \;
chmod 600 /var/www/yourdomain.com/wp-config.php
# Check files with suspicious permissions
find /var/www/yourdomain.com -type f -perm /o+w
find /var/www/yourdomain.com -name "*.php" -newer /var/www/yourdomain.com/wp-config.php
WordPress Configuration:
// What should be in wp-config.php
define('DISALLOW_FILE_EDIT', true);
define('DISALLOW_FILE_MODS', true); // blocks plugin installation
define('WP_DEBUG', false); // not in production
define('WP_DEBUG_DISPLAY', false);
define('FORCE_SSL_ADMIN', true);
Information Disclosure:
-
readme.html,license.txt,wp-config-sample.phpdeleted - WordPress version hidden from HTML and RSS
-
X-Powered-Byheader removed - Directory listing disabled (Nginx:
autoindex off)
REST API:
// Hide user list from REST API
add_filter('rest_endpoints', function (array $endpoints): array {
if (isset($endpoints['/wp/v2/users'])) {
unset($endpoints['/wp/v2/users']);
unset($endpoints['/wp/v2/users/(?P<id>[\d]+)']);
}
return $endpoints;
});
Vulnerability Code Analysis
# PHPCS with WordPress Coding Standards
composer require --dev squizlabs/php_codesniffer wp-coding-standards/wpcs
vendor/bin/phpcs --standard=WordPress-Security wp-content/themes/my-theme/
# Search for potentially dangerous functions
grep -r "eval(" wp-content/themes/ wp-content/plugins/
grep -r "base64_decode(" wp-content/themes/ wp-content/plugins/
grep -r "system(" wp-content/themes/ wp-content/plugins/
grep -r "\$_GET\[" wp-content/themes/ wp-content/plugins/ | grep -v "sanitize\|esc_"
Check .htaccess / Nginx Configuration
# Mandatory blocks in Nginx
location ~ /\.(ht|git|svn) { deny all; }
location = /wp-config.php { deny all; }
location ~* /(?:uploads|files)/.*\.php$ { deny all; }
location = /xmlrpc.php { deny all; }
# Security headers
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
SSL and Headers
# Check SSL configuration
testssl.sh --full https://yourdomain.com
# Check security headers
curl -I https://yourdomain.com | grep -i "x-content\|x-frame\|strict-transport\|content-security"
Report Contents
After the audit, client receives:
- List of found vulnerabilities with severity assessment (Critical/High/Medium/Low)
- Specific recommendations for fixing each
- Prioritized remediation plan
- Preventive measures checklist
Timeline
WordPress site security audit with report preparation — 1–2 days. Remediation of found issues — depends on quantity and complexity.







