solenya.info

Anonymous user enumeration on a WordPress REST API via the ?rest_route= bypass

2026-08-11 · low European telecom brand (Tier 2)
Target redacted. This finding is not submitted to the program nor publicly disclosed yet, so hostnames are replaced with redacted.example and account identifiers are removed. The technical detail is kept intact.

Summary

An unauthenticated attacker could list every registered user of the WordPress site with a single GET request. The site blocked /wp-json, /wp-login.php and xmlrpc.php, but the classic /?rest_route= query-string form of the REST API was not covered, so the block was cosmetic.

Impact

User enumeration is the first stage of a credential-stuffing chain: real names, slugs and Gravatar hashes (MD5 of the email, rainbow-table friendly) give an attacker a validated username list plus a path to the email addresses (PII). No authentication and no victim interaction required.

Reproduction

GET /?rest_route=/wp/v2/users&per_page=100 HTTP/1.1
Host: redacted.example
Accept: application/json

Response: 200 OK with a JSON array of users (id, name, slug, avatar_urls).

The blocking was inconsistent:

RequestResult
GET /wp-json/wp/v2/users404 (blocked)
GET /wp-login.php404 (blocked)
POST /xmlrpc.php403 (blocked)
GET /?rest_route=/wp/v2/users&per_page=100200 with data

Root cause

The hardening was applied to URL paths only. In WordPress the REST API is also reachable through the rest_route query parameter, which never touches /wp-json and therefore skipped every rule.

Severity

CVSS 3.1 5.3 — AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N. Programs usually triage it as P4/Low because the disclosure alone is not highly sensitive.

Remediation

Lesson

"Blocked" endpoints deserve a second request in their alternative form. One extra parameter changed a 404 into a full user dump.