flawopen.com/AI Security/wazuh-mcp-server-webshell-check-ssrf-ghsa-pw2j-pj4h-f5vg
SSRF-Schwachstelle im Wazuh-MCP-Webshell-Prüfer — GHSA-pw2j-pj4h-f5vg
Ein Hostname umging die Prüfung literaler IP-Adressen in Wazuh-MCP-Server, bevor ein Forensik-Tool ihn abrief. Die GHSA stuft den Fehler als Hoch ein und nennt CWE-918; eine CVE gibt es nicht. Behoben in Commit 2bbfe12.[1], [2], [3]
Eine Empfangskraft prüft, ob ein Ausweis auf einer Sperrliste steht, und lässt die Person danach ein Büro wählen. Die Prüfung der aufgedruckten Kennung zeigt nicht, dass der Name zu einem gesperrten Raum führt. Die Korrektur prüft die Namensauflösung und bindet die Verbindung an das geprüfte Ziel.[1], [3]
Kernkonzepte & Begriffe
Server-side request forgery (SSRF)- Ein Server sendet eine Netzwerkanfrage an ein Ziel, das der Aufrufer beeinflusst. Unvollständige Prüfungen können den Zugriff auf Netze ermöglichen, die der Aufrufer selbst nicht erreichen kann.[4], [1]
DNS-Auflösung und Rebinding- Ein Hostname wird in eine oder mehrere IP-Adressen aufgelöst. Prüft man nur den Text oder löst der HTTP-Client den Namen später erneut auf, kann die Verbindung ein anderes Ziel verwenden als das geprüfte.[1], [3]
Zieladressbindung- Die geprüfte IP-Adresse wird an die ausgehende Verbindung gebunden; der Hostname bleibt für HTTP- und TLS-Prüfungen erhalten. So wird die Lücke zwischen Prüfung und Verbindung geschlossen.[3]
Framework-Zuordnungen
- CWE-Referenz für die in diesem Leitfaden beschriebene Schwachstelle: CWE-918
- D3-OTF Filterung des ausgehenden Datenverkehrs — Die in diesem Leitfaden beschriebene Beschränkung des ausgehenden Netzwerkverkehrs begrenzt die für den Dienst oder Host erreichbaren Ziele.
Schritt-für-Schritt Angriffsablauf
Eine URL aus Forensikdaten erreicht das Prüfwerkzeug
Das betroffene Tool blueteam_check_webshell nimmt eine URL entgegen, damit Analysten eine Adresse untersuchen können, die möglicherweise ein Webshell hostet. Die Meldung grenzt den Fehler auf dieses Tool ein, nicht auf alle Funktionen von Wazuh-MCP-Server.[1]
Der HTTP-Client löst das Ziel auf und folgt Weiterleitungen
Die validierte URL wurde anschließend an curl übergeben, das selbst DNS auflöste. Die Meldung beschreibt außerdem automatisches Folgen von Weiterleitungen ohne erneute Prüfung. SSRF ist möglich, wenn der Server interne Ziele erreichen kann und das Tool eine von nicht vertrauenswürdigen Daten beeinflusste URL erhält. Die tatsächliche Auswirkung hängt von Netz und Toolzugriff ab.[1], [3]
Der Patch prüft und bindet aufgelöste Adressen
Commit 2bbfe12 löst IPv4- und IPv6-Einträge auf, lehnt nicht öffentliche Adressen ab, sofern der Host nicht ausdrücklich in ALLOWED_INTERNAL_DOMAINS steht, und bindet die gewählte Adresse an die Anfrage. Der korrigierte Abruf folgt Weiterleitungen nicht automatisch. Die GHSA nennt Schweregrad Hoch und CWE-918, aber keine CVE und keinen Paketversionsbereich.[1], [3]
Quellcode: Verwundbar vs. Sicher
Der verwundbare Ausschnitt gibt die relevante Logik aus WebshellCheckInput.validate_url in Commit 6bd1fa8 wieder; Imports und Klassenfelder sind ausgelassen. Er weist nicht öffentliche IP-Literale zurück, behandelt aber den ValueError eines Hostnamens als Domain und akzeptiert ihn ohne DNS-Auflösung. Der gehärtete Ausschnitt gibt _pinned_curl_args aus Fix-Commit 2bbfe12 wieder. Der korrigierte Validator ruft außerdem _host_pins auf; der Anfrageablauf übergibt curl diese --resolve-Argumente und prüft jedes Redirect-Ziel vor dem nächsten Schritt. Interne Ziele sind nur für ausdrücklich konfigurierte Domains zulässig. Das sind gezielte Quelltextauszüge, kein vollständiger Ersatz des URL-Abrufpfads.[2], [3]
Quelltextauszug: mcp_server/tools/webshell_check.py — Prüfung 6bd1fa8; Korrektur 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}")
# Private/reservierte IP-Adressen im URL-Host ablehnen.
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
Checkliste für Engineering & Systemsicherheit
- ✓Ermitteln Sie Installationen mit der betroffenen Implementierung von
blueteam_check_webshell; die Meldung nennt Commits, keinen Paketversionsbereich.[1], [2] - ✓Aktualisieren Sie auf Commit
2bbfe12oder eine spätere Version mit der Korrektur und prüfen Sie den bereitgestellten Quellstand.[3] - ✓Lösen Sie alle A- und AAAA-Einträge auf und lehnen Sie nicht öffentliche Adressen ab, sofern keine eng begrenzte interne Domain-Ausnahme nötig ist.[3]
- ✓Binden Sie die geprüfte IP an die tatsächliche Verbindung, damit eine spätere DNS-Abfrage das Ziel nicht ändert.[3]
- ✓Deaktivieren Sie automatische Weiterleitungen oder prüfen und binden Sie jedes Weiterleitungsziel erneut.[1], [3]
- ✓Beschränken Sie den Toolzugriff und den ausgehenden Netzwerkzugriff; klären Sie, ob nicht vertrauenswürdige Daten das URL-Argument steuern.[1]
- ✓Testen Sie gemischte DNS-Antworten, IPv4, IPv6, interne Ausnahmen, Weiterleitungen und Adressbindung ohne echte interne Dienste aufzurufen.[3]
Quellen
- Wazuh-MCP-Server-Sicherheitsmeldung GHSA-pw2j-pj4h-f5vg (keine CVE)
- Verwundbarer Quelltext in Commit 6bd1fa8 — WebshellCheckInput.validate_url
- Wazuh-MCP-Server-Korrekturcommit 2bbfe12
- MITRE CWE-918: Server-Side Request Forgery
- The Next Web: getrennte SSRF-Fehler in MCP-Implementierungen
- Ars Technica: Vulnerability in agents from Google and others exposes structural flaw in MCP