// TECHNOLOGIES / WORDPRESS

WordPress

WordPress, fingerprinted and probed.

Everything NewScan checks on a WordPress site: core and plugin versions mined from the markup, comments and bundled JS then cross-referenced against an offline CVE dataset, REST-API and ?author= user enumeration, and the xmlrpc.php brute-force and pingback-SSRF surface. Nothing is recorded unless the target is confirmed WordPress — every version is a verbatim match, never a guess, and each active check fires only on a reproduced signal.

Core & plugin fingerprinting

// tool: scan_wordpress

WordPress leaks its version through many channels, and plugins advertise themselves the same way. NewScan mines every one of them — verbatim, never inferred — then cross-references each detected component and version against an offline known-vulnerability dataset for core and plugin CVEs. If no source yields a concrete version, nothing is guessed.

// CORE VERSION SOURCES (PRIORITY ORDER)

# 1 <meta name="generator" ... WordPress X.Y> # 2 /wp-includes/…?ver=X.Y # core asset # 3 <generator>wordpress.org/?v=X.Y # RSS feed # 4 /readme.html "Version X.Y" # 5 "WordPress X.Y" # HTML comments + bundled JS

// PLUGIN DETECTION

# slug + version from the asset path /wp-content/plugins/<slug>/…?ver=X.Y # refined by the plugin's own readme.txt Stable tag: X.Y

Every referenced plugin slug is mapped to a version, refined by its readme.txt Stable tag:, then run through the CVE dataset the same way core is.

// WHY THIS STAYS FALSE-POSITIVE-FREE

Nothing is recorded unless at least one WordPress signature is present — a /wp-content/ or /wp-includes/ path, the generator meta tag, or the api.w.org link header. Every version is a verbatim string pulled from the markup or an asset, so a component is never flagged on a guessed version. A known-vulnerable finding only fires when a concrete, matched version maps to a CVE in the offline dataset.

PRESENCE SIGNATURES (ANY ONE CONFIRMS WORDPRESS)

/wp-content/ · /wp-includes/ <meta generator … wordpress> wordpress.org/?v= <link rel="https://api.w.org/">

User enumeration

// REST API + ?author=N

Usernames are half of every credential. WordPress hands them out through two near-universal channels, and NewScan records only when it actually reads a name back:

// REST-API USER ENUMERATION  medium

GET /wp-json/wp/v2/users -> 200 [{"slug":"admin", …}, {"slug":"editor", …}]

The unauthenticated endpoint returns valid logins to anyone. Flagged only on a 200 with a JSON content-type and at least one real slug/name — mapped to OWASP A01:2021 (CWE-200).

// AUTHOR ENUMERATION  low

GET /?author=1 -> 301 Location: /author/<login>/ (or canonical /author/<login>/ in a 200 body)

WordPress maps user ID 1 to its author archive, disclosing the login. Iterating ?author=N maps every user. Recorded only when the /author/<login>/ slug is actually resolved.

XML-RPC attack surface

// brute-force amplification + pingback SSRF

When xmlrpc.php is enabled it bypasses login rate limits: system.multicall tries hundreds of passwords in a single request, and pingback.ping makes the server fetch an attacker-supplied URL — a blind SSRF and reflected-DoS primitive.

// XML-RPC ENABLED  low

GET /xmlrpc.php -> "XML-RPC server accepts POST requests only" # the enabled signature

Recorded only when the endpoint returns its own enabled banner. Recommendation: disable XML-RPC if unused, or block the pingback and system.multicall methods.

// PINGBACK BLIND SSRF — CONFIRMED OUT-OF-BAND  high

pingback.ping(sourceURI, targetURI) makes WordPress fetch sourceURI server-side. NewScan points it at an OOB collaborator canary and records a verified finding only on a real callback. With no collaborator configured the probe is inert and never sent — so an offline scan can't produce this false positive.

POST /xmlrpc.php (Content-Type: text/xml) <methodCall><methodName>pingback.ping</methodName> <params><param><value><string><canary></string></value></param> <param><value><string>/?p=1</string></value></param></params> </methodCall> # canary callback -> SSRF confirmed (OWASP API7)

Exposure & disclosure

// version · config · known CVEs
Finding How NewScan finds it Severity
Known-vulnerable core A verbatim-matched core version maps to a CVE in the offline dataset. per-CVE
Known-vulnerable plugin A plugin slug + Stable tag / ?ver= version maps to a CVE. per-CVE
REST user enumeration /wp-json/wp/v2/users returns valid usernames unauthenticated. medium
Pingback SSRF OOB-confirmed pingback.ping server-side fetch of an attacker URL. high
Author enumeration ?author=N resolves to /author/<login>/, disclosing logins. low
XML-RPC enabled xmlrpc.php returns its enabled banner — brute-force / pingback surface. low
Version disclosure The core version is exposed via the generator tag, /readme.html, or feed. info

Recent WordPress security issues

// why these checks matter

A sample of the vulnerability classes above, seen in the wild — plugin CVEs that the offline dataset flags on version match, and the XML-RPC brute-force surface these checks are built for.

External links; referenced for context. CVE severities and details are the publishers'.

How it's recorded

// audit-ready evidence

CATEGORY

User enumeration maps to OWASP A01:2021 (CWE-200); pingback SSRF to OWASP API7; CVEs carry their own IDs.

SEVERITY

One calibrated severity per finding that translates into each framework's risk rating and remediation SLA — no inflated numbers.

EVIDENCE

Every finding stores the exact request, the matched version or username, and — for SSRF — the out-of-band callback that confirmed it.

Point it at your site.

NewScan is free and self-hosted — bring your own key. The fingerprinting, user-enumeration, and XML-RPC checks above run in the deterministic floor with no model or provider key at all; the pingback-SSRF confirmation just needs an OOB collaborator configured.