前言
在一次测试过程中扫描器扫出了这个漏洞,以前只知道一个大概,今天来具体的看一下该漏洞的原理,利用方式以及检测方式。
由于本人水平有限,文章中可能会出现一些错误,欢迎各位大佬指正,感激不尽。如果有什么好的想法也欢迎交流~~
漏洞原理
在复杂的网络环境下,不同的服务器对RFC标准实现的方式不同,程度不同。这样一来,对同一个HTTP请求,不同的服务器可能会产生不同的处理结果,这样就产生安全风险。
为了缓解服务器的压力,一般在服务器前面会用代理服务器进行缓存,因此就可能造成代理服务器与真实的服务器之间处理请求不同,导致非法的请求到达真实服务器。
如果在代理服务器上做权限控制,则还可能绕过权限限制。
实际就是绕过第一个服务器,让它以为发送的是一个请求,而真实的服务器认为是两个不同的请求。
一般来说,反向代理服务器与后端的源站服务器之间,会重用TCP链接。这也很容易理解,用户的分布范围是十分广泛,建立连接的时间也是不确定的,这样TCP链接就很难重用,而代理服务器与后端的源站服务器的IP地址是相对固定,不同用户的请求通过代理服务器与源站服务器建立链接,这两者之间的TCP链接进行重用,也就顺理成章了。
当我们向代理服务器发送一个比较模糊的HTTP请求时,由于两者服务器的实现方式不同,可能代理服务器认为这是一个HTTP请求,然后将其转发给了后端的源站服务器,但源站服务器经过解析处理后,只认为其中的一部分为正常请求,剩下的那一部分,就算是走私的请求,当该部分对正常用户的请求造成了影响之后,就实现了HTTP走私攻击。
RFC标准:Request For Comments
检测工具:https://github.com/anshumanpattnaik/http-request-smuggling
基础知识
漏洞的主要原因是在http1.x中引入了长连接keep-alive与pipline的概念。长连接允许多个请求复用同一个tcp连接,不必每个请求重新建立连接,大大节约了服务器资源,pipline使得http的请求不必等到响应之后在发起,而可以流式得发起请求,请求到达服务端后仍然通过排队的方式进行处理。正是这两个概念导致了我们今天要讲的问题,当然还有另外重要的一点就是,关于服务器在处理te(Transfer-Encoding)与cl(Content-Length)时存在的差异导致了这个问题。
Keep-Alive
HTTP/1.0 的持久连接机制是后来才引入的,通过 Connection: keep-alive 这个头部来实现,服务端和客户端都可以使用它告诉对方在发送完数据之后不需要断开 TCP 连接,以备后用。HTTP/1.1 则规定所有连接都必须是持久的,除非显式地在头部加上 Connection: close。所以实际上,HTTP/1.1 中 Connection 这个头部字段已经没有 keep-alive 这个取值了,但由于历史原因,很多 Web Server 和浏览器,还是保留着给 HTTP/1.1 长连接发送 Connection: keep-alive 的习惯。
Pipeline
客户端可以像流水线一样发送自己的HTTP请求,而不需要等待服务器的响应,服务器那边接收到请求后,需要遵循先入先出机制,将请求和响应严格对应起来,再将响应发送给客户端。现如今,浏览器默认是不启用Pipeline的,但是一般的服务器都提供了对Pipleline的支持。
Content-Length
表示传输内容的长度。告诉服务端传输内容的长度。
Transfer-Encoding
是一个 HTTP 头部字段,字面意思是「传输编码」。实际上,HTTP 协议中还有另外一个头部与编码有关:Content-Encoding(内容编码)。通过特殊的格式来表示一个http请求是否传输完成。
在长连接的情况下,如果两个服务端对传输的长度处理不同,可能导致一个服务端认为是一个完整的请求,另一个服务端任务是两个。这就是请求走私。
利用场景
上面说了关于请求走私的一些基础知识,请求走私主要就是由于前后端服务器对于数据包的处理方式不同造成的,造成这种问题主要是由Content-Length与Transfer-Encoding两个参数控制的,这两个参数简称为CL与TE。下面就结合portswigger来看看该漏洞的一些具体应用场景。
https://portswigger.net/web-security/request-smuggling#what-is-http-request-smuggling
场景1:CL-TE:前端服务器使用Content-Length消息头,后端服务器使用Transfer-Encoding消息头
场景2:TE-CL:前段服务器使用Transfer-Encoding消息头,后端服务器使用Content-Length消息头
场景3:TE-TE:前端服务器和后端服务器都支持Transfer-Encoding标头,但是可以通过对标头进行某种方式的混淆来诱导其中一台服务器不对其进行处理
场景4:CL-CL:在RFC7230中,规定当服务器收到的请求中包含两个Content-Length,而且两者的值不同时,需要返回400错误。有些服务器不会严格的实现该规范,假设中间的代理服务器和后端的源站服务器在收到类似的请求时,都不会返回400错误。 但是中间代理服务器按照第一个Content-Length的值对请求进行处理,而后端源站服务器按照第二个Content-Length的值进行处理。
场景5:CL不为0的的Get请求:前端代理服务器允许GET请求携带请求体;后端服务器不允许GET请求携带请求体,它会直接忽略掉GET请求中的Content-Length头,不进行处理。这就有可能导致请求走私。
场景一:CL-TE
前端服务器使用Content-Length消息头,后端服务器使用Transfer-Encoding消息头。
RFC2616规范
如果收到同时存在Content-Length和Transfer-Encoding这两个请求头的请求包时,在处理的时候必须忽略Content-Length。
chunked
设置了 Transfer-Encoding: chunked 后,请求主体按一系列块的形式发送,并将省略 Content-Length。在每个块的开头需要用十六进制数指明当前块的长度,数值后接 \r\n(占 2 字节),然后是块的内容,再接 \r\n 表示此块结束。最后用长度为 0 的块表示终止块。终止块后是一个 trailer,由 0 或多个实体头组成,可以用来存放对数据的数字签名等。
[chunk size][\r\n][chunk data][\r\n][chunk size][\r\n][chunk data][\r\n][chunk size = 0][\r\n][\r\n]
代码实例
POST / HTTP/1.1 Host: xxxx.com Content-Length: 6 Transfer-Encoding: chunked 0 a
分析
前端服务器:判断数据包以Content-Length的值,Content-Length: 6,判断完整,传给后端
后端服务器:判断数据包以Transfer-Encoding,遇到0\r\n\r\n后,以为请求体结束,留下了一个字母a在下一次请求时,会附着在下个请求中
此时再有用户请求
GET / HTTP/1.1 Host: localhost
就会返回错误内容造成服务器解析异常
aGET / HTTP/1.1 Host: localhost
portswigger实验
实验地址:https://portswigger.net/web-security/request-smuggling/lab-basic-cl-te
添加下面的内容,连续发送两次数据包,第二次的数据包会出现下面的报错
成功解决
场景二:TE-CL
前段服务器使用Transfer-Encoding消息头,后端服务器使用Content-Length消息头
代码实例
POST / HTTP/1.1 Host: cccccc.web-security-academy.net Content-Type: application/x-www-form-urlencoded Content-Length: 4 Transfer-Encoding: chunked 12 GPOST / HTTP/1.1 0
注意上边有两个换行,为了让Transfer-Encoding成功解析
分析
前端: 读取到0\r\n\r\n后,Transfer-Encoding认为是一个完整请求, 传给后端
后端:Content-Length: 4,判断到12\r\n,不在解析,后边的内容会留给下个请求
此时再有用户发出请求
GET / HTTP/1.1 Host: localhost
拼接预留内
4A评测 - 免责申明
本站提供的一切软件、教程和内容信息仅限用于学习和研究目的。
不得将上述内容用于商业或者非法用途,否则一切后果请用户自负。
本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑或手机中彻底删除上述内容。
如果您喜欢该程序,请支持正版,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。敬请谅解!
程序来源网络,不确保不包含木马病毒等危险内容,请在确保安全的情况下或使用虚拟机使用。
侵权违规投诉邮箱:4ablog168#gmail.com(#换成@)