
Framework di test differenziale per implementazioni HTTP
HTTP Garden è una raccolta di server HTTP e proxy configurati per essere componibili, insieme a script per interagire con essi in un modo che rende la ricerca di vulnerabilità molto molto più facile. Per alcune belle demo delle vulnerabilità che puoi trovare con HTTP Garden, guarda il nostro talk allo ShmooCon 2024.
Vorremmo ringraziare i nostri amici di Galois, Trail of Bits, Narf Industries e Dartmouth College per aver reso possibile questo progetto.
Questo materiale si basa su un lavoro supportato dalla Defense Advanced Research Projects Agency (DARPA) con numero di contratto HR0011-19-C-0076.
pip) o dal gestore di pacchetti del tuo sistema:docker
pyyaml
tqdm
Se installi i pacchetti Python con il gestore di pacchetti del tuo sistema, tieni presente che i nomi dei pacchetti potrebbero dover essere preceduti da py3-, python3- o python-, a seconda del sistema.
./garden.sh start --build gunicorn hyper nginx haproxy
./garden.sh repl
garden> payload 'GET / HTTP/1.1\r\nHOST: a\r\n\r\n' | transduce haproxy | fanout | grid
'GET / HTTP/1.1\r\nHOST: a\r\n\r\n'
⬇️ haproxy
'GET / HTTP/1.1\r\nhost: a\r\n\r\n'
gunicorn: [
HTTPRequest(
method=b'GET', uri=b'/', version=b'1.1',
headers=[
(b'host', b'a'),
],
body=b'',
),
]
hyper: [
HTTPRequest(
method=b'GET', uri=b'/', version=b'1.1',
headers=[
(b'host', b'a'),
],
body=b'',
),
]
nginx: [
HTTPRequest(
method=b'GET', uri=b'/', version=b'1.1',
headers=[
(b'host', b'a'),
(b'content-length', b''),
(b'content-type', b''),
],
body=b'',
),
]
g
u
n
i h n
c y g
o p i
r e n
n r x
+-----
gunicorn|✓ ✓ ✓
hyper | ✓ ✓
nginx | ✓
Sembra che siano tutti d'accordo. (Nota che anche se Nginx ha aggiunto le intestazioni content-length e content-type, il Garden ne è consapevole e non lascia che questa discrepanza insignificante compaia nell'output di grid.)
Proviamo un payload che usa una semplice terminazione di riga LF in un corpo di messaggio in chunked. Questo è vietato dalla specifica.
garden> payload 'POST / HTTP/1.1\r\nHost: a\r\nTransfer-Encoding: chunked\r\n\r\n0\n\r\n' | fanout | grid
gunicorn: [
HTTPResponse(version=b'1.1', method=b'400', reason=b'Bad Request'),
]
hyper: [
]
nginx: [
HTTPRequest(
method=b'POST', uri=b'/', version=b'1.1',
headers=[
(b'transfer-encoding', b'chunked'),
(b'host', b'a'),
(b'content-length', b'0'),
(b'content-type', b''),
],
body=b'',
),
]
g
u
n
i h n
c y g
o p i
r e n
n r x
+-----
gunicorn|✓ ✓ X
hyper | ✓ X
nginx | ✓
Ok, quindi Gunicorn ha risposto 400, Hyper non ha risposto e Nginx ha accettato. Questa è una violazione della specifica da parte degli autori di Nginx che non hanno intenzione di correggere.
Potresti anche aver notato che, anche se Gunicorn e Hyper non hanno avuto esattamente la stessa risposta, nell'output di grid precedente risultavano in accordo.
Questo perché le loro risposte sono sostanzialmente equivalenti (un rifiuto del messaggio), e il Garden ne tiene conto.
imagesLa directory images contiene una sottodirectory per ogni server HTTP e trasduttore nel Garden.
Ogni target ha la propria immagine Docker.
Tutti i programmi vengono compilati dal sorgente quando possibile.
Per poter compilare facilmente più versioni di ciascun target, tutti i target sono parametrizzati con un URL del repository (APP_REPO), un nome di branch (APP_BRANCH) e un hash di commit (APP_VERSION).
toolsLa directory tools contiene gli script usati per interagire con i server. Al suo interno troverai
probe_quirks.py: uno script per elencare le stranezze innocue del parsing HTTP nei sistemi in test, da ignorare durante il fuzzing,repl.py: l'interfaccia utente principale dell'HTTP Garden,update.py: uno script per aggiornare gli hash dei commit in docker-compose.yml,|-| | aiohttp | | apache_httpd | | apache_tomcat | | appweb | | aws_c_http | | cpp_httplib | | eclipse_grizzly | | eclipse_jetty | | fasthttp | | go_stdlib | | gunicorn | | h2o | | haproxy_fcgi | | hyper | | hypercorn | | ktor | | libevent | | libmicrohttpd | | libsoup | | lighttpd | | mongoose | | netty | | nginx | | node_stdlib | | openbsd_httpd | | openlitespeed | | openwrt_uhttpd | | protocol_http1 | | puma | | tornado | | | | | | | | | | | | |
|-| | apache_httpd_proxy | | apache_traffic_server | | envoy | | go_stdlib_proxy | | h2o_proxy | | haproxy | | lighttpd_proxy | | nghttpx | | nginx_proxy | | openlitespeed_proxy | | pound | | squid | | varnish | | yahns_proxy |
Le seguenti sono le spiegazioni di alcune omissioni degne di nota dal Garden:
Vedi TROPHIES.md per un elenco completo dei bug che il Garden ha trovato.
| Nome | Motivazione |
|---|
| Anything from Microsoft | MSRC ci ha detto che "l'HTTP smuggling non è considerato una vulnerabilità", e non sento alcun bisogno particolare di aiutare Microsoft. |
| unicorn | Usa lo stesso parser HTTP di yahns. |
| SwiftNIO | Usa llhttp per il parsing HTTP, già coperto da node_stdlib. |
| Bun | Usa picohttpparser per il parsing HTTP, già coperto da h2o. |
| Deno | Usa hyper per il parsing HTTP, già presente nel Garden. |
| Daphne | Usa twisted per il parsing HTTP, già presente nel Garden. |
| pitchfork | Usa lo stesso parser di yahns. |
| nghttpx | Usa lhttp per il parsing HTTP, già coperto da node_stdlib. |
| Cheroot | Ignora i nostri report. |
| CherryPy | Usa cheroot per il parsing HTTP. |
| libhttpserver | Usa libmicrohttpd per il parsing HTTP, già presente nel Garden. |
| Werkzeug | Usa la stdlib di CPython per il parsing HTTP, già presente nel Garden. |
| Caddy | Usa la stdlib di Go per il parsing HTTP, già presente nel Garden. |
| Tengine | Usa il parser HTTP di Nginx. |
| OpenResty | Usa il parser HTTP di Nginx. |
| Google Cloud Global External Application Load Balancer | Basato su Envoy. |
| Google Cloud Regional External Application Load Balancer | Basato su Envoy. |
| Phusion Passenger | Usa llhttpd per il parsing HTTP, già coperto da node_stdlib. |
| passim | Usa libsoup per il parsing HTTP, già presente nel Garden. |
| boa | Non mantenuto. |
| Ulfius | Usa libmicrohttpd, già presente nel Garden. |
| Vultr Load Balancer | È semplicemente HAProxy, già presente nel Garden. |
| VMWare Avi Load Balancer | È semplicemente Nginx, già presente nel Garden. |
| Sanic | Usa httptools, già coperto da Uvicorn. |
| CPython http.server | Non destinato all'uso in produzione. |
| openjdk_stdlib | Non offre un canale coerente per la divulgazione delle vulnerabilità. |
| dart_stdlib | Ha ignorato le segnalazioni precedenti. |
| eventlet | La libreria HTTP è solo un fork di quella nella stdlib di CPython. |
| uwsgi | Non supporta i corpi dei messaggi in chunked. |