漏洞产生原理:
大多数HTTP请求走私漏洞的出现是因为HTTP规范提供了两种不同的方法来指定请求的结束位置:Content-Length标头和Transfer-Encoding标头。
同时使用两种不同的方法时,Content-Length无效。当使用多个服务器时,对客户端传入的数据理解不一致时,就会出现有些服务器认为Content-Length的长度有效,有些以Transfer-Encoding有效。而一般情况下,反向代理服务器与后端的源站服务器之间,会重用TCP链接。这样超出的长度就会拼接到下一次请求进行请求,从而导致HTTP请求走私漏洞。
简述原理:
由于前后端对请求消息的理解不同,从而造成了部分请求搁置再缓冲区,当进行下一次请求的时候,缓冲区的请求会拼接到该次请求,从而造成走私,走私再CTF中常见的利用方式就是:从服务器本地访问资源获得FLAG,因此我们需要构造X-F-D:127.0.0.1等等都可以
五种攻击方式:
CL不为0(前端允许GET请求携带请求体)
其实在这里,影响到的并不仅仅是GET请求,所有不携带请求体的HTTP请求都有可能受此影响,只因为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的存在,它就认为这是收到了两个请求,分别是
第一个
GET / HTTP/1.1\r\n
Host: example.com\r\n
第二个
GET / secret HTTP/1.1\r\n
Host: example.com\r\n
CL-CL
当服务器收到的请求中包含两个Content-Length,而且两者的值不同时,需要返回400错误。
但是总有服务器不会严格的实现该规范,假设中间的代理服务器和后端的源站服务器在收到类似的请求时,都不会返回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
前端服务器读取第一个conent-length:8, 把12345\r\na转发给后端服务器,后端服务器读取content-length:7,读取7个字符:12345\r\n,那么剩下的a就会留在缓冲区,当进行下一次请求的时候,会出现以下情况:
aGET /index.html HTTP/1.1\r\n
Host: example.com\r\n
请求就会报错
CL-TE
所谓CL-TE,就是当收到存在两个请求头的请求包时,前端代理服务器只处理Content-Length这一请求头,而后端服务器会遵守RFC2616的规定,忽略掉Content-Length,处理Transfer-Encoding这一请求头。
chunk传输数据格式如下,其中size的值由16进制表示。
[chunk size][\r\n][chunk data]