PHP中一个有趣的preg_replace函数详解


Posted in PHP onAugust 15, 2018

0x01 起因

事情的起因是下午遇到了 preg_replace 函数,我们都知道 preg_replace 函数可能会导致命令执行。现在我们来一些情况。

0x02 经过

踩坑1:

测试代码大概是这样的:

foreach ($_GET as $regex => $value) {
 preg_replace('/(' . $regex . ')/ei','strtolower("\\1")',$value);
}

测试过程中发现通过浏览器的方式传入数据的时候,会将 . + 等特殊字符转换为 _ 。

PHP中一个有趣的preg_replace函数详解

PHP中一个有趣的preg_replace函数详解

这里涉及到了php的一个特性

php自身在解析请求的时候,如果参数名字中包含空格、.、[等字符,会将他们转换成_。

<?php
$a = $_GET;
var_dump($a);
?>

PHP中一个有趣的preg_replace函数详解

经过我的fuzz,结果如下图:

PHP中一个有趣的preg_replace函数详解

踩坑2:

那我们知道 preg_replace 的 /e 修正符会将 replacement 参数当作 php 代码,并且以 eval 函数的方式执行,前提是 subject 中有 pattern 的匹配。既然是这样我们看一张图。

PHP中一个有趣的preg_replace函数详解

图中实际上通过 eval 执行的是 strtolower 函数。分别实际执行的是:

strtolower("JUST TEST");
strtolower("PHPINFO()");
strtolower("{${PHPINFO()}}");

第三个之所以可以执行代码,是因为我们通过复杂(花括号)语法的方式来让其代码执行。

踩坑3:

回到源代码中,我们再理解一下:

foreach ($_GET as $regex => $value) {
 preg_replace('/(' . $regex . ')/ei','strtolower("\\1")',$value);
}

这里的 replacement 是 strtolower(“\\1”) ,着重理解一下 \\1 。

每个这样的引用将被匹配到的第n个捕获子组捕获到的文本替换。 n可以是0-99,\0和\$0代表完整的模式匹配文本。

假设一个正则表达式是这样的:

preg_replace('/(.*)(\?|&)' . $key . '=[^&]+?(&)(.*)/i', '$1$2$4', $url . '&');

这里的 \$1\$2\$4 等同于上面的 \1\2\4 的作用,因此我们看一下是怎么选择匹配的。

$1 $2   $3 $4
'/(.*)(\?|&)' . $key . '=[^&]+?(&)(.*)/i'

0x03 解决

好了上面都已经铺垫完坑了,这里要开始解决了。

foreach ($_GET as $regex => $value) {
 preg_replace('/(' . $regex . ')/ei','strtolower("\\1")',$value);
}

我们想要让这部分代码达到代码执行的效果需要达到几个条件:

  • pattern 部分的表达式需要命中 \$value 中的数据
  • \1 中取出的数据复杂(花括号)语法的特征,来保证在双引号的包含下达到代码执行的效果
  • 由于php的特性url会将 . 、 [ 、 + 等特殊字符转换为 _ 。

我们知道这里是通过 get 方式获取到 \$regex 和 \$value 的,要想在 replacement 部分通过 \1 截取到 pattern 正则匹配命中 \$value 中的数据,并且携带 \$ 、 { 、 ( 这里就涉及到正则表达式的使用了。

这里我选择了 \S ,也就是匹配任意的非空白字符,那么最后的payload长这样

\S*()={${phpinfo()}}

PHP中一个有趣的preg_replace函数详解

PHP中一个有趣的preg_replace函数详解

0x04 后记

其实还有点小问题,我这边没有写,不过大家可以看看这个深入研究preg_replace与代码执行。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

PHP 相关文章推荐
用PHP编写PDF文档生成器
Oct 09 PHP
PHP的分页功能
Mar 21 PHP
PHP中防止SQL注入实现代码
Feb 19 PHP
PHP使用range协议实现输出文件断点续传代码实例
Jul 04 PHP
php从数组中随机选择若干不重复元素的方法
Mar 14 PHP
YII Framework框架教程之安全方案详解
Mar 14 PHP
php实现三级级联下拉框
Apr 17 PHP
将PHP的session数据存储到数据库中的代码实例
Jun 24 PHP
Thinkphp5结合layer弹窗定制操作结果页面
Jul 07 PHP
PHP扩展Swoole实现实时异步任务队列示例
Apr 13 PHP
laravel框架模型中非静态方法也能静态调用的原理分析
Nov 23 PHP
解决thinkphp6(tp6)在状态码500下不报错,或者显示错误“Malformed UTF-8 characters”的问题
Apr 01 PHP
PHP使用curl_multi_select解决curl_multi网页假死问题的方法
Aug 15 #PHP
php+croppic.js实现剪切上传图片功能
Aug 14 #PHP
PHP设计模式之委托模式定义与用法简单示例
Aug 13 #PHP
PHP设计模式之建造者模式定义与用法简单示例
Aug 13 #PHP
PHP设计模式之装饰器模式定义与用法简单示例
Aug 13 #PHP
PHP实现的ID混淆算法类与用法示例
Aug 10 #PHP
PHP+ajax实现二级联动菜单功能示例
Aug 10 #PHP
You might like
ThinkPHP3.1.3版本新特性概述
2014/06/19 PHP
PHP自定义多进制的方法
2016/11/03 PHP
详谈php中 strtr 和 str_replace 的效率问题
2017/05/14 PHP
PHP切割汉字的常用方法实例总结
2019/04/27 PHP
一个js拖拽的效果类和dom-drag.js浅析
2010/07/17 Javascript
统计jQuery中各字符串出现次数的工具
2012/05/03 Javascript
AngularJS删除路由中的#符号的方法
2016/09/20 Javascript
微信小程序 教程之注册页面
2016/10/17 Javascript
bootstrap模态框消失问题的解决方法
2016/12/02 Javascript
Angular2平滑升级到Angular4的步骤详解
2017/03/29 Javascript
JS实现电商放大镜效果
2017/08/24 Javascript
vue-router实现组件间的跳转(参数传递)
2017/11/07 Javascript
ajax前台后台跨域请求处理方式
2018/02/08 Javascript
傻瓜式解读koa中间件处理模块koa-compose的使用
2018/10/30 Javascript
Vue props 单向数据流的实现
2018/11/06 Javascript
Vue中props的详解
2019/05/16 Javascript
微信小程序利用Canvas绘制图片和竖排文字详解
2019/06/25 Javascript
vue中nextTick用法实例
2019/09/11 Javascript
基于vue+uniapp直播项目实现uni-app仿抖音/陌陌直播室功能
2019/11/12 Javascript
JS实现横向跑马灯效果代码
2020/04/20 Javascript
js模拟实现百度搜索
2020/06/28 Javascript
vue data变量相互赋值后被实时同步的解决步骤
2020/08/05 Javascript
javascript的hashCode函数实现代码小结
2020/08/11 Javascript
ES11新增的这9个新特性,你都掌握了吗
2020/10/15 Javascript
Django框架登录加上验证码校验实现验证功能示例
2019/05/23 Python
python 5个顶级异步框架推荐
2020/09/09 Python
初一英语教学反思
2014/01/11 职场文书
合同协议书格式
2014/04/18 职场文书
市级优秀班主任事迹材料
2014/05/13 职场文书
新闻工作者先进事迹
2014/05/26 职场文书
安全检查汇报材料
2014/12/26 职场文书
维稳工作承诺书
2015/01/20 职场文书
给女朋友道歉的话大全
2015/01/20 职场文书
PyTorch 如何检查模型梯度是否可导
2021/06/05 Python
Mysql数据库值的添加、修改、删除及清空操作实例
2021/06/20 MySQL
GoFrame gredis缓存DoVar Conn连接对象 自动序列化GoFrame gredisDo/DoVar方法Conn连接对象自动序列化/反序列化总结
2022/06/14 Golang