WordPress expone endpoints REST para acceder a datos (posts, páginas, taxonomías y también usuarios). El endpoint de usuarios existe como GET /wp/v2/users.
Ahora bien: que el endpoint “exista” no significa automáticamente que haya exposición sensible. La pregunta correcta es: ¿qué datos entrega a un usuario no autenticado y con qué utilidad ofensiva?
📌 Guía completa: Seguridad WordPress (checklist + prioridades).
✅ Acción rápida: Iniciar auditoría gratis y recibir evidencias en minutos.
1) Cuándo hay exposición real (criterio técnico, no percepciones)
Caso A — Exposición real por “datos sensibles” en la respuesta
Existe exposición real si un usuario no autenticado puede obtener campos que deberían estar restringidos (ej.: usuario/login, email, roles, capabilities).
En el esquema oficial del endpoint de usuarios, WordPress delimita campos por “contexto”:
username(login) aparece en contextoedit.emailaparece en contextoedit.roles,capabilitiesyextra_capabilitiesaparecen en contextoedit.
Implicación operativa: por diseño, en condiciones normales esos campos no deberían estar disponibles en respuestas anónimas (contexto por defecto view).
Si aun así aparecen, normalmente hablamos de:
- plugins/endpoints personalizados con permisos mal definidos,
- filtros que amplían campos,
- o lógica de autorización incorrecta.
Esto encaja directamente con el riesgo de OWASP API Security: un endpoint es vulnerable si expone propiedades sensibles de un objeto a quien no debería verlas (excesiva exposición de datos / autorización a nivel de propiedad).
Caso B — Exposición “útil” por enumeración de usuarios/author slugs
Aunque no se expongan emails o roles, puede existir exposición útil si el endpoint permite:
- listar usuarios que han publicado (parámetros como
who=authors/has_published_postsexisten en el endpoint), - y con ello obtener identificadores públicos (p. ej.,
slug,name, enlaces de autor).
Esto no siempre es un fallo, porque muchos sitios publican autores de forma pública igualmente (páginas de autor, bylines, sitemaps, etc.). Aun así, sí puede reducir el coste de ataque cuando se combina con:
- login expuesto,
- credenciales débiles,
- falta de 2FA,
- y ausencia de rate limiting.
2) Cómo verificamos (paso a paso y con evidencia)
- Petición anónima al listado de usuarios
curl -s https://su-dominio.tld/wp-json/wp/v2/users | head
- Confirmamos si devuelve 200 y cuántos registros.
- Revisamos qué campos aparecen (especialmente si aparece algo propio de
edit).
- Verificar si hay escalado de contexto
- Probamos si un anónimo puede forzar
context=edit. (Por diseño no debería). - Si aparecieran
username/email/roles/capabilities, lo tratamos como exposición real.
- Revisar autenticación real
WordPress indica que la REST API usa autenticación por cookies y nonces; si no se envía nonce, la request se trata como no autenticada, incluso estando logueados.
Esto es importante para evitar diagnósticos erróneos durante pruebas.
3) Mitigación sin romper el sitio: enfoque por capas
Capa 1 — Corregir autorización en endpoints (la base)
Si existe código custom (theme/plugin) o endpoints propios, la mitigación correcta es autorización explícita, no “ocultar” rutas.
WordPress es claro: al registrar endpoints custom debemos definir una permission_callback para controlar si el usuario puede realizar la acción.
Además, recomienda basar la decisión en capabilities (current_user_can) más que en “está logueado o no”.
Objetivo: que ningún endpoint devuelva propiedades sensibles a quien no corresponda, alineado con OWASP API3 (evitar exposición excesiva y validar acceso a propiedades).
Capa 2 — Minimización de datos (solo lo necesario)
Aunque el endpoint sea público por necesidad (p. ej., headless), debemos:
- retornar únicamente campos imprescindibles,
- evitar respuestas genéricas que “serializan todo” (OWASP lo desaconseja: seleccionar propiedades específicas).
Capa 3 — WAF y rate limiting (contención de abuso)
Cuando el riesgo es enumeración + automatización, el control más rentable suele ser:
- rate limiting por ruta (especialmente
/wp-json/wp/v2/users), - reglas anti-bot y umbrales por IP / comportamiento,
- y, si el negocio lo permite, bloqueo directo del endpoint de usuarios para no autenticados.
Aquí el punto clave es ser quirúrgicos: no recomendamos bloquear toda la REST API, porque puede romper editor de bloques, integraciones y plugins. Recomendamos actuar sobre:
/wp-json/wp/v2/users(y, según caso,/wp-json/wp/v2/users/*),- y/o condiciones concretas (volumen, países, ASN, UA, etc.).
4) Estrategias recomendadas según escenario
Escenario 1 — Sitio “clásico” (no headless), sin necesidad de listar usuarios por API
- Bloquear o exigir autenticación para
/wp/v2/users. - Rate limit en WAF para requests a
users. - Verificar que no se rompen flujos legítimos (normalmente es seguro si no hay consumidor externo).
Escenario 2 — Headless o integraciones que consumen usuarios
- Mantener endpoint, pero:
- asegurar permisos correctos,
- reducir campos al mínimo,
- autenticar mediante mecanismos soportados (cookies/nonces en contexto WP; o Application Passwords sobre HTTPS cuando aplique).
Escenario 3 — Exposición por plugin/custom endpoint
- Auditar endpoints custom y su
permission_callback. - Aplicar principio de mínimo privilegio (capabilities).
- Validar que datos sensibles solo aparecen en contextos autorizados (p. ej.,
edit).
5) Checklist de cierre (criterios de aceptación)
- Un usuario no autenticado no obtiene
username,email,rolesnicapabilitiespor REST. - Los endpoints custom implementan
permission_callbacky validan capabilities. - Se ha minimizado la respuesta (solo propiedades necesarias), evitando exposición excesiva.
- Existe rate limiting/WAF específico para rutas de usuarios si hay abuso o enumeración.
- Se ha probado que el sitio sigue operando (editor, frontend, plugins críticos).