A default WordPress deployment often exposes enough surface for user enumeration, optimized brute-force patterns, and known-core vulnerability exploitation.
This article documents the exact field workflow I used across three critical areas:
- Core-version CVE correlation (NVD + OSV)
- XML-RPC method mapping with
system.multicallfocus - REST API user enumeration checks
1) Baseline first: target and version acquisition
TARGET="https://domain.tld"
SITE_VERSION=$(curl -skL "$TARGET" | grep -oP 'WordPress\s+\K[0-9]+\.[0-9]+(\.[0-9]+)?' | head -n1)
if [[ -z "$SITE_VERSION" ]]; then
SITE_VERSION=$(curl -skL "$TARGET/readme.html" | grep -oP 'Version\s+\K[0-9]+\.[0-9]+(\.[0-9]+)?' | head -n1)
fi
2) CVE lookup automation (NVD + OSV links)
fetch_nvd_cves() {
local wp_ver="$1"
local encoded="wordpress%20$wp_ver"
curl -s "https://services.nvd.nist.gov/rest/json/cves/2.0?keywordSearch=$encoded&keywordExactMatch" |
jq -r '.vulnerabilities[] |
"- " + .cve.id + ": " +
(.cve.descriptions[] | select(.lang=="en").value) +
" (https://osv.dev/vulnerability/" + .cve.id + ")"'
}
nvd_cves=$(fetch_nvd_cves "$SITE_VERSION")
if [[ -n "${nvd_cves//[[:space:]]/}" ]]; then
echo "$nvd_cves"
else
echo "No CVE found for version $SITE_VERSION"
fi
Key bug fix: always capture function output before validation.
3) XML-RPC method audit
XMLRPC_GET_METHODS=$(curl -sLk -X POST "$TARGET/xmlrpc.php" \
-H "Content-Type: text/xml" \
--data '<?xml version="1.0"?>
<methodCall><methodName>system.listMethods</methodName></methodCall>')
declare -a XMLRPC_METHODS_LIST
while IFS= read -r METHOD; do
XMLRPC_METHODS_LIST+=("$METHOD")
done < <(echo "$XMLRPC_GET_METHODS" | grep -oP '(?<=<string>).*?(?=</string>)')
if printf '%s\n' "${XMLRPC_METHODS_LIST[@]}" | grep -q "^system.multicall$"; then
echo "system.multicall ENABLED – critical brute-force risk"
fi
system.multicall drastically improves credential attack efficiency by batching attempts in a single request.
4) REST API user enumeration checks
REST_USERS=$(curl -sk "$TARGET/wp-json/wp/v2/users" |
jq -r '.[] | "\(.id): \(.name) (\(.slug))"' 2>/dev/null)
if [[ -n "$REST_USERS" ]]; then
echo "$REST_USERS"
if echo "$REST_USERS" | grep -q '^1:'; then
echo "ALERT: ID 1 user is exposed"
fi
if echo "$REST_USERS" | grep -Eiq 'admin|administrator|root'; then
echo "WARNING: administrative slugs detected"
fi
fi
Note: unauthenticated REST does not expose role directly, but public metadata still provides strong intelligence for targeted attacks.
5) Hardening roadmap from findings
- Disable or strictly control XML-RPC (
xmlrpc.php) - Restrict REST author exposure for anonymous users
- Add NGINX/WAF rate limiting for sensitive endpoints
- Patch core/plugins/themes with tracked SLA
- Re-run audit after remediation for closure evidence
6) Technical conclusion
This audit model moves WordPress security from assumptions to measurable evidence. With a Bash-first approach and reproducible checks, incident triage becomes faster and hardening decisions become objective.
This post is licensed under CC BY-NC.
Comments
Join the discussion below.
Comments are not configured yet. Add Cusdis settings in /assets/json/config/blog-comments-config.json.