代码安全审计:当file_exists遇上eval
起因
昨晚有人在一QQ群上问lcms(一款网站CMS系统)的一个漏洞是怎么形成的,说了半天。他截图不完整,于是叫他传代码,下载回来找到router.php代码片段如下:
这里我们先来看 getInputString()。
Preg_matach_all 执行搜索$format 中匹配/[G|P|C|S|R|F]/ 的数据 返回一个数组$matches,这样默认的也就是返回了 GPCS 。
然后循环这个数组,$GLOBALS 意思是引用一个全局变量。
$GLOBALS 具体参考:http://php.net/manual/zh/reserved.variables.globals.php
这样$GLOBALS[$format_defines[$glb]][$name]
这段代码的意思就是 ,先取到$format_defines数组里面的一个值 如_GET,再用get方法获取 name的值。这这里代码的本身是不存在问题的。不过最好addslashes ,addslashes请参考:http://www.w3school.com.cn/php/func_string_addslashes.asp
下面我们来看代码二 调用了这个getInputString函数 而这个函数并未做任何过滤,
判断了一下 core/plugs/".$plugin."Starter.php 文件存不存如果在就带入了 eval 。
eval的意思请看这里:http://www.w3school.com.cn/php/func_misc_eval.asp
引用某大牛的一句话“一切进入函数的变量是有害的”。
并且这里的 $page是可控的,也就是说当提交 ?page=’);phpinfo();//
语句就变成这样了 eval (“new ”.$plugin.”starter(‘’);phpinfo();//’)”)
eval里面双斜杠代表注释的意思,这样也就是等于执行了 phpinfo(),所以说明这个漏洞是存在的。
漏洞证明:
重点来了
下面开始说重点,群里某牛说其实$plugin也能phpinfo 本人研究了半天,百思不得其解……
过了许久就大牛就发出来,(?a=echo 1;//../1),悲剧的发现只有一步只差,很感谢这位大牛的指点,现在来分析这句话的意思,于是写了个1.php,代码如下:
<?php
$act=$_GET['a'];if (file_exists('test/'.$act.'2.php')) {eval("echo ('2');".$act);}?>
并且在test文件下建立一个名为12.php的空文件,这也就是指的file_exists遇上eval了。 首先来分析 ,代码的意思是,如果test下 存在 *2.php时就执行下面的代码,正常提交的应该是1.php?a=1 才能执行下面的。输出 1
然而我们提交的是 1.php?a=echo 1;//../
http://localhost/1.php?a=echo%201;//../1
如图比正常提交多输出了个 1 也就是说 我们提交的 echo 1 执行了。把提交内容写进代码上也就是if (file_exists('test/echo 1;//../12.php'))
为什么会执行下面的eval呢? 可能是file_exists处理方式吧。 把echo 1;/ 当作了一个目录处理 ,然后 /../ 就放回了上级目录也就是变成了 if (file_exists('test/12.php')) ,然而我我们test的目录下是有12.php。所以这个判断放回了ture,也就是说进入了eval。
Eval的这段代码 就变成了 evil(“echo (‘2’);echo 1;//../1”) ,上面提到过// 是注释后面的代码,所以就输出了图上的 21 。
总结
尽量少使用eval ,并且过滤能控制的变量。这个CMS系统的修补方式是写一个函数过滤掉,$plugin 中的 / ,并且过滤$page 。如果不写上面那个csm的例子大家可能会认为提到这个file_exists 遇上 eval 不怎么实际。
一些看似用处不大的东西往往会产生漏洞,代码安全审计最重要的就是:细心与耐心,细节决定成败。
最后附上CMS源码:
链接: http://pan.baidu.com/s/1vri8Y 密码: okpq
[本文作者crsec,本文属于FreeBuf.COM独家发布文章,未经许可禁止转载]
- Shell系列-Shell概述
- sqoop2系统入门之2汇总:用户指南shell命令
- 深入解析golang编程中函数的用法
- MySQL数据库(一):安装MySQL数据库
- Spring Security入门(二):基于数据库验证
- flume搜集日志:如何解决实时不断追加的日志文件及不断增加的文件个数问题
- hduoj-----(2896)病毒侵袭(ac自动机)
- MySQL数据库(二):基本管理
- Golang编程实现生成n个从a到b不重复随机数的方法
- TiDB 在株式会社 FUNYOURS JAPAN 的应用
- MySQL数据库(三):数据类型
- spark开发环境详细教程2:window下sbt库的设置
- hdu----(2222)Keywords Search(ac自动机)
- MySQL数据库(四):约束条件
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 哈希表:解决了两数之和,那么能解决三数之和么?
- 双指针法:一样的道理,能解决四数之和
- 【python-opencv】轨迹栏作为调色板
- springBoot 线程池异步编程
- MPU6050姿态解算2-欧拉角&旋转矩阵
- 【python-opencv】图像的基本操作
- 3 分钟生成一个单元测试报告,这个样式爱了
- 拼多多的底层逻辑
- 详解ELF重定向原理
- 干货 | 携程基于Quasar协程的NIO实践
- 【python-opencv】图像上的算术运算
- 个人珍藏的80道多线程并发面试题(11-20答案解析)
- 【python-opencv】性能衡量和提升技术
- 【python-opencv】转换颜色空间
- 七夕,当然少不了纯CSS的点缀啦