[代码审计]记一次渗透中的代码审计

作者: Luan 分类: 代码审计 发布时间: 2017-08-10 11:48

文章首发于蛇皮团队的知乎专栏

https://zhuanlan.zhihu.com/shepi

 

最近一直忙着做各种事情,,总结下好像什么也没做成。。。

整理,重写了下一篇一年前的文章,分享一点思路给大家。

首先渗透的起因是这样的。 那时候我闲着无聊看看补天的主页,发现有人提交了XX公司XX漏洞,奖金RMBXX元(具体记不太清了)。

然后我就想去捡捡漏。。。貌似大家都喜欢这样?

百度搜索了一下那公司的名字,找到了他们公司的官网。

一下还看不出是什么CMS,一般这种公司展示的网站都是用CMS做的,不会自己找程序员写新的。大多都是dede。

拿到这个站后,先看看他的URL。

/news/index.php?c=show&id=xx

他这里是比较普通的一个URL,也看不出什么,顺手测试下sql注入,发现不存在。。要是存在就没有下文了。

然后又简单看了看几个别的页面,没什么特殊的地方,功能也很少,就是展示下公司新闻。

这种情况就得掏出扫描器扫一下目录文件了。

扫了下,发现存在member目录。

然后思路就多了一条了。先注册试试。

网站也没有关闭注册,顺利注册登录。

登录后直接跳转到了主页,于是再访问member目录,成功进入会员中心。

但是蛋疼得发现所有的功能都还不可用,是待审核会员,需要等待审核。。。

然后扫描器还扫到一个adminkey.php,访问发现是一个后台登陆页面,测了下注入也不行。

如果有注入的话,结果可能就是我的另一篇文章了:对某CMS的一次简单渗透测试 – Luan's Blog

到目前为止,虽然我没有挖到漏洞,但是废话了很多,顺带发现了一些信息。这个网站是使用的XXCMS,然后根据后台页面的提示,这个CMS是XXX公司开发的。貌似首页下面也有写技术支持:XXXX。

那么就有思路了,去下载这个CMS来审计一下看看有没有什么漏洞好利用的。

百度他们公司名字,发现没有提供这个CMS的下载,百度这个CMS,发现没有一点关于这个CMS的信息,全是其他杂七杂八的东西。

然后就想到这个可能不是一个开源的CMS。

那么思路就得变通一下,去寻找使用这个CMS的网站,找脆弱的拿到这个CMS的源码。

那么具体怎么找呢?

找这个网站上比较特别的地方,去搜,最好不要使用百度了,谷歌搜的更全。通过搜索:

“技术支持:XXXX”

inurl:/news/index.php?c=show&id=

采集到了一些应该是使用这个CMS的网站。

然后又怎么快速获取源码呢?

批量扫备份。我这里是只扫备份文件,很快就真找到了一个。运气不错,如果没有找到的话,得费点功夫弄旁站什么的了,你们懂我的意思吧?

下载备份文件:http://www.xxxxxx.com/wwwroot.rar,解压,打开工具开始审计。

先看index.php里写的什么鬼东西。(实际上我当时直接就上法师工具自动审计,快速搜漏洞点的。这里为了写的更明白点,就先假装是看index.php吧。一般比较熟悉后,想快速定位漏洞,直接找敏感函数回溯就可以了。)

看了index.php,马上知道这个CMS是使用了CI框架。

怎么知道的?看代码结构啊。看不太懂?看第39行注释你总得懂了吧。

然后就去看他的一些控制器的代码

为什么这么做?

这就是,不解释审计。

然后开始不解释审计:

读api.php

直接看公开的方法。一路往下看。构造函数什么也没做,第二个方法调用了一个api_template方法。sublime快捷键ctrl+shift+f 搜索定位到定义处。

好了,不用看了,不存在什么高危漏洞。回到api.php,继续读下一个方法。

hits方法这里把获取到的内容强制转换成了整数型,不能注入。

desktop方法看注释就不用看了,跳过。

test方法没用,不过当作这个CMS的指纹挺不错。

data方法先是判断get[‘auth’]是否等于SYS_KEY常量。这个常量我们可以先搜下看看是多少。

这个常量就是 这个CMS的名字,应该不会 是随机生成的,也就是存在默认值。

接着data方法第121行,获取的get[‘param’]传入了list_tag方法,搜索跟入。

定义了几个数组,然后用空格分隔传入的参数,也就是get[‘param’],放入到$params中。那么现在这个$params就是可以控制的。接着426行,foreach遍历它。接续看。

用 ‘=’ 分割数组中的元素,放入到$var,$val变量。然后经过一系列的判断,$var当作key,$val当作value赋值到$system或者$param或者$where。

那么现在这三个变量都是可以控制的了。

然后是替换掉$system[‘order’]中的非法字符。再就进入switch语句。

当$system[‘action’]是等于cache的时候:

把$param[‘name’]用 ‘.’ 分割放到$_name 和 $_param变量里面。

然后把$_name 和 $system[‘site’]传入_cache_var方法,跟进去看下吧。

如果$_name等于某些值,就返回一些固定的值。否则返回$_name和$system[‘site’]传入ci->get_cache方法的返回值。

然后回到list_tag方法。

判断$cache是否为空,是的话就会返回。如果想执行到后面的代码的话,就得让_cache_var方法返回值不是空。前面分析了,如果$_name等于某些值,_cache_var就会返回一些固定值。

接着,492行,$_param传入_get_var方法,返回值就带入了eval函数。如果_get_var的返回值可控的话,我们就可以通过控制$_param变量来注入任意的php代码去执行。

跟入_get_var。

用 ‘.’ 分隔了$param放到$array中,然后遍历$array,对$var进行简单判断,直接拼接到$string变量,然后返回$string。

这里可以发现,返回值$string我们还是可以控制部分,插入恶意php代码。

然后再一层层回溯上去,构建出POC去验证:

成功执行phpinfo().然后我就拿到了目标站的权限。

这个漏洞至今还没有修复,所以我也不方便把这个CMS的名字说出来,全程打马了。

旨在分享思路,不是分享exp然后批量getshell。

凌晨4点多了,可能不太清醒,写得不好的地方望指出。

转载请注明来源: Luan @ 蛇皮安全

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

发表评论

电子邮件地址不会被公开。 必填项已用*标注