php eval 黑客利用,代码安全审计:当file_exists遇上eval

‍起因‍

昨晚有人在一QQ群上问lcms(一款网站CMS系统)的一个漏洞是怎么形成的,说了半天。他截图不完整,于是叫他传代码,下载回来找到router.php代码片段如下:protected function getInputString($name, $default_value = "", $format = "GPCS")

{

//order of retrieve default GPCS (get, post, cookie, session);

$format_defines = array (

'G'=>'_GET',

'P'=>'_POST',

'C'=>'_COOKIE',

'S'=>'_SESSION',

'R'=>'_REQUEST',

'F'=>'_FILES',

);

preg_match_all("/[G|P|C|S|R|F]/", $format, $matches); //splitting to globals order

foreach ($matches[0] as $k=>$glb)

{

if ( isset ($GLOBALS[$format_defines[$glb]][$name]))

{

return $GLOBALS[$format_defines[$glb]][$name];

}

}

return $default_value;

}

这里我们先来看 getInputString()。

Preg_matach_all 执行搜索$format 中匹配/[G|P|C|S|R|F]/ 的数据 返回一个数组$matches,这样默认的也就是返回了 GPCS 。然后循环这个数组,$GLOBALS 意思是引用一个全局变量,

这段代码的意思就是 ,先取到$format_defines数组里面的一个值 如_GET,再用get方法获取 name的值。这这里代码的本身是不存在问题的。不过最好addslashes ,addslashes请参考:http://www.w3school.com.cn/php/func_string_addslashes.asp

public function Router(){

//Get page request (if any)

$page = $this->getInputString("page", "index");

//Get plugin request (if any)

$plugin = $this->getInputString("system", "Page");

//If there is a request for a plugin

if(file_exists("core/plugs/".$plugin."Starter.php")){

//Include Page fetcher

include("core/plugs/".$plugin."Starter.php");

//Fetch the page and get over loading cache etc...

eval("new ".$plugin."Starter('".$page."');");

}else if(file_exists("data/modules/".$plugin."/starter.dat")){

//Include Module Fetching System

include("core/lib/ModuleLoader.php");

//Load Module

new ModuleLoader($plugin, $this->getInputString("page", null));

}else{ //Otherwise load a page from the standard system.

//Include Page fetcher

include("core/plugs/PageStarter.php");

//Fetch the page and get over loading cache etc...

new PageStarter($page);

}

}

下面我们来看代码二 调用了这个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(),所以说明这个漏洞是存在的。

漏洞证明:

9fa7c56567b415b3cd241f6f74f61f64.png

‍‍重点来了‍‍

下面开始说重点,群里某牛说其实$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

0230b7553eee21ad046422db4c929c7c.png

如图比正常提交多输出了个 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源码:

[本文作者crsec,本文属于FreeBuf.COM独家发布文章,未经许可禁止转载]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值