
HTTP 구현체를 위한 차등 테스트 프레임워크
HTTP Garden은 구성 가능하도록 설계된 HTTP 서버와 프록시 모음으로, 취약점을 훨씬 쉽게 찾을 수 있는 방식으로 이들과 상호작용하는 스크립트를 함께 제공합니다. HTTP Garden으로 찾을 수 있는 취약점에 대한 멋진 데모를 보려면 ShmooCon 2024 발표를 확인하세요.
이 프로젝트를 가능하게 해 주신 Galois, Trail of Bits, Narf Industries, Dartmouth College의 친구들에게 감사드립니다.
이 자료는 계약 번호 HR0011-19-C-0076에 따라 국방고등연구계획국(DARPA)의 지원을 받은 작업을 기반으로 합니다.
pip) 또는 시스템 패키지 관리자에서 설치할 수 있습니다:docker
pyyaml
tqdm
Python 패키지를 시스템 패키지 관리자로 설치하는 경우, 시스템에 따라 패키지 이름 앞에 py3-, python3- 또는 python- 접두사가 필요할 수 있음을 유의하세요.
./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 | ✓
모두 일치하는 것 같습니다. (Nginx가 content-length 및 content-type 헤더를 추가했지만, Garden은 이를 인지하고 있어 이 사소한 불일치가 grid 출력에 나타나지 않게 합니다.)
청크 메시지 본문에서 순수 LF 줄바꿈을 사용하는 페이로드를 시도해 보겠습니다. 이는 사양에서 허용되지 않습니다.
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 | ✓
자, Gunicorn은 400을 응답했고, Hyper는 응답하지 않았으며, Nginx는 수락했습니다. 이는 Nginx 개발자들이 고치려 하지 않는 사양 위반입니다.
또한 Gunicorn과 Hyper가 정확히 동일한 응답을 보내지 않았음에도 앞서 grid 출력에서 일치하는 것으로 표시된 것을 눈치챘을 수도 있습니다.
이는 두 응답이 본질적으로 동등(메시지 거부)하기 때문이며, Garden은 이를 고려합니다.
imagesimages 디렉터리에는 Garden의 각 HTTP 서버와 트랜스듀서별 하위 디렉터리가 포함되어 있습니다.
각 대상은 자체 Docker 이미지를 갖습니다.
가능한 경우 모든 프로그램은 소스에서 빌드됩니다.
각 대상의 여러 버전을 쉽게 빌드할 수 있도록 모든 대상은 저장소 URL(APP_REPO), 브랜치 이름(APP_BRANCH), 커밋 해시(APP_VERSION)로 파라미터화되어 있습니다.
toolstools 디렉터리에는 서버와 상호작용하는 데 사용되는 스크립트가 포함되어 있습니다. 그 안에는 다음이 있습니다:
probe_quirks.py: 퍼징 중 무시할 테스트 대상 시스템의 무해한 HTTP 파싱 특성(quirks)을 열거하는 스크립트,repl.py: HTTP Garden의 기본 사용자 인터페이스,update.py: 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 | | twisted | | undertow | | uvicorn | | waitress | | webrick | | yahns |
|-| | 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 |
다음은 Garden에서 눈에 띄게 제외된 몇 가지 항목에 대한 설명입니다:
| Name | Rationale |
|---|---|
| Anything from Microsoft | MSRC가 "HTTP 스머글링은 취약점으로 간주하지 않는다"고 알려왔고, 저는 Microsoft를 도와야 할 특별한 필요성을 느끼지 않습니다. |
| unicorn | yahns와 동일한 HTTP 파서를 사용합니다. |
| SwiftNIO | HTTP 파싱에 node_stdlib에 이미 포함된 llhttp를 사용합니다. |
| Bun | HTTP 파싱에 h2o에 이미 포함된 picohttpparser를 사용합니다. |
| Deno | HTTP 파싱에 이미 Garden에 있는 hyper를 사용합니다. |
| Daphne | HTTP 파싱에 이미 Garden에 있는 twisted를 사용합니다. |
| pitchfork | yahns와 동일한 파서를 사용합니다. |
| nghttpx | HTTP 파싱에 node_stdlib에 이미 포함된 lhttp를 사용합니다. |
| Cheroot | 우리의 보고를 무시합니다. |
| CherryPy | HTTP 파싱에 cheroot를 사용합니다. |
| libhttpserver | HTTP 파싱에 이미 Garden에 있는 libmicrohttpd를 사용합니다. |
| Werkzeug | HTTP 파싱에 이미 Garden에 있는 CPython 표준 라이브러리를 사용합니다. |
| Caddy | HTTP 파싱에 이미 Garden에 있는 Go 표준 라이브러리를 사용합니다. |
| Tengine | Nginx의 HTTP 파서를 사용합니다. |
Garden이 발견한 전체 버그 목록은 TROPHIES.md를 참조하세요.
| OpenResty | Nginx의 HTTP 파서를 사용합니다. |
| Google Cloud Global External Application Load Balancer | Envoy 기반입니다. |
| Google Cloud Regional External Application Load Balancer | Envoy 기반입니다. |
| Phusion Passenger | HTTP 파싱에 node_stdlib에 이미 포함된 llhttpd를 사용합니다. |
| passim | HTTP 파싱에 이미 Garden에 있는 libsoup를 사용합니다. |
| boa | 유지보수되지 않음. |
| Ulfius | 이미 Garden에 있는 libmicrohttpd를 사용합니다. |
| Vultr Load Balancer | 이미 Garden에 있는 HAProxy일 뿐입니다. |
| VMWare Avi Load Balancer | 이미 Garden에 있는 Nginx일 뿐입니다. |
| Sanic | Uvicorn에 이미 포함된 httptools를 사용합니다. |
| CPython http.server | 프로덕션 사용을 위한 것이 아닙니다. |
| openjdk_stdlib | 일관된 취약점 공개 채널을 제공하지 않습니다. |
| dart_stdlib | 이전 보고를 무시했습니다. |
| eventlet | HTTP 라이브러리는 CPython 표준 라이브러리의 것을 포크한 것일 뿐입니다. |
| uwsgi | 청크 메시지 본문을 지원하지 않습니다. |