flawopen.com/AI Security/wazuh-mcp-server-webshell-check-ssrf-ghsa-pw2j-pj4h-f5vg
Fallo SSRF en el comprobador de webshell de Wazuh MCP — GHSA-pw2j-pj4h-f5vg
Un nombre de host eludía la comprobación de IP literal de Wazuh-MCP-Server antes de que una herramienta forense lo consultara. La GHSA asigna gravedad Alta y CWE-918; no hay CVE. Corregido en el commit 2bbfe12.[1], [2], [3]
Una recepcionista comprueba que la credencial de una persona no aparezca en una lista de bloqueo y luego le permite elegir una oficina. Revisar solo la credencial impresa no revela que el nombre de la persona apunta a una sala restringida. La corrección comprueba dónde resuelve el nombre y obliga a la conexión a usar ese destino verificado.[1], [3]
Conceptos Clave y Términos
Server-side request forgery (SSRF)- El servidor realiza una solicitud de red a un destino influido por quien lo invoca. Una validación incompleta puede permitirle alcanzar redes a las que la persona no llega directamente.[4], [1]
Resolución DNS y rebinding- Un nombre de host se traduce en una o varias direcciones IP. Si se valida solo el texto o el cliente HTTP vuelve a resolverlo, la conexión puede usar una dirección distinta de la comprobada.[1], [3]
Fijación del destino- La IP validada se vincula a la conexión saliente, mientras el nombre se conserva para las comprobaciones HTTP y TLS. Así se cierra la brecha entre validación y conexión.[3]
Mapeos de marcos
- Referencia CWE para la debilidad descrita en esta guía: CWE-918
- D3-OTF Filtrado del tráfico saliente — La restricción de red saliente de esta guía limita los destinos a los que puede acceder el servicio o el host.
Flujo de Ataque Paso a Paso
Una URL de datos forenses llega al comprobador
La herramienta afectada blueteam_check_webshell recibe una URL para que un analista examine una dirección sospechosa de alojar un webshell. El aviso limita el fallo a esta herramienta, no a todas las funciones de Wazuh-MCP-Server.[1]
El cliente HTTP resuelve el host y sigue redirecciones
Después, la URL validada se entregaba a curl, que realizaba su propia resolución DNS. El aviso también documenta el seguimiento automático de redirecciones sin volver a validar el destino. Esto expone a SSRF si el servidor puede alcanzar direcciones internas y la herramienta recibe una URL influida por contenido no confiable. El impacto depende de la red y del acceso a la herramienta.[1], [3]
El parche valida y fija las direcciones resueltas
El commit 2bbfe12 resuelve registros IPv4 e IPv6, rechaza direcciones no públicas salvo dominios configurados en ALLOWED_INTERNAL_DOMAINS y fija la dirección usada en la solicitud. La ruta corregida no sigue redirecciones automáticamente. La GHSA asigna gravedad Alta y CWE-918; no asigna CVE ni indica un rango de versiones.[1], [3]
Código Fuente: Vulnerable vs. Seguro
El fragmento vulnerable reproduce la lógica pertinente de WebshellCheckInput.validate_url del commit 6bd1fa8; se omiten imports y campos de la clase. Rechaza IP literales no públicas, pero trata el ValueError de un nombre de host como si fuera un dominio y lo acepta sin resolver DNS. El fragmento corregido reproduce _pinned_curl_args del commit 2bbfe12. El validador corregido también llama a _host_pins; el flujo de solicitudes pasa esos argumentos --resolve a curl y valida cada destino de redirección antes del siguiente salto. El parche solo permite destinos internos en dominios configurados explícitamente. Son fragmentos concretos, no un reemplazo completo del flujo de solicitudes URL.[2], [3]
Fragmento de origen: mcp_server/tools/webshell_check.py — validación 6bd1fa8; corrección 2bbfe12
@field_validator("url")
@classmethod
def validate_url(cls, v: str) -> str:
v = v.strip()
if not v.startswith(("http://", "https://")):
raise ValueError(f"URL must start with http:// or https://, got: {v!r}")
# Rechaza IP privadas/reservadas en el host de la URL.
from urllib.parse import urlparse
import ipaddress
host = urlparse(v).hostname
if host:
try:
ip = ipaddress.ip_address(host)
except ValueError:
ip = None # not an IP - domain name, allowed
if ip is not None and (ip.is_private or ip.is_loopback or ip.is_reserved or ip.is_link_local):
raise ValueError(f"URL host is a private/reserved IP: {host}. This tool only accepts public hosts.")
return v
def _pinned_curl_args(url: str) -> tuple[list[str], str | None]:
"""Build curl --resolve args for an already-validated destination."""
import ipaddress
u = urlparse(url)
host = u.hostname
if not host:
return [], "URL has no host."
try:
ipaddress.ip_address(host)
return [], None # Literal IP: no DNS lookup to rebind.
except ValueError:
pass
port = u.port or (443 if u.scheme == "https" else 80)
ips, err = _host_pins(host, _allowed_internal_domains())
if err:
return [], err
args: list[str] = []
for ip in ips:
addr = f"[{ip}]" if ":" in ip else ip
args += ["--resolve", f"{host}:{port}:{addr}"]
return args, None
Lista de Verificación de Seguridad para Ingeniería
- ✓Identifica las instalaciones con la implementación afectada de
blueteam_check_webshell; el aviso enumera commits, no versiones del paquete.[1], [2] - ✓Actualiza al commit
2bbfe12o a una versión posterior que incluya la corrección y comprueba el código desplegado.[3] - ✓Resuelve todos los registros A y AAAA y rechaza cualquier dirección no pública, salvo una excepción interna de dominio muy concreta.[3]
- ✓Vincula la IP validada a la conexión real para evitar que una segunda consulta DNS cambie el destino.[3]
- ✓Desactiva las redirecciones automáticas o valida y fija cada destino de redirección.[1], [3]
- ✓Limita el acceso a la herramienta y la salida de red del servidor; comprueba si usuarios o contenido no confiables controlan el argumento URL.[1]
- ✓Prueba respuestas DNS mixtas, IPv4, IPv6, excepciones internas, redirecciones y fijación sin consultar servicios internos reales.[3]
Fuentes
- Aviso Wazuh-MCP-Server GHSA-pw2j-pj4h-f5vg (sin CVE asignado)
- Código vulnerable en el commit 6bd1fa8 — WebshellCheckInput.validate_url
- Commit de corrección Wazuh-MCP-Server 2bbfe12
- MITRE CWE-918: Server-Side Request Forgery
- The Next Web: fallos SSRF separados en implementaciones MCP
- Ars Technica: Vulnerability in agents from Google and others exposes structural flaw in MCP