长亭WAF绕过测试

本文的Bypass WAF 的核心思想在于,一些 WAF 产品处于降低误报考虑,对用户上传文件的内

容不做匹配,直接放行

0、环境

环境:两台服务器,一台配置宝塔面板,一台配置长亭雷池WAF

思路主要围绕:multipart/form-data,也就是主要针对于 POST 参数,对于漏洞点在 GET 参数位置则用处不大。

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

1、multipart/form-data特性

以 PHP 为例,我们写一个简单的测试脚本:

<?php
echo "POST Content:\n";
echo file_get_contents("php://input");echo "\n\n";
echo "\$_POST Content:  \n";
var_dump($_POST);echo "\n\n";
echo "\$_FILES Content: \n";
var_dump($_FILES);
?>

先使用BP来进行一些测试,以便了解一些特性

这是在Content_Type:application/x-www-form-urlencoded情况下的一个request和response

然后,在观察一下Content-Type:multipart/form-data的情况:

参数并没有进入$_FILES 数组,而是进入了$_POST 数组。

可以发现将Content-Type改成传输文件,并且在没有filename参数的情况下,我们是可以将文件内容传输为POST参数的。而正常情况下,传输文件还需要有一个filename参数,有了个参数,才会将文件内容装载成文件

那么,何时是上传文件?何时是 POST 参数呢?这个关键点在于有没有一个完整的 filename=。这 9 个字符是经过反复测试的,缺一个字符不可,替换一个字符也不可,在其中添加一个字符更不可。

加上了 filename=以后的效果:

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

小结:通过上传文件时,不使用filename=,来使文件内容传递给$_POST数组,通过这样就可以达到POST传参并且不会绕过WAF的目的

2、基础绕过

可以看到当我们进行sql注入时,是会对我们进行阻拦的

可以考虑某些绕过去进行单一规则绕过,但是进行到下一条语句时,很有可能需要重新去尝试绕过的规则。所以我们可以想象通用性绕过。

那么利用multipart/form-data的特性来绕过,但是发现WAF还是检测到了。

尝试一下其他方法

0x00截断filename

在 filename 前加入了 0x00,因为有些 WAF 在检测前会删除 HTTP 协议中的 0x00、空格,这样就导致了 WAF 认为是含有 filename 的普通上传,而后端 PHP 则认为是 POST 参数。空格也可以试试

但是在长亭的雷池WAF中并没有绕过

双写上传描述行

双写描述行后,一些 WAF 会取第二行,而实际 PHP 会获取第一行。

在没有\t,00,20的破坏下,WAF取第二行,而PHP取第一行

可以看到使用双写描述行的方法成功绕过了WAF

双写整个 part 开头部分

原理与双写上传描述行类似,但是可惜的是并没有绕过

但是当两个part头中的空格去除时,就能成功

个人理解为有空格的情况下,那么这两个part头是分开的个体,而当空格去除时,这两个part头就合成一个part头了,只是它们的赋值语句重复了,那么就取决于赋值语句的选取第一个还是第二个

需要注意的是,如果双写part头能成功,那么就需要考虑它的一些垃圾数据的影响,因为该参数会引入一些垃圾数据,在命令注入及 SQL 注入的攻击场景,需要尽可能将前面的内容闭合。

构造假的 part 部分 1

原理都是相似的

可以看到POST内容的开始是由--a决定的,而结束是由--a--决定的,那么是否可以构造两个开始来影响WAF的决定呢?

通过测试可以发现雷池WAF取得是第二个,还是覆盖那一套。而php则是取得第一个

当然,php取得第一个开始,那么第二个开始是会成为垃圾数据,所以需要注意引号的闭合

构造假的 part 部分 2

与构造part部分1相比缺少了一个空行,但是我觉得这还是将两个开始合成一个开始,考虑的是对于语句的复写选择,但相比于构造1的好处是数据会纯净许多

两个 boundary

写两个boundary,思路是考虑WAF与PHP后端的选择差异

测试发现,PHP后端选择的是第一个boundary,那么思考的点就是WAF的取值是否是第二个

很遗憾,WAF的取值貌似也是第一个,并不能绕过。

有一点疑惑是PHP取得是第一个boundary,即a,那么WAF不管取得是第一个还是第二个,它的参数应该是都含有-1' union select user(),database()#这个危险语句的。只是取一个是该语句,而取第二个只是包含该语句。因此在我看来这个方法无论如何都是无法成功

解决了,第二个boundary是具有filename的,也就是如果WAF取第二个那就不会检测内容

两个 Content-Type

与两个boundary类似,使用了两个Conten-Type

可以看到PHP取得还是第一个并且WAF也是第一个,所以没有成功

空 boundary

也就是说boundary并不设值,而结束符是分号;,那么是否可以引起歧义。因为作为最后一个

参数,它有没有分号都是不影响的。

这边的原理是让WAF认为boundary为分号,而PHP是将boundary认为是空

很遗憾,并没有成功

空格 boundary

原理与空boundary类似,想让WAF认为是空

但是也没有成功

boundary 中的逗号

boundary遇到逗号,结束,同理是否可以让WAF认为是a,b

或者以逗号,,来让WAF认为分界为逗号,,而实际是空值

失败

3、进阶绕过

0x00截断进阶

从前面可知,0x00对于一些WAF来说可能会先删除在检测,而PHP又是自动选择第一行,所以在基础的0x00截断中并没有成功将filename=截断

进阶的内容就是,当我们在适当的地方加入0x00、空格和\t后,就会破坏第一行,让PHP反以第二行为主

这三个位置为首选:替换成0x00、0x20同理

此外还有:

最容易被忽视的是参数名中的 0x00

由此测试还有一个十分鸡肋的方式,用处不大,但有意思。只有当网站获取全部 POST 数组

后以参数前缀来取值的场景才可利用,因为参数名后缀部分不可控。

在三个首选位置中,最后一个位置成功了

boundary 进阶

boundary 的名称是可以前后加入任意内容的,WAF 如果严格按 boundary 去取,又要上当了。

通过空格去破坏Content-Type,使PHP取第二个,WAF取一个。但是比较吃Nginx的版本

很可惜的是WAF并没有取后面的b

单双引号混合进阶

通过不规范的单双引号破坏,使PHP取第二个,WAF取第一个

WAF也取了第二个,失败

urlencoded 伪装成为 multipart

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

也就是说,它想要通过urlencoded去传递参数,而传递的这三个参数构成了form-data的一个样子

由于版本限制,并不能直接按照上图做

猜测它的想法应该是想要利用WAF自动去补齐,然后去第二个Content-Type,那我直接补齐试试

很遗憾没有成功。

4、高阶绕过

skip_upload 进阶 1

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

前面内容中我们介绍了,如果在第一行的 Content-Disposition 位置添加\0,是有可能引起第一行失效,从而从上传文件变为 POST 参数的。

除此以外,我们来看一下php源码 php-5.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还是没有绕过

skip_upload 进阶 2

在 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 个就会出错了。即skip_upload

那么:

看看是否能绕过,还是失败了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/429672.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Wpf使用NLog将日志输出到LogViewer

1 LogViewer LogViewer是通过UDP传输的高性能实时log查看器。 具有一下特性&#xff1a; 通过UDP读取日志通过文件导入日志导出日志到一个文件中排序、过滤&#xff08;日志树&#xff0c;日志等级&#xff09;和查找突出显示搜索文本从UPD接收日志时忽略IP地址列表多接收器支…

Java:Clonable 接口和拷贝

一 Clonable 接口 在 Java SE 中&#xff0c;Cloneable 是一个标记接口&#xff08;Marker Interface&#xff09;&#xff0c;它位于 java.lang 包中。这个接口的主要目的是标识实现该接口的类能够被合法地克隆&#xff08;即可以调用 Object 类中的 clone() 方法&#xff09…

【觅图网-注册安全分析报告-无验证方式导致安全隐患】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 1. 暴力破解密码&#xff0c;造成用户信息泄露 2. 短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉 3. 带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造…

神经网络面试题目

1. 批规范化(Batch Normalization)的好处都有啥&#xff1f;、 A. 让每一层的输入的范围都大致固定 B. 它将权重的归一化平均值和标准差 C. 它是一种非常有效的反向传播(BP)方法 D. 这些均不是 正确答案是&#xff1a;A 解析&#xff1a; ‌‌‌‌  batch normalization 就…

基于SpringBoot+WebSocket实现地图上绘制车辆实时运动轨迹图

实现基于北斗卫星的车辆定位和轨迹图的Maven工程&#xff08;使用模拟数据&#xff09;&#xff0c;我们将使用以下技术&#xff1a; Spring Boot&#xff1a;作为后端框架&#xff0c;用来提供数据接口。Thymeleaf&#xff1a;作为前端模板引擎&#xff0c;呈现网页。Leaflet…

算法之逻辑斯蒂回归(Logistic regression)

简介&#xff1a;个人学习分享&#xff0c;如有错误&#xff0c;欢迎批评指正。 逻辑斯蒂回归&#xff08;Logistic Regression&#xff09;是统计学中一种广泛应用于二分类问题的算法。它的主要目标是预测二分类问题中的事件发生的概率。尽管名字里有“回归”&#xff0c;但逻…

高级I/O知识分享【epoll || Reactor ET,LT模式】

博客主页&#xff1a;花果山~程序猿-CSDN博客 文章分栏&#xff1a;Linux_花果山~程序猿的博客-CSDN博客 关注我一起学习&#xff0c;一起进步&#xff0c;一起探索编程的无限可能吧&#xff01;让我们一起努力&#xff0c;一起成长&#xff01; 目录 一&#xff0c;接口 epo…

【kaggle竞赛】毒蘑菇的二元预测题目相关信息和思路求解代码

毒蘑菇的二元预测 您提供了很多关于不同二元分类任务的资源和链接&#xff0c;看起来这些都是Kaggle竞赛中的参考资料和高分解决方案。为了帮助您更好地利用这些资源&#xff0c;这里是一些关键点的总结&#xff1a; Playground Season 4 Episode 8 主要关注的竞赛: 使用银行…

如何将很多个pdf拼接在一起?很多种PDF拼接的方法

如何将很多个pdf拼接在一起&#xff1f;将多个PDF文件合并不仅能够提升信息的整合性&#xff0c;还能使文件管理更加高效。想象一下&#xff0c;你需要向同事或老师提交一份综合报告&#xff0c;其中包含了多份相关资料。如果每个文件单独存在&#xff0c;查找和传输都会变得繁…

Java 入门指南:JVM(Java虚拟机)—— Java 类加载器详解

类加载器 类加载器&#xff08;Class Loader&#xff09;是 Java 虚拟机&#xff08;JVM&#xff09;的一部分&#xff0c;它的作用是将类的字节码文件&#xff08;.class 文件&#xff09;从磁盘或其他来源加载到 JVM 中。类加载器负责查找和加载类的字节码文件&#xff0c;并…

Python|OpenCV-实现识别目标图像中的圆圈(20)

前言 本文是该专栏的第22篇,后面将持续分享OpenCV计算机视觉的干货知识,记得关注。 在处理图像检测项目的时候,可能会遇到需要检测目标图像中的“圆圈”需求。笔者在这里举个例子,如下图所示: 在图中有一个篮球,但是我们要找的目标对象并不是篮球,而是篮球它本身的这个…

MySQL安装教程

MySQL安装教程 如果需要删除原有mysql&#xff0c;然后安装过新的&#xff0c;可以参照如何彻底卸载旧mysql重装测试 1. 准备资源 mysql官网直达&#xff1a;https://dev.mysql.com/downloads/mysql/ CADN&#xff1a;https://download.csdn.net/download/luocong321/89592962 …

《深度学习》PyTorch框架 优化器、激活函数讲解

目录 一、深度学习核心框架的选择 1、TensorFlow 1&#xff09;概念 2&#xff09;优缺点 2、PyTorch 1&#xff09;概念 2&#xff09;优缺点 3、Keras 1&#xff09;概念 2&#xff09;优缺点 4、Caffe 1&#xff09;概念 2&#xff09;优缺点 二、pytorch安装 1、安装 2、…

【人工智能】在大型活动中的应用案例

人工智能在娱乐大型活动中的应用 ## 作者主页: 知孤云出岫 目录 **人工智能在娱乐大型活动中的应用****1. 引言****2. 智能票务与入场管理****2.1 动态定价与票务预测****2.2 生物识别技术快速入场****2.3 区块链技术防伪票务管理** **3. 智能观众互动与个性化体验****3.1 个性…

CCF csp认证 小白必看

c支持到C17(还是更高?)&#xff1b;所以学一些封装好的函数功能是必要的---比如STL里的函数&#xff1b; 因为可携带纸质资料&#xff0c;建议打印带入&#xff0c;需要时可翻阅。 【题目概述:】 0-devc环境配置 配置好你常用的编译版本&#xff1a; 想要调试记得开启下选…

Python练习宝典:Day 1 - 选择题 - 基础知识

目录 一、踏上Python之旅二、Python语言基础三、流程控制语句四、序列的应用 一、踏上Python之旅 1.想要输出 I Love Python,应该使用()函数。 A.printf() B.print() C.println() D.Print()2.Python安装成功的标志是在控制台(终端)输入python/python3后,命令提示符变为: A.&…

Linux自主学习篇

用户及权限管理 sudo 是 "superuser do" 的缩写&#xff0c;是一个在类 Unix 操作系统&#xff08;如 Linux 和 macOS&#xff09;中使用的命令。它允许普通用户以超级用户&#xff08;root 用户&#xff09;的身份执行命令&#xff0c;从而获得更高的权限。 useradd…

数据飞轮:打造业务增长的持续循环

在当今数据驱动的世界中&#xff0c;企业必须利用数据的力量才能保持竞争力。然而&#xff0c;仅仅收集和分析数据是不够的&#xff1b;企业必须能够从他们的数据中创造一个持续增长的循环&#xff0c;才能保持成功。其中一种方法就是创建数据飞轮。接下来让我们来探讨一下什么…

网络高级day03(Http)

目录 【1】HTTP简介 【2】 HTTP特点 【3】 HTTP协议格式 1》客户端请求消息格式 1> 请求行 2> 请求头 3> 空行 4> 请求数据 2》服务器响应消息格式 【1】HTTP简介 HTTP协议是Hyper Text Transfer Protocol &#xff08;超文本传输协议&#xff09;的缩写&a…

Python_控制循环语句

if语句单分支结构的语法形式如下&#xff1a; 【操作】输入一个数字&#xff0c;小于10&#xff0c;则打印这个数字(if_test01.py)&#xff1a; num input("输入一个数字&#xff1a;") if int(num)<10: print("小于10的数&#xff1a;"num)条件表达式…