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之第四天
Oct 09 PHP
php写的简易聊天室代码
Jun 04 PHP
PHP中date()日期函数有关参数整理
Jul 19 PHP
PHP四舍五入精确小数位及取整
Jan 14 PHP
php中stream(流)的用法
Mar 25 PHP
smarty实现多级分类的方法
Dec 05 PHP
PHP strtotime函数用法、实现原理和源码分析
Feb 04 PHP
PHP+jQuery翻板抽奖功能实现
Oct 19 PHP
thinkphp3.2实现上传图片的控制器方法
Apr 28 PHP
php微信公众账号开发之前五个坑(一)
Sep 18 PHP
php intval函数用法总结
Apr 14 PHP
基于Laravel-admin 后台的自定义页面用法详解
Sep 30 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
php指定函数参数默认值示例代码
2013/12/04 PHP
PHP实现动态删除XML数据的方法示例
2018/03/30 PHP
PHP中quotemeta()函数的用法讲解
2019/04/04 PHP
Javascript Boolean、Nnumber、String 强制类型转换的区别详细介绍
2012/12/13 Javascript
jquery显示和隐藏div特效实例
2013/02/27 Javascript
在新窗口打开超链接的方法小结
2013/04/14 Javascript
Jquery AJAX POST与GET之间的区别
2013/11/14 Javascript
鼠标选择动态改变网页背景颜色的JS代码
2013/12/10 Javascript
javascript定义变量时带var与不带var的区别分析
2015/01/12 Javascript
jQuery插件MixItUp实现动画过滤和排序
2015/04/12 Javascript
JS简单实现多级Select联动菜单效果代码
2015/09/06 Javascript
基于jquery实现页面滚动时顶部导航显示隐藏
2020/04/20 Javascript
jQuery实现无限往下滚动效果代码
2016/04/16 Javascript
JavaScript操作表单实例讲解(上)
2016/06/20 Javascript
Vue方法与事件处理器详解
2016/12/01 Javascript
canvas实现图片根据滑块放大缩小效果
2017/02/24 Javascript
vue微信分享出来的链接点开是首页问题的解决方法
2018/11/28 Javascript
Vue实现PC端靠边悬浮球的代码
2020/05/09 Javascript
初步解析Python中的yield函数的用法
2015/04/03 Python
python装饰器深入学习
2018/04/06 Python
python 多维切片之冒号和三个点的用法介绍
2018/04/19 Python
python可视化实现代码
2019/01/15 Python
python topk()函数求最大和最小值实例
2020/04/02 Python
win10从零安装配置pytorch全过程图文详解
2020/05/08 Python
详解如何用canvas画一个微笑的表情
2019/03/14 HTML / CSS
中国最大的名表商城:万表网
2016/08/29 全球购物
美国高档百货Nordstrom的折扣店:Nordstrom Rack
2017/11/13 全球购物
Belvilla法国:休闲度假房屋出租
2020/10/03 全球购物
工程管理造价应届生求职信
2013/11/13 职场文书
国际政治个人自荐信范文
2013/11/26 职场文书
企业军训感想
2014/02/07 职场文书
关于工作时间玩手机的检讨书
2014/09/18 职场文书
2014年医生工作总结
2014/11/21 职场文书
欢迎词范文
2015/01/27 职场文书
Pytorch 使用tensor特定条件判断索引
2021/04/08 Python
Python Django搭建文件下载服务器的实现
2021/05/10 Python