使用生僻函数替代常见的函数,例如在报错注入中使用 polygon()函数替换常用的 updatexml()函数。
select polygon((select * from (select * from (select @@version) f) x));
注:上面的句子有待改善。
分块传输编码(Chunked transfer encoding)是只在 HTTP 协议 1.1 版本(HTTP/1.1)中提供的一种数据传送机制。以往 HTTP
的应答中数据是整个一起发送的,并在应答头里 Content-Length 字段标识了数据的长度,以便客户端知道应答消息的结束。
传统的 Content-length 解决方案:计算实体长度,并通过头部告诉对方。浏览器可以通过 Content-Length 的长度信息,判断出响应
实体已结束。
Content-length 面临的问题:由于 Content-Length 字段必须真实反映实体长度,但是对于动态生成的内容来说,在内容创建完之前,
长度是不可知的。
这时候要想准确获取长度,只能开一个足够大的 buffer,等内容全部生成好再计算。这样做一方面需要更大的内存开销,另一方面也会让
客户端等更久。
我们需要一个新的机制:不依赖头部的长度信息,也能知道实体的边界——分块编码(Transfer-Encoding: chunked)。对于动态生成的
应答内容来说,内容在未生成完成前总长度是不可知的。因此需要先缓存生成的内容,再计算总长度填充到 Content-Length,再发送整个
数据内容。这样显得不太灵活,而使用分块编码则能得到改观。
分块传输编码允许服务器在最后发送消息头字段。例如在头中添加散列签名。对于压缩传输传输而言,可以一边压缩一边传输。
如果在 http 的消息头里 Transfer-Encoding 为 chunked,那么就是使用此种编码方式。
接下来会发送数量未知的块,每一个块的开头都有一个十六进制的数,表明这个块的大小,然后接 CRLF("\r\n")。然后是数据本身,数据
结束后,还会有CRLF("\r\n")两个字符。有一些实现中,块大小的十六进制数和 CRLF 之间可以有空格。
最后一块的块大小为0,表明数据发送结束。最后一块不再包含任何数据,但可以发送可选的尾部,包括消息头字段。消息最后以CRLF结尾。
在头部加入Transfer-Encoding: chunked之后,就代表这个报文采用了分块编码。这时,报文中的实体需要改为用一系列分块来传输。
每个分块包含十六进制的长度值和数据,长度值独占一行,长度不包括它结尾的CRLF(\r\n),也不包括分块数据结尾的 CRLF(\r\n)。
最后一个分块长度值必须为 0,对应的分块数据没有内容,表示实体结束。
例:
HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked
23\r\n
This is the data in the first chunk\r\n
1A\r\n
and this is the second one\r\n
3\r\n
con\r\n
8\r\n
sequence\r\n
0\r\n
\r\n
用 burpsuite 抓包提交分析,首先原生包 id=1&submit=1,查询到用户 id 为 1 的值。
使用分块传输,首先在 http 头加上 Transfer-Encoding: chunked,表示分块传输传送。
第一行是长度,第二行是字符串,0 表示传输结束,后面跟上两个空格。
也可以使用 burpsuite 的插件 chunked-coding-converter 进行编码提交。
有些 WAF 会自带一些文件白名单,对于白名单 waf 不会拦截任何操作,所以可以利用这个特点,可以试试白名单绕过。
白名单通常有目录:
/admin
/phpmyadmin
/admin.php
?a=/admin.php&name=' union select 1,user()--+&submit=1
/phpmyadmin?name=' union select 1,user()--+&submit=1
除了白名单信任文件和目录外,还有一部分 waf 并不会对静态文件进行拦截。
例如,图片文件 jpg 、png 、gif 或者 css 、js 会对这些静态文件的操作不会进行检测从而绕过 waf 拦截。
?/1.jpg&name=-vince' union select 1,user()--+&submit=1
?/1.jpg=/1.jpg&name=-vince' union select 1,user()--+&submit=1
?/1.css=/1.css&name=-vince' union select 1,user()--+&submit=1
http 协议是由 tcp 协议封装而来,当浏览器发起一个 http 请求时,浏览器先和服务器建立起连接 tcp 连接,然后发送 http 数据包
(即我们用 burpsuite 截获的数据),其中包含了一个 Connection 字段,一般值为 close。apache 等容器根据这个字段决定是保持
该 tcp 连接或是断开。当发送的内容太大,超过一个 http 包容量,需要分多次发送时,值会变成 keep-alive,即本次发起的 http
请求所建立的 tcp 连接不断开,直到所发送内容结束 Connection 为 close 为止。
用 burpsuite 抓包提交,复制整个包信息放在第一个包最后,把第一个包 close 改 成 keep-alive,把brupsuite 自动更新
Content-Length 勾去掉。
第一个包参数的字符要加上长度,接着提交即可。有些 waf 会匹配第二个包的参数,属于正常参数,不会对第一个包的参数进行检测,这样
就可以绕过一些 waf 拦截。