phpCMS历来以漏洞多著称,其2008版本继承了之前版本的光荣传统,存在各种危害程度不同的漏洞。下面我们来看一个已经在后期更新中补掉的本地文件包含漏洞,但是该漏洞的利用方式还是比较有意思的。
漏洞代码很简单,相信很多人都看到了。
pay/respond.php
- require \'./include/common.inc.php\';
- $pay_code = !emptyempty($code) ? trim( $code ) : "";//$pay_code没过滤
- if ( emptyempty( $pay_code ) )
- {
- showmessage(\'校验失败\');
- }
- else
- {
- $plugin_file = PHPCMS_ROOT.\'pay/include/payment/\'.$pay_code.\'.php\';
- if (is_file($plugin_file))
- {
- include_once( $plugin_file );//产生本地文件包含漏洞
很多同学看到这个地方,也许会觉得很鸡肋。无论是采用上传图片包含的办法还是直接包含日志,都需要用%00或者若干[/////]截断后面的.php,而这个都对php.ini或者系统有一定要求。事实上不是这样的,结合phpcms自身的其他缺陷,我们很可以通过二次攻击将这个本地文件包含漏洞的威力放到,下面我给出两个利用的思路。
利用方式一:绕过后台认证,转化为代码执行漏洞
细心读过phpcms2008早期版本代码的朋友应该都发现了(现在最新版本的貌似改过了),它的后台登陆认证都是在admin.php文件中实现的,然后通过下面这样的代码包含admin目录下的文件实现其他复杂的管理功能
- if(!@include PHPCMS_ROOT.(isset($M[\'path\']) ? $M[\'path\'] : \'\').\'admin/\'.$file.\'.inc.php\') showmessage("The file ./{$M[\'path\']}admin/{$file}.inc.php is not exists!");
为了不让非管理员用户访问admin目录下的相关文件,该目录下所有文件的开头采用了如下的代码来做处理,并没有做权限认证。
- defined(\'IN_PHPCMS\') or exit(\'Access Denied\');
有了这段代码,我们基本上没办法直接访问了。IN_PHPCMS这个常量是在文件/include/common.inc.php中定义的,代码如下
- define(\'PHPCMS_ROOT\', str_replace("\\", \'/\', substr(dirname(__FILE__), 0, -7)));
- define(\'MICROTIME_START\', microtime());
- define(\'IN_PHPCMS\', TRUE);
而在产生漏洞的respond.php文件,第一行就包含了/include/common.inc.php文件,这样的话,理论上我们直接利用该本地文件包含漏洞包含admin目录下的文件,就可以直接使用后台的管理功能了。但是实际利用的时候,我们还要考虑后台文件中可能有些函数是调用的admin.php文件中的,所以我们有可能会遇到未定义函数的错误,但是在Phpcms中我们幸运的避免了这个问题。看代码:
admin/template.inc.php
- defined(\'IN_PHPCMS\') or exit(\'Access Denied\');
- //引入模版函数文件
- if($action != \'tag\' && $action != \'preview\') require_once \'template.func.php\';
- //初始化一堆变量
- if(!$forward) $forward = HTTP_REFERER;
- $module = isset($module) ? $module : \'phpcms\';
- $project = isset($project) ? $project : TPL_NAME;
- $templatedir = TPL_ROOT.$project.\'/\'.$module.\'/\';
- $projects = cache_read(\'name.inc.php\', TPL_ROOT);
- //common.inc.php已经包含了定义过cache_read的文件了