代码安全审计:当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独家发布文章,未经许可禁止转载]

原文发布于微信公众号 - FreeBuf(freebuf)

原文发表时间:2014-12-10

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏owent

Rust的第二次接触-写个小服务器程序

蛮久前入门了一下 Rust 语言。它的设计模型非常地吸引C/C++的开发者。但是学习语言嘛还是要练习一下,之前也用它给我们项目写了个命令行小工具。这回拿来写个小...

1.4K30
来自专栏性能与架构

Redis 新数据结构 - Streams

1. 为什么添加 Streams 数据流? Stream 数据流的使用越来越多,Redis 的作者 antirez 也在积极思考,如何让 redis 能够很好的...

43060
来自专栏FreeBuf

如何绕过Windows 10的CFG机制

前言 本文来源于我在2016年7月的研究结论,由于各种原因现在才能发布。2016年6月,Theori曾发表了一篇关于MS16-063中修补了的IE漏洞分析,文中...

23260
来自专栏UDNZ

【译】Go 语言实践:编写可维护的程序的建议

本文为 QCon 2018 上海站主题演讲嘉宾、Heptio 资深工程师、著名 Go 语言专家 David Cheney 关于 Go 语言实践的英文分享。为方便...

52380
来自专栏LuckQI

Java核心技术讲解学习

15020
来自专栏AndroidTv

移动端造json假数据时的坑(转义符问题)

迭代开发中,经常出现服务端接口还没开发完成的情况,所以经常需要移动端自己在本地造一些假数据。

41750
来自专栏吉浦迅科技

DAY41:阅读Synchronization Functions

waits until all threads in the thread block have reached this point and all glob...

9130
来自专栏CDA数据分析师

热度碾压 Java、C#、C++的 Python,为什么速度那么慢?

眼下 Python 异常火爆,不论是 DevOps、数据科学、Web 开发还是安全领域,都在用 Python——但是它在速度上却没有任何优势。

18710
来自专栏游戏杂谈

php正则表达式的分组捕获

经过测试,发现php正则表达式获取分组捕获是从$0开始,而平时工作中JavaScript中的正则是$1..$9

16430
来自专栏java一日一条

Java 元编程及其应用

同样是实现一个投票系统,一个是python程序员,基于django-framework,用了半小时就搭建了一个完整系统,另外一个是标准的SSM(Spring-S...

21210

扫码关注云+社区

领取腾讯云代金券