最近一直在给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
更多解答,请见代码审计-知识星球。
(那个,有没有广告费?)