The HTTP Garden 是一个可组合的 HTTP 服务器和代理的集合,附带用于与它们交互的脚本,让发现漏洞变得容易得多。想看看使用 HTTP Garden 可以发现哪些漏洞的酷炫演示,请查看我们的 ShmooCon 2024 演讲。
我们感谢 Galois、Trail of Bits、Narf Industries 和 Dartmouth College 的朋友们,让这个项目成为可能。
本材料基于国防高级研究计划局(DARPA)在合同号 HR0011-19-C-0076 下支持的工作。
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 行结尾的 payload。这在规范中是不允许的。
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 服务器和转换器(transducer)包含一个子目录。
每个目标都有自己的 Docker 镜像。
所有程序在可能的情况下都会从源码构建。
为了便于构建每个目标的多个版本,所有目标都通过仓库 URL(APP_REPO)、分支名(APP_BRANCH)和提交哈希(APP_VERSION)进行参数化。
toolstools 目录包含用于与服务器交互的脚本。在其中,你会找到
probe_quirks.py:一个用于枚举被测系统中无害的 HTTP 解析怪癖的脚本,以便在模糊测试期间忽略它们,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 | | | | | | | | | | | | |
|-| | 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 中几个显著遗漏项的解释:
有关 Garden 发现的完整 bug 列表,请参阅 TROPHIES.md。
| Name | Rationale |
|---|
| Microsoft 的任何产品 | MSRC 告诉我们“HTTP 走私不被视为漏洞”,而我觉得没有特别必要去帮助 Microsoft。 |
| unicorn | 使用与 yahns 相同的 HTTP 解析器。 |
| SwiftNIO | 使用 llhttp 进行 HTTP 解析,而 node_stdlib 已经涵盖了它。 |
| Bun | 使用 picohttpparser 进行 HTTP 解析,而 h2o 已经涵盖了它。 |
| Deno | 使用 hyper 进行 HTTP 解析,而它已在 Garden 中。 |
| Daphne | 使用 twisted 进行 HTTP 解析,而它已在 Garden 中。 |
| pitchfork | 使用与 yahns 相同的解析器。 |
| nghttpx | 使用 lhttp 进行 HTTP 解析,而 node_stdlib 已经涵盖了它。 |
| Cheroot | 忽略我们的报告。 |
| CherryPy | 使用 cheroot 进行 HTTP 解析。 |
| libhttpserver | 使用 libmicrohttpd 进行 HTTP 解析,而它已在 Garden 中。 |
| Werkzeug | 使用 CPython 标准库进行 HTTP 解析,而它已在 Garden 中。 |
| Caddy | 使用 Go 标准库进行 HTTP 解析,而它已在 Garden 中。 |
| Tengine | 使用 Nginx 的 HTTP 解析器。 |
| OpenResty | 使用 Nginx 的 HTTP 解析器。 |
| Google Cloud Global External Application Load Balancer | 基于 Envoy。 |
| Google Cloud Regional External Application Load Balancer | 基于 Envoy。 |
| Phusion Passenger | 使用 llhttpd 进行 HTTP 解析,而 node_stdlib 已经涵盖了它。 |
| passim | 使用 libsoup 进行 HTTP 解析,而它已在 Garden 中。 |
| boa | 已不再维护。 |
| Ulfius | 使用 libmicrohttpd,而它已在 Garden 中。 |
| Vultr Load Balancer | 它其实就是 HAProxy,而 HAProxy 已在 Garden 中。 |
| VMWare Avi Load Balancer | 它其实就是 Nginx,而 Nginx 已在 Garden 中。 |
| Sanic | 使用 httptools,而它已由 Uvicorn 涵盖。 |
| CPython http.server | 不打算用于生产环境。 |
| openjdk_stdlib | 没有提供连贯的漏洞披露渠道。 |
| dart_stdlib | 忽略了之前的报告。 |
| eventlet | 其 HTTP 库只是 CPython 标准库中相应库的一个分支。 |
| uwsgi | 不支持分块消息体。 |