前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[安全入门教学]如何分析海洋CMS漏洞

[安全入门教学]如何分析海洋CMS漏洞

作者头像
安恒网络空间安全讲武堂
发布2018-02-06 12:10:39
4K0
发布2018-02-06 12:10:39
举报

看到freebuf上有一篇为《漏洞预警 | 海洋CMS(SEACMS)0day漏洞预警》的文章,展示了关于漏洞使用的POC,这里我们来完整的分析一下POC的原理以及漏洞成因。

我分析使用的版本是seacms6.53

其中post的数据如下:

代码语言:js
复制
searchtype=5&searchword={if{searchpage:year}&year=:e{searchpage:area}}&area=v{searchpage:letter}&letter=al{searchpage:lang}&yuyan=(join{searchpage:jq}&jq=($_P{searchpage:ver}&ver=OST[9]))&9[]=ph&9[]=pinfo();

关键的位置如下 search.php中:

在include/main.class.php parseIf()中,特殊构造的字段被送进了eval()中:

那接下来我们就看一看如何构造以及如何绕过各个过滤函数。

我们由上图可以看到,传入eval()的变量是$strIf,$strIf=$iar[1][$m]

那$iar又是由preg_match_all($labelRule,$content,$iar)获取

其中$labelRule = buildregx("{if:(.*?)}(.*?){end if}","is"),buildregx()在include/common.func.php中:

所以$labelRule = ‘/{if:(.*?)}(.*?){end if}/is’

因此根据preg_match_all()的用法,返回的数组中$ iar [0]保存完整模式的所有匹配, $ iar [1] 保存第一个子组的所有匹配,即{if:(.*?)}中的(.*?)的内容,$ iar [2] 保存第二个(.*?)指代的内容。所以我们的目标就是构造一个满足正则的参数。

我们再回到之前的search.php,可以看到,传入parseIf()的参数是$content,而$content,我们向上看可以看到这个变量经过了很多很多很多的变化。。。看的似乎要晕过去,不过我们还是要慢慢理一理。。。

我们可以看到$content经过了多次的str_replace(),也就是多次的替换:

看到多次的替换,我们可以想到什么呢,重复替换,什么意思呢,拿上图举例子,str_replace()替换的规则是将参数3中的参数1替换成参数2,因为语句是逐条执行的,所以如果我们在$page中包含下一条替换的内容{seacms:searchword},那么执行下一条语句的时候就会替换{seacms:searchword}这个位置,然后我们在$searchword中再包含下一条语句替换的{seacms:searchnum},以此类推,那么这样就可以达到一种拆分替换的方法,达到绕过关键词检测的目的。

然后我们就需要找到这些被替换的位置在哪里,通过全局搜索,我们会找到像{searchpage:year},{searchpage:area},{searchpage:letter}等包含这些要被替换的标签的页面是templets\default\html\cascade.html,但是在页面内{searchpage:page},{seacms:searchnum}等是不存在的,因此在选取被替换的变量要经过筛选。

因此我们需要使用页面cascade.html的话,阅读一下代码,大致推断出要满足$searchtype=5.

我看看到poc选取的第一个变量是$searchword,因为{seacms:searchword}是存在于页面中的。然后后面的变量选取的话,思路就是之前那样,只要按照顺序下来就可以了。代码顺序如下:

所以整个思路有了,那接下来就是看一下我们如果传入参数,会有哪些过滤。

还是在search.php页面中,上移我们会看到这些变量传入都经过RemoveXSS(),addslashes(), cn_substr()

在include/common.func.php中我们可以看到RemoveXSS()就是常见的XSS防御函数,把关键字段给过滤了。

addslashes()就是php自带的转义函数,就是对某些字符前加上反斜杠。

cn_substr()同样是在include/common.func.php中,对变量的长度做了限制,长度限制为20,

这几个函数就不贴了,因为有点长,想看内容的话可以自己打开源码看一看。

然后在\include\common.php中也有输入检查函数,差不多是全局的addslashes()。

那过滤手段我们知道了,就是全局的addslashes(),加上一些关键词过过滤,所以我们就要避开这些雷区,addslashes()一般是防注入的,但是RemoveXSS()却过滤了很多字段,那这时候,就要用上我们之前的那个连续替换的方法来绕过了。

但是由于20这个长度限制, 即使使用拼接的手段依然又限制,因此这里还使用了另外一个相对猥琐的思路。

POST的数据最后几个数据:

&yuyan=(join{searchpage:jq}&jq=($_P{searchpage:ver}&ver=OST[9]))&9[]=ph&9[]=pinfo();

这里拼接起来其实是$_POST[9],然后在$_POST[9][]中传入数据,而且最重要的是,我们可以在这里把想要执行的代码不停的拆分就可以了!我们传入对的数据被拆分后放在了$_POST[9]这个数组里,而&yuyan=(join{searchpage:jq},这里拼接上去的是join()函数,join()根据php手册中介绍是implode()的别名,作用是将一个一维数组的值转化为字符串,但是如果使用implode()长度将超过20,因为我们可以发现&yuyan使用join()长度这样刚好是20,完美的绕过,到达拼接我们后面上传的数组的目的。而这个9其实只是一个key值,是可以随意更改的,后面的&9[]=ph&9[]=pinfo();其实只要能绕过过滤函数,长度小于20,那就随便执行命令啦,这里直接改成&9[]=phpinfo();都是没有问题的!

这就是对该漏洞以及对应POC的分析过程,毕竟菜鸡刚上路,有啥不好不全的地方请狂吐槽!

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-10-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 恒星EDU 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档