关于第三方登陆我们还能做些什么
2020-03-16 10:56:27 Author: xz.aliyun.com(查看原文) 阅读量:172 收藏

1、跳转时使用js造成的xss攻击

   先说一下结果,几个月前,在部分有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>

修复:

  1. 若输出点在script标签中,注意转义\、/、'、"符号
  2. 若输出点在属性中,注意伪协议的利用
  3. 如输出点在标签中,可进行html实体转义
  4. 如果无需跨域,可使用302跳转(要注意CRLF)

2、微博快捷登陆域名配置错误的攻击

其实这一段并不是什么新的攻击手法了,早在很久之前就已经出现了这种攻击手法,并且引起了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

修复:

  1. 在微博开发者中心严格设定跳转域

3、绑定接管的攻击

这类问题存在于更多的厂商中,但是危害并不是很大,有较大的局限性。

以aaa.com的微博(QQ、微信都可)快捷登陆方式为例,使用一个从未绑定过aaa.com的微博账号登陆成功之后,跳转到:
https://passport.aaa.com/account/sina?code=0e563372a36017

因为是首次登陆的第三方帐号,所以要求用户绑定本站aaa.com账号。
但是,此绑定链接再发给任何一个人都可以正常打开,整个页面没有瞩目的提醒是在绑定,看起来就像是一个登陆页面一样,这很容易被普通用户认为是正常登陆,用户输入账号登陆之后就导致了帐号被攻击者接管。但是因为一个第三方帐号只能绑定一个帐号,所以就有很大的局限性了。

测试中发现,有很多的厂商做了如下的防护,但是每一种都有方法绕过。:

  1. 在绑定页面加强提醒,并且给出第三方帐号的昵称、头像
  2. 携带code的认证链接仅能使用一次,访问一次之后code即失效
  3. 携带code的回调登陆链接需要验证referer是否为可信的且不能为空

对于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了。

修复建议如下:

  1. 在跳转至第三方登陆的时候,set-cookie一个third=value(随机值),第三方登陆成功之后回调链接参数中需要含有这个字段third=value,与cookie中的third对比验证,如果一致则通行。
  2. 甚至如果没有太多必要的话,首次快捷登陆的账号不进行账号绑定,由用户自行在个人中心绑定合并资料。

文章来源: http://xz.aliyun.com/t/7360
如有侵权请联系:admin#unsafe.sh