目录
[三、尝试绕过雷池防护的 sqli-labs 靶场](#三、尝试绕过雷池防护的 sqli-labs 靶场)
[4.1 技术原理及绕过思路:](#4.1 技术原理及绕过思路:)
[4.2 multipart/form-data](#4.2 multipart/form-data)
[4.2.1 0x00 截断filename](#4.2.1 0x00 截断filename)
[4.2.2 双写上传描述行【绕过】](#4.2.2 双写上传描述行【绕过】)
[4.2.3 双写整个part开头部分](#4.2.3 双写整个part开头部分)
[4.2.4 构造假的part部分1【绕过】](#4.2.4 构造假的part部分1【绕过】)
[4.2.5 构造假的part部分2 【绕过】](#4.2.5 构造假的part部分2 【绕过】)
[4.2.6 两个boundary](#4.2.6 两个boundary)
[4.2.7 两个Content-Type](#4.2.7 两个Content-Type)
[4.2.8 空boundary](#4.2.8 空boundary)
[4.2.9 空格boundary](#4.2.9 空格boundary)
[4.2.10 boundary 中的逗号](#4.2.10 boundary 中的逗号)
[4.3 进阶绕过](#4.3 进阶绕过)
[4.3.1 0x00 截断进阶【绕过X2】](#4.3.1 0x00 截断进阶【绕过X2】)
[4.3.2 boundary 进阶](#4.3.2 boundary 进阶)
[4.3.3 单双引号混合进阶](#4.3.3 单双引号混合进阶)
[4.3.4 urlencoded伪装成为multipart【绕过】](#4.3.4 urlencoded伪装成为multipart【绕过】)
[4.4 skip_upload 进阶](#4.4 skip_upload 进阶)
一、前言
记录一下在测试环境中的 waf 绕过思路和技巧。本文方法仅用于技术研习提升企业安全防护能力,严禁一切未授权测试与非法利用。
二、搭建环境
雷池社区版 + 宝塔面板 + SQLi-LABS + Windows10 + 安全狗
宝塔linux面板,一键安装LAMP/LNMP/SSL/Tomcat
安全狗-领先云安全服务与解决方案提供商|云原生安全|服务器安全|网站安全|态势感知
三、尝试绕过雷池防护的 sqli-labs 靶场
搭建好环境后,首先来看一下第11关的靶场,通过POST传参可以看到是查询了两个字段,尝试构造注入语句。
sql
admin' union select 1,users()#
sql 注入已经被雷池拦截了,现在尝试绕过需要考虑拦截了哪些函数。接下来通过构造 sql 语句来进行测试,看一下 waf 认为不合法的传入都有什么?
admin' and updatexml(1,concat(0x7e,user(),0xe7),1)#
admin' and aaa(1,concat(0x7e,user(),0xe7),1)#
admin' and aaa(1,concat(0x7e,ccc(),0xe7),1)#
admin' and aaa(1,bbb(0x7e,ccc(),0xe7),1)#
构造的这四个语句都被 waf 拦截了,很明显最后一个根本不是注入语句了,但是仍然被拦截。
那问题出在 and 上,继续构造sql语句进行测试。第一个没有被拦截,第二个**&& 替换 and** 没有被拦截,第三个updatexml 报错函数被拦截,第四个 concat 和 users 没被拦截。最终结果就是 and 和 updatexml 报错函数被拦截了,and 替换&&没有被杀掉,updatexml报错函数怎么进行绕过?将updatexml()报错函数替换为ST_LatFromGeoHash()(mysql>=5.7.x)最终系统函数被拦截了。。
admin' andb aaa(1,bbb(0x7e,ccc(),0xe7),1)#
admin' && aaa(1,bbb(0x7e,ccc(),0xe7),1)#
admin' && updatexml(1,bbb(0x7e,ccc(),0xe7),1)#
admin' && aaa(1,concat(0x7e,user(),0xe7),1)#
admin' && ST_LatFromGeoHash(concat(0x7e,user(),0x7e))#
系统函数被杀了,尝试@@ 绕过,结果还是不行。或者可以使用 MySQL 自带库 information 进行查询,就不测试了因为关键词也被杀了。。
【网络安全】SQL注入------无列名注入_sql无联名注入-CSDN博客
admin' && ST_LatFromGeoHash(concat(0x7e,@@user(),0x7e))#
admin' && ST_LatFromGeoHash(concat(0x7e,(select 1,2,3),0x7e))#
四、通用型入门绕过思路
进入正题,以上绕过只是想着绕过查杀了哪些函数,就算绕过一句语句,在后续的查询语句中很有可能会被继续拦截。这种只是属于事件型的绕过。本次事件型绕过就不继续往下做了。我们追求通用型的绕过,这一次要绕过的方案是通过差异化进行绕过,一但绕过所有语句将畅通无阻。通用型的理念就是差异化绕过,waf认为传入的是合法的值,而后端接收的确是非法的值。
4.1 技术原理及绕过思路:
先来看一下师傅们的思路:
首先谈一下WAF。Web应用防火墙,主要用途是对HTTP(s)协议进行校验,拦截恶意的攻击请求,放行正常的业务请求。从架构来看,主要分为:网络层、应用层、云WAF 三类。从绕过来看,分为通用型绕过和单一规则绕过。通用型绕过即完全绕过WAF防护,一 旦产生绕过后,可以利用该Payload实现任意一种攻击;而单一规则绕过,则仅能够绕过特 定规则,例如:SQL注入规则中使用 select-1.1from......来绕过 select\b[\s\S]*\bfrom 这一正则规则,绕过以后仅能够实现SQL注入攻击。我所致力研究的属于前者。
从网络层、应用层、云WAF三类场景来看他们的绕过思路也有所区别,例如,对于传 统的网络层WAF,采用 chunked编码即可绕过,目前多数WAF厂商已经修复,但是我们仍 然可以在网络层发包这一方向进行尝试和探索。对于应用层WAF,WAF的处理引擎是经过 前端Nginx或Apache(大多数场景都是Nginx及Tengine)完成HTTP协议初步解析以后, 再转发给WAF处理引擎的,因而一些网络层组包的技术是无法绕过的。那么就需要我们去 研究:对于一个HTTP请求,Nginx解析了什么内容?交给后面的PHP、ASP又解析了什么 内容?
本文介绍的思路主要围绕: multipart/form-data。主要针对于POST参数的,对于漏洞 点在GET参数位置则用处不大。
4.2 multipart/form-data
以php为例写一个测试脚本,了解除了常规的 application/x-www form-urlencoded 以外,还有 multipart/form-data 这种形式。基于 Nginx+PHP 的架构,Nginx 实际上是不负责解析 multipart/form-data 的 body 部分,而是交由PHP来解析,因此WAF所获取的内容就很有可能与后端的PHP发生不一 致。
php
<?php
echo "POST CONTENT: " . file_put_contents("php://input") . "\n";
echo "POST: ";
var_dump($_POST);
echo "FILES: ";
var_dump($_FILES);
?>
当我们用 multipart 形式进行文件上传时,实际上与 urlencoded 是一个效果,参数并没有进入_FILES 数组,而是进入了_POST数组。文件上传 POST 也可以接到,为什么可以接到,少一个参数,缺失这个参数就不认为是文件上传了,如果没有 filename 这个字段,那么认为就是post提交。 正常我认为 file 就是上传 file,post 就是上传 post,这里是一个上传图片,实际上还是在 post 下接收到了。那何时是上传文件?何时是POST参数呢?这个关键点在于有没有一个完整的 filename=

加上了 filename= 以后的效果:

Bypass WAF 的核心思想在于,一些WAF产品处于降低误报考虑,对用户上传文件的内 容不做匹配,直接放行。事实上,这些内容在绝大多数场景也无法引起攻击。但关键问题在于,WAF 能否准确有效识别出哪些内容是传给_POST 数组的,哪些传给_FILES 数组?如果不能,那我们是否就可以想办法让WAF以为我们是在上传文件,而实际上却是在POST 一个参数,这个参数可以是命令注入、SQL注入、SSRF等任意的一种攻击,这样就实现了通用WAF Bypass。
4.2.1 0x00 截断filename
0x00截断在php5.2版本出现过,也就是遇到\0自动结束,因为C语言的结束符就是\0。我们看一下如何截断filename。
在filename 之前加入了0x00,而有些WAF在检测前会删除HTTP协议中的0x00, 这样就导致了WAF认为是含有filename的普通上传,而后端PHP则认为是POST参数。

进行测试我们的靶场,将第11关靶场字段修改成一个,更方便进行测试。输入正确user,查询到了数据,证明接收到的确实是post提交,00截断成功。


4.2.2 双写上传描述行【绕过】
双写后,一些WAF会取第二行,而实际PHP会获取第一行。php获取的确实是第一个,那 waf 获取的是第二个吗?

通过双写上传描述行成功绕过!!

4.2.3 双写整个part开头部分
该参数会引入一些垃圾数据,在命令注入及 SQL 注入的攻击场景,需要尽可能将前面的内容闭合。就是post提交在后端的是光标所选部分,需要注意闭合前面的垃圾数据。

4.2.4 构造假的part部分1【绕过】
第二次绕过了长亭的 waf ,很明显 waf 取的是第一个,而后端接收到了第二个。

4.2.5 构造假的part部分2 【绕过】
这里比前一种【构造假的part部分1】少了一个换行,数据纯净了许多。这种通用型只要能绕过一次那么就畅通无阻。报错注入和联合查询等都是成功绕过。

4.2.6 两个boundary
对于php来说,真正的 boundary 是 a, waf 也是一样。


4.2.7 两个Content-Type
真正的 boundary 仍然是a,经测试没有取到b。同样也没有绕过长亭的 waf。


4.2.8 空boundary
boundary为空,php依然取的是里面的,现在想让 waf 取空boundary,但是没有绕过。


4.2.9 空格boundary
同样可以接收到空格boundary,但是没有绕过waf。

4.2.10 boundary 中的逗号
同样php取值还是取的里面的,和上面的几种方法类似,都没有绕过waf。


4.3 进阶绕过
4.3.1 0x00 截断进阶【绕过X2】
如果是双写,其实是以第一行为主的,这样就是上传文件。但如果我们在适当的地方加入0x00、空格 和 \t , 就会破坏第一行,让PHP以第二行为主。
第一种 在Content-Disposition后加入\t,从而破坏第一行,让php取第二行,但是waf也是取的第二行,没有绕过。


第二种 在Content-Disposition前加入\t ,依然没有绕过。

第三种 在 filename 后加入\t ,又一次绕过了长亭的waf。

此外在name="uname"加入00截断,也是可以的。 最容易被忽视的是参数名中的0x00。

4.3.2 boundary 进阶
boundary 的名称是可以前后加入任意内容的,WAF如果严格按 boundary 去取,可能又会被绕过。将boundary前后加入字符,会被php忽略,那waf是怎么样的?

waf 的取值和php一样,没有绕过长亭 waf 也取到了 boundary=a

4.3.3 单双引号混合进阶
Content-Disposition中的字段使用单引号还是双引号?想破坏掉file的取值让php取第二个,但是没有绕过长亭的 waf。

4.3.4 urlencoded伪装成为multipart【绕过】
这个poc很特殊。实际上是 urlencoded,但是伪装成了 multipart,通过&来截取前后装饰部分,保留 uname 参数的完整性。理论上 multipart/form-data 下的内容不进行urldecoded, 一些WAF也正是这样设计的,这样做本没有问题,但是如果是 urlencoded 格式的内容,不进行 url 解码就会引入%0a这样字符,而这样的字符不解码是可以直接绕过防护规则的,从而导致了绕过。

4.4 skip_upload 进阶
在PHP 中,skip_upload 是可以来控制上传行是否为上传文件的。

前面内容中介绍了,如果在第一行的 Content-Disposition 位置添加 \0,是有可能引起第一行失效,从而从上传文件变为 POST参数的。除此以外,我们来看一下php源码php 5.3.3/main/rfc1867.c ,其中 line: 991 有这样一段内容:
php
if (!skip_upload) {
char *tmp = param;
long c = 0;
while (*tmp) {
if (*tmp == '[') {
c++;
} else if (*tmp == ']') {
c--;
if (tmp[1] && tmp[1] != '[') {
skip_upload = 1;
break;
}
}
if (c < 0) {
skip_upload = 1;
break;
}
tmp++; }
}
其中的param参数是name="uname" 也就是 id 这个参数,那么如何能让它skip_upload ? 通过想办法进入c < 0,c原本是 0,遇到 [ 就自增一,遇到 ] 就减一。那么,我们构造 name="f]" 即可让c=-1 。

虽然没有绕过,事实上,只要参数中有不成对匹配的左右中括号都可以引发skip_upload。
五、总结
本次在waf下测试和分析绕过waf的技巧和思路到此结束,以上共有六种方式能够绕过长亭的雷池waf。经过后续测试,发现长亭雷池对webshell的查杀并不是很强,主要还是防御 Top10 漏洞。上述研究的绕过技巧在安全狗下也有多种方式能够绕过。本文方法仅用于技术研习提升企业安全防护能力,严禁一切未授权测试与非法利用。