先说一下结果,几个月前,在部分有SRC的厂商的测试中,有5家使用js跳转(其他使用302跳转),4家存在xss
,这一处的xss
很容易被厂商忽视。
随着各大厂商对安全的重视和投入越来越大以后,一些非常重要的核心cookie
都被设置为httponly
,即使攻击者得到了一个一般域名下的xss
,也很难直接劫持用户的身份认证信息,但是这一部分所讲述的xss
恰恰通常是存在于登陆域名下的,这样域名下的xss
将更加容易利用。
登陆过程一般都是从厂商的某个链接跳转到第三方,而不是直接进入第三方登陆链接,相当大部分的厂商会存在一个跳转用的参数,这个参数的作用是,当第三方登录通过,携带state、code
回调后set-cookie
,之后进行的跳转目标。
比如某厂商的登陆链接为:
https://passport.aaa.com/login?type=QQ&u=https://www.aaa.com/xianzhitest
访问之,进入QQ快捷登陆链接。
通过了QQ登录之后,携带认证得到的code和state回调,登录,set-cookie
https://passport.aaa.com/auth?code=565B415BD1DE9&state=1583668657
可以看到,多个cookie
都被设置了httponly
。这个时候之前登陆链接中的u参数有了作用,此步setcookie
的同时,还会通过返回的js跳转到之前设置的u参数内容。
如图所示,callbackUrl
为我们之前设置的u参数内容,也就是说当前我们在script
块中有了一处可控点,可控点在script标签内,如果没有做好转义或过滤是一件危险的事情,攻击者可以直接注入unicode字符等,后面贴了这段js代码。
此时你就能明白为什么passport
域下的xss更容易利用,在下方的clearSsoUrls[0]
中,有一个完全不同于aaa.com
的域名bbb.com
,即跨域设置cookie,这段js通过clearSsoUrlArray.forEach
遍历clearSsoUrls[0]
中的每个url并设置为image的src属性,通过xss
获取这一段ticket
就可以劫持帐号。
var callbackUrl = "https://www.aaa.com/xianzhitest"; var clearSsoUrls = [["https://store.aaa.com/xman/user/ac-set-img-sso-cookie?ticket=c66428aec0","http://www.bbb.com/setssocookieac.php?ticket=c66428aec0"]]; var clearSsoUrlArray = clearSsoUrls[0]; var loadedCount = 0; var len = 0; ssoLogin(clearSsoUrlArray); function ssoLogin(clearSsoUrlArray) { if (clearSsoUrlArray === undefined) { window.location.href = callbackUrl; return; } var imgList = []; len = clearSsoUrlArray.length; if (len === 0) { window.location.href = callbackUrl; return; } clearSsoUrlArray.forEach(function(url, index){ imgList[index] = new Image(); imgList[index].src = url; if (imgList[index].complete) { loadCallback() } else { imgList[index].onload = function () { loadCallback() }; imgList[index].onerror = function () { loadCallback() } } }); } function loadCallback () { loadedCount++; if (len === loadedCount) { window.location.href = callbackUrl; } }
在这顺嘴儿提一下其他利用方法,但是很少满足这种条件,当u参数的域名校验不严格可跳转到evil.com,并且认证code能复用的时候,攻击者就可通过referer劫持用户的code和state直接进行认证。
<script type="text/javascript"> var callbackUrl="https://xz.aliyun.com"; window.location.href=callbackUrl; </script>
另外,如果我们的可控点被转义了单双引号,无法跳出单引号双引号时,可以尝试javascript
伪协议,比如:javascript://%0aalert(1)
,因为最终会通过window.location.href
跳过去时触发xss。
<script type="text/javascript"> var callbackUrl="javascript://%0aalert(1)"; window.location.href=callbackUrl; </script>
修复:
其实这一段并不是什么新的攻击手法了,早在很久之前就已经出现了这种攻击手法,并且引起了QQ强制加强网站应用回调地址校验,但是weibo快捷登陆并没有设置这种强校验,如果weibo快捷登陆配置错误,就会存在问题,所以还是写一下,同时也说一下我在测试中遇到的这类问题。
得到一个QQ快捷登陆的链接是这个样子
https://graph.qq.com/oauth2.0/show?which=Login&display=pc&client_id=100312028&response_type=code&redirect_uri=https%3A%2F%2Fpassport.baidu.com%2Fphoenix%2Faccount%2Fafterauth%3Fmkey%3Dee36f9305947139a0bfc14f0045d89577008093404cf50ef4e%26tpl%3Dmn&state=1583675451&display=page&scope=get_user_info%2Cadd_share%2Cget_other_info%2Cget_fanslist%2Cget_idollist%2Cadd_idol%2Cget_simple_userinfo&traceid=
如果我们对redirect_uri
参数进行修改,修改为baidu.com
的一个其他子域名
得到weibo快捷登陆的链接如下:
https://api.weibo.com/oauth2/authorize?client_id=2512457640&response_type=code&redirect_uri=https%3A%2F%2Fpassport.baidu.com%2Fphoenix%2Faccount%2Fafterauth%3Fmkey%3D2339731a1d135c5e11e650c358d4a3dba67ccf17028f56b581%26tpl%3Dmn&forcelogin=1&state=1583675765&display=page&traceid=
同样是修改redirect_uri
为其他的baidu.com子域名
weibo快捷登陆是没有强制校验的,全看应用开发者是如何配置的,这时候就表明baidu并不存在这种问题。
如果某个厂商存在问题的话,我们更换redirect_url
为其他子域名后访问应该是这样的:
如果某个网站的微博快捷登陆可以跳转到任意子域名,在某个子域名下你可以插入一个自己的图片,并且能够接收referer
(或者你有一个xss),那么你就可以通过修改redirect_url
到插入图片的地址来获取referer
进而获取code、state
修复:
这类问题存在于更多的厂商中,但是危害并不是很大,有较大的局限性。
以aaa.com的微博(QQ、微信都可)快捷登陆方式为例,使用一个从未绑定过aaa.com的微博账号登陆成功之后,跳转到:
https://passport.aaa.com/account/sina?code=0e563372a36017
因为是首次登陆的第三方帐号,所以要求用户绑定本站aaa.com账号。
但是,此绑定链接再发给任何一个人都可以正常打开,整个页面没有瞩目的提醒是在绑定,看起来就像是一个登陆页面一样,这很容易被普通用户认为是正常登陆,用户输入账号登陆之后就导致了帐号被攻击者接管。但是因为一个第三方帐号只能绑定一个帐号,所以就有很大的局限性了。
测试中发现,有很多的厂商做了如下的防护,但是每一种都有方法绕过。:
对于1方法,有部分厂商已经在绑定页面做了加强提醒,如下图:
下面这个不光有微博字眼和昵称,连头像也给了出来
但是实际上,攻击者完全可以把微博的头像换成当前测试对象的logo,昵称换成xx官方,这样反倒又增加了攻击者的可信性。
对于2,厂商做了访问一次失效,攻击者可以在获取了认证链接之后自己不去访问,直接给受害者访问。
对于3,厂商做了referer校验,攻击者可以使用一个跳转结合。
在这里再提一嘴,某厂商的通过没有绑定账号的第三方登陆之后,返回的链接如下:
https://passport.aaa.com/account/sina?code=0e563372a36017&weiboname=testtest&weibopic=https://img.weibo.com/xxx.jpg
这是一个像上面说的那样,在页面通过显示第三方昵称和头像,来提醒你目前正在绑定社交账号的链接,而昵称和头像竟然是我们可控的,虽然不存在xss,但是可以通过展示我们的图片来获取referer了,这个时候即使厂商的微博快捷登陆配置没有问题,攻击者也可以通过这个可控图片的链接来获取referer再获取code了。
修复建议如下: