
PoC: divulgación de esquema OpenAPI sin autenticación en changedetection.io (CVE-2026-71203, Media 5.3)
Producto: dgtlmoon/changedetection.io — v0.55.7
Archivo: changedetectionio/api/Spec.py
CWE: CWE-306 — Autenticación faltante para función crítica
CVSS 3.1: AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N — 5.3 (Media)
CNA: Turan Security · Registro CVE
Los recursos de la API REST de changedetection.io están protegidos por un decorador @auth.check_token
que valida la cabecera x-api-key del llamante — excepto el recurso Spec registrado en
/api/v1/full-spec (changedetectionio/api/Spec.py), cuyo método get no lleva ni
@auth.check_token ni @validate_openapi_request.
Cualquier cliente de red no autenticado puede recuperar el esquema OpenAPI completo de la instancia, revelando la superficie completa de la API interna (todas las rutas de recursos, parámetros y estructuras de respuesta) sin presentar ninguna clave API. Si bien el esquema en sí no es información confidencial del usuario, proporciona al atacante un mapa completo y autoritativo de todos los demás endpoints de la API a los que atacar — lo que reduce el coste del reconocimiento adicional contra los recursos realmente protegidos de la instancia.
GET /api/v1/full-spec HTTP/1.1
Host: target-instance
No se requiere cabecera x-api-key, cookie ni ninguna credencial. La respuesta es el documento
completo de la especificación OpenAPI.
Prueba de concepto (Python):
import requests
import sys
target = sys.argv[1] if len(sys.argv) > 1 else "http://localhost:5000"
resp = requests.get(f"{target}/api/v1/full-spec", timeout=10)
print(f"[*] Status: {resp.status_code}")
if resp.status_code == 200:
print("[+] Full OpenAPI schema disclosed with zero authentication:")
print(resp.text[:1000])
Todos los demás recursos REST de la API están registrados con @auth.check_token (y
@validate_openapi_request) aplicado a sus métodos de controlador; el método get del recurso
Spec no estaba decorado de la misma manera, dejándolo como el único endpoint no autenticado en una
superficie que de otro modo está protegida por clave API.
Aplique @auth.check_token a Spec.get() de forma coherente con todos los demás recursos de la
API, o, si se pretende que el esquema sea público, convierta eso en una decisión explícita y
documentada en lugar de una inconsistencia.