Strona główna / Blog / mysql-mcp: SSE otwiera 0.0.0.0

Blog · case study

MySQL MCP Server CVE-2026-59971: stdio jest bezpieczne, SSE otwiera 0.0.0.0 bez auth — kiedy sam transport zmienia cały attack surface

CVE-2026-59971 nie da się sensownie triage'ować po nazwie pakietu i numerze wersji. Ten sam mysql-mcp-server ma inny profil ryzyka zależnie od transportu: w trybie stdio opisany attack path nie występuje, a problem pojawia się przy MCP_TRANSPORT=sse, gdzie serwer uruchamia transport HTTP/SSE bez wymaganych ustawień bezpieczeństwa, bez auth i z domyślnym bindem do 0.0.0.0. Finding „mysql-mcp-server < 0.4.2” to dopiero początek — prawdziwe pytanie brzmi, czy instancja działa w SSE, na jakim interfejsie nasłuchuje i czy ruch może do niej dotrzeć.

CVE-2026-59971 (fix 0.4.2): w SSE SseServerTransport nie dostaje security_settings — brak walidacji Origin/Host (DNS rebinding), brak TrustedHostMiddleware/CORS, bind 0.0.0.0, endpointy bez auth; sink wykonuje SQL.
stdio: opisany attack path nie występuje.

Dwa różne attack paths

Pierwszy — banalny: bind do 0.0.0.0 bez ograniczeń firewall/security group/reverse proxy → zdalny klient wchodzi w SSE i woła narzędzia MCP bez loginu. Drugi — ciekawszy: DNS rebinding. Nawet gdy operator zakłada „usługa lokalna”, przeglądarka użytkownika bywa pośrednikiem: złośliwa domena początkowo wskazuje publiczny adres atakującego, potem po zmianie DNS wskazuje 127.0.0.1/adres prywatny; bez walidacji Host/Origin przeglądarka wysyła request do lokalnego SSE w kontekście tej samej domeny. „Nie wystawiliśmy portu do Internetu” nie jest pełnym dowodem braku reachability.

CVSS 10.0 nie znaczy „każda instalacja krytyczna”

Severity opisuje możliwy skutek w podatnym układzie; exploitability zależy od konfiguracji. Wyłącznie stdio → path nieaktywny. SSE poprawnie izolowany i nieosiągalny → ryzyko niższe. SSE na 0.0.0.0 bez auth → praktycznie natychmiastowy P1. Enrichment: MCP_TRANSPORT, bind address i port, realna reachability, obecność reverse proxy/mTLS/auth gateway, uprawnienia konta MySQL (FILE?). Brak FILE nie ogranicza problemu do wycieku danych — unauthenticated SQL nadal oznacza odczyt/modyfikację/usunięcie zgodnie z prawami konta; RCE zależy od dodatkowych capabilities, nie dopisuj go automatycznie, ale nie zamykaj analizy na CVSS.

Remediation i weryfikacja

Fix w 0.4.2 (włącza DNS-rebinding protection; dokumentacja kieruje do bindu 127.0.0.1). Upgrade to pierwszy krok. Weryfikacja: runtime uruchamia 0.4.2+, SSE nie nasłuchuje szerzej niż trzeba, brak alternatywnego endpointu bez auth, Host/Origin spoza polityki odrzucane, konto DB w least privilege, reverse proxy/network policy nieominięte przez bezpośredni port. Component version bez runtime context daje i false positive (podatny pakiet w instalacji tylko-stdio → Critical), i false negative (usługa uznana za „lokalną” mimo DNS rebindingu i braku Host validation). Właściwy model: vulnerable version + SSE enabled + reachable transport + unauthenticated tool path + database privilege context.

Powiązane na blogu

Źródła

Nota redakcyjna: stan informacji 12 września 2026. CVE-2026-59971 (mysql-mcp-server <0.4.2): profil ryzyka zależy od transportu (stdio vs SSE) i reachability. Brak potwierdzenia active exploitation. Artykuł podkreśla model finding oparty o transport, reachability i uprawnienia konta DB.

Zapamiętaj jedno

Component version bez runtime context daje zarówno false positive, jak i false negative. Właściwy finding to nie „package < 0.4.2”, lecz vulnerable version + SSE enabled + reachable transport + unauthenticated tool path + database privilege context.