最近一直在给cmsPoc写各种cms的exp/poc。遇到了这个配置文件写入从而getshell的洞,想到了P神-代码审计圈里分享过的一道审计题,借此分析一波。
漏洞复现

cmsPoc里用的payload如下:
下面基于这个payload进行分析。
漏洞分析
在 install/index.php 的第44行左右:
在 framework/core/subsystems/expString.php 的第502行
由于 $_REQUEST是个数组,从代码中可以看到只经过了xss_clean的检查,这对我们的payload没有影响。因此经过sanitize后,仍然有sc[SMTP_PORT]=25\\');echo `$_POST[chybeta]`;//
继续分析,install/index.php 的第56行左右:
对于一个已经安装完成的exponent,其文件framework/conf/config.php必定是存在的,所以当传入参数$_REQUEST['sc'],会进入更新config的流程。
expSettings::change定义在 framework\core\subsystems\expSettings.php中的第220行
self::parseFile定义在该文件的第140行,其作用是将config.php中的内容解析出来。接下去的一行,将我们传入的$key和$value进行设置,即执行:
接下去进行写入,即self::saveValues,该函数定义在该文件expSettings.php的第175行左右:
|
|
可以看到对于$value,先经过了一次stripslashes,这会将value值中原有的反斜杠(\)去掉。25\\');echo `$_POST[chybeta]`;//中,25后面的第一个反斜杠(\)将会被去掉,再之后的一个反斜杠(\),被当作是后面单引号的转义符,因此不会被去除。因此$value的值为下面这个:
完成上述操作后,继续执行
由于我们的payload为sc[SMTP_PORT],不以_HTML结尾,且不为SESSION_TIMEOUT,因此会执行下面这条语句:
对应前面的$value,它将$value中的单引号前又加上了一次反斜杠,导致$value的值现在变为:

最后的操作就是将得到的内容写入到配置文件中了。

|
|
由于第一个反斜杠的存在,它把第二个反斜杠给转义了,从而导致了后面这个单引号的逃逸,进一步的使我们能够成功的闭合define。接下来又利用了php的//注释将原有的括号注释掉,从而getshell。
P神的审计题

与本次漏洞分析异曲同工之妙的一种解法如下:
|
|
经过addslashes后,$str为 aaa\\\';phpinfo();//
经过preg_replace正则匹配后,对\做了转义处理,xxxxx/option.php的内容变为:
同样利用第一个斜杠转义第二个斜杠,从而导致了单引号的逃逸。
另一种解答方法放在 Code-Audit-Challenges PHP challenge-3
更多解答,请见代码审计-知识星球。
(那个,有没有广告费?)