HTTP请求走私漏洞

HTTP请求走私漏洞

本文转自Atkxor 并作补充

简介

HTTP请求走私是一种干扰网站处理从一个或多个用户接收的HTTP请求序列的方式的技术。请求走私漏洞本质上通常很关键,它使攻击者可以绕过安全控制,未经授权访问敏感数据并直接危害其他应用程序用户。

  • 利用Content-Length字段来判定请求体的内容长度
  • 利用Transfer-Encoding字段来判定请求体的结束位置

基础知识

Content-Length

Content-Length即为实体长度。浏览器可以通过 Content-Length 的长度信息,判断出响应实体已结束。通常如果 Content-Length 比实际长度短,会造成内容被截断;如果比实体内容长,会造成 pending。

Transfer-Encoding

历史上 Transfer-Encoding 可以有多种取值,但最新的 HTTP 规范里,只定义了一种传输编码:分块编码(chunked)。
分块编码相当简单,在头部加入 Transfer-Encoding: chunked 之后,就代表这个报文采用了分块编码。这时,报文中的实体需要改为用一系列分块来传输。每个分块包含十六进制的长度值和数据,长度值独占一行,长度不包括它结尾的 CRLF(\r\n),也不包括分块数据结尾的 CRLF。最后一个分块长度值必须为 0,对应的分块数据没有内容,表示实体结束。

CL与TE解析优先级顺序

CL表示Content-Length,TE表示Transfer-Encoding。优先级顺序详见 RFC7230 section 3.3.3

1
2
3
4
5
If a message is received with both a Transfer-Encoding and a
Content-Length header field, the Transfer-Encoding overrides the
Content-Length. Such a message might indicate an attempt to perform
request smuggling (Section 9.5) or response splitting (Section 9.4)
and ought to be handled as an error. A sender MUST remove the received Content-Length field prior to forwarding such a message downstream.

TE 优先于 CL ,但可以通过一些方式绕过

请求走私分类

请求走私攻击包括将Content-Length标头和Transfer-Encoding 标头都放入单个HTTP请求中并进行处理,以便前端服务器和后端服务器以不同的方式处理请求。完成此操作的确切方式取决于两个服务器的行为:

  • CL不为0:前端代理服务器允许请求携带请求体,而后端服务器不允许请求携带请求体。
  • CL-CL:前端服务器使用Transfer-Encoding头,而后端服务器使用Content-Length头。
  • CL-TE:前端服务器使用Content-Length标头,而后端服务器使用Transfer- Encoding标头。
  • TE-TE:前端服务器和后端服务器都支持Transfer-Encoding标头,但是可以通过某种方式混淆标头来诱导其中一台服务器不对其进行处理。
  • TE-CL:前端服务器使用Transfer-Encoding头,而后端服务器使用Content-Length头。

CL不为0

所有不携带请求体的HTTP请求都有可能受此影响,这里以GET请求为例。
当前端服务器允许GET请求携带请求体,而后端服务器不允许GET请求携带请求体,它会直接忽略掉GET请求中的Content-Length头,不进行处理。这就有可能导致请求走私。
比如构造请求:

1
2
3
4
5
6
7
GET / HTTP/1.1\r\n
Host: demo.com\r\n
Content-Length: 44\r\n
\r\n
GET /secret HTTP/1.1\r\n
Host: demo.com\r\n
\r\n

注:\r\n表示 CRLF即换行

前端服务器处理了Content-Length,而后端服务器没有处理 Content-Length ,基于pipeline机制认为这是两个独立的请求:
第一个请求:

1
2
GET / HTTP/1.1\r\n
Host: demo.com\r\n

第二个请求:

1
2
GET /secret HTTP/1.1\r\n
Host: demo.com\r\n

CL-CL漏洞

RFC7230规范:在RFC7230的第3.3.3节中的第四条中,规定当服务器收到的请求中包含两个Content-Length,而且两者的值不同时,需要返回400错误。
构造请求:

1
2
3
4
5
6
7
POST / HTTP/1.1\r\n
Host: demo.com\r\n
Content-Length: 5\r\n
Content-Length: 6\r\n
\r\n
12345\r\n
a

得到响应,返回400 Bad Request
image

触发过程:但是总有服务器不会严格的实现该规范,假设中间的代理服务器和后端的源站服务器在收到类似的请求时,都不会返回400错误,但是中间代理服务器按照第一个Content-Length的值对请求进行处理,而后端源站服务器按照第二个Content-Length的值进行处理。

CL-TE漏洞

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

TE-TE漏洞

在这里,前端服务器和后端服务器都支持Transfer-Encoding标头,但是可以通过对标头进行某种方式的混淆来诱导其中一台服务器不对其进行处理。
详见 RFC7230 section 3.3.3.3

1
2
3
4
5
6
7
8
If a Transfer-Encoding header field is present in a response and
the chunked transfer coding is not the final encoding, the
message body length is determined by reading the connection until
it is closed by the server. If a Transfer-Encoding header field
is present in a request and the chunked transfer coding is not
the final encoding, the message body length cannot be determined
reliably; the server MUST respond with the 400 (Bad Request)
status code and then close the connection.

这里列出七种混淆方式:

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

Transfer-Encoding : chunked

Transfer-Encoding: x

Transfer-Encoding:[tab]chunked

[space]Transfer-Encoding: chunked

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

Transfer-Encoding
: chunked

之所以在处理这些请求头时会出现问题,是因为在实际的HTTP协议实现中,很少有代码精确的遵循了其中的规范,以此导致面对变形的请求头时会出现不同的处理方式。
TE.CL实验环境

TE-CL漏洞

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

绕过前端服务器安全控制

利用CL-TE漏洞绕过

CL.TE实验环境

利用TE-CL漏洞绕过

TE.CL实验环境

漏洞防御

在前端服务器通过同一网络连接将多个请求转发到后端服务器的情况下,会出现HTTP请求走私漏洞,并且后端连接所使用的协议会带来两个服务器不同意边界的风险。要求。防止HTTP请求走私漏洞的一些通用方法如下:

  • 禁用后端连接的重用,以便每个后端请求通过单独的网络连接发送。
  • 使用HTTP / 2进行后端连接,因为此协议可防止对请求之间的边界产生歧义。
  • 前端服务器和后端服务器使用完全相同的Web服务器软件,以便它们就请求之间的界限达成一致。
    在某些情况下,可以通过使前端服务器规范歧义请求或使后端服务器拒绝歧义请求并关闭网络连接来避免漏洞。但是,这些方法比上面确定的通用缓解措施更容易出错。

参考文章

(https://paper.seebug.org/1048)
(https://portswigger.net/web-security/request-smuggling)
(https://portswigger.net/web-security/request-smuggling/exploiting)