前言
maccms8.x命令执行漏洞分析现场…..
先放上POC

漏洞分析
根据POC,来到index.php

然后跟进be()

也就是说通过get请求发送$m
再将$m打散成$par
先看$par[0]

我们跟到vod.php然后这个’search’为method之一.看看wd在search中是怎么用的

然后这里的$wd可以通过任何形式的请求获得.
知道了$m的作用,然后我们回到index.php,看看这里是如何解析$wd
跟进到$tpl->ifex();

这里指定一个匹配规则:{if-([\s\S]?):([\s\S]+?)}([\s\S]?){endif-\1}
$this->H在vod.php中可以找到:

所以实际上,
1 | preg_match_all($labelRule,$this->H,$iar); |
这段代码是在匹配获得我们输入参数后的html页面的符合匹配规则的字符串放入$iar中.
这里的正则匹配如果看不懂了,建议debug动态调试一下,有助于理解

进入一个for循环

底下的代码可以看到一堆eval()

这个就是漏洞的触发点,要做的就是绕过限制,触发命令执行.
找到912行处,这里对eval的限制最少.

所以最终我们输入的wd参数带有{if-就可以绕过,因为最前面有这么一行代码:
1 | if (!strpos(",".$this->H,"{if-")) { return; } |

然后还要满足匹配规则:{if-([\s\S]?):([\s\S]+?)}([\s\S]?){endif-\1}
所以构造payload:
1 | {if-A:(phpinfo())}{endif-A} |
总结
这个漏洞不难,根据POC,也能很快的分析出来.
就是中间发现原来自己对preg_match_all()这个函数的用法一直没有理解通透.

学长和我说正则匹配出的数组中存储的信息,要看它正则表达式是怎么写的:
表达式:{if-([\s\S]?):([\s\S]+?)}([\s\S]?){endif-\1}
所以他匹配的结果就是一个二维数组$iar
以下是$iar[0]的内容:

这是根据正则规则,匹配出的所有字符串
以下是$iar[2]的内容:

发现没有$iar[2]的内容就是第二个[\s\S]的匹配内容
以下分别是$iar[1]和$iar[3]的内容

