OAuth 2.0安全案例回顧

wyzsk發表於2020-08-19
作者: horseluke · 2013/09/13 15:06

0x00 背景


縱觀賬號互通發展史,可以發現OAuth比起其它協議(如OpenID)更流行的原因是,業務雙方不僅要求賬號本身的認證互通(authentication;可理解為“我在雙方的地盤姓甚名誰”),而是更需要雙方業務流的授權打通(authorization;可理解為“我在雙方的地盤上可做什麼”),因為後者才能產生實際的互惠互利。

2013年將過大半,有關OAuth的討論確有冷卻的趨勢,這源於在商業價值上該協議的使用越來越趨於理性;而OAuth 2.0在國內的實施也已經成熟,“第三方登入”已經規模化。在這個時刻進行安全問題回顧,也許可以為未來類似協議的安全實施做一個參考。在此之前,captain pysolve《淺談OAuth安全(OAuth Security)》(2012年11月)和pnig0s《OAuth Security》(2012年12月),均進行了OAuth歷史和漏洞回顧;而Eran Hammer於2012年7月撰寫的著名文章《OAuth 2.0:通往地獄之路》,則以協議制定參與者的身份,在原理上闡述OAuth 2.0為什麼“在大部分開發者手中會容易出現不安全的實現結果”。本文主要從被攻擊的資源分類角度,結合wooyun等披露案例對OAuth 2.0實施過程進行分點回顧,也在整體上反映國內開放平臺的歷史關注度。為簡化責任說明,本文主要有如下角色:平臺方、應用方、使用者。本文可能有錯誤,敬請指正。

0x01 OAuth 2.0的安全焦點


OAuth 2.0的標準在去年(2012年)10月份總算塵埃落定:RFC 6749 The OAuth 2.0 Authorization Framework(中文翻譯點此https://github.com/jeansfish/RFC6749.zh-cn)和RFC 6750 The OAuth 2.0 Authorization Framework: Bearer Token Usage(中文翻譯點此https://github.com/jeansfish/RFC6749.zh-cn)。相比OAuth 1.0的實踐式總結,OAuth 2.0更像是一種框架式指引,這其中主要的特點有:

(1)儘量適應多個場景授權:場景複雜化下增加了攻擊點

從業務出發點來講,制定OAuth 2.0協議的最大動力之一,是希望用一個協議適應多個業務場景授權,即需要既能滿足傳統客戶端授權場景,又要滿足無伺服器參與的授權場景,甚至還有手機應用授權場景等等等等。

而這種拉大業務場景的結果,一般也意味著薄弱點的增多,這是因為在場景複雜化的情況下,開發方容易考慮不周、或者對應用方的相關安全指示不足,應用方也容易錯誤使用應用場合,而協議對這些場景也沒有更加深入的指引。另外它也可能導致場景之間的安全問題產生了交叉,一些本來屬於潛在威脅,很容易透過場景轉換變成了顯性漏洞。對於擅長“由點到面”的攻擊者來說,現在只需要針對常見薄弱點(尤其是授權認證流程中的薄弱點)就有可能攻擊成功。

OAuth 2.0的rfc定義了幾種場景授權模式,並允許平臺方自行擴充,本文討論的有:

(A)Authorization Code Grant(授權code許可)

使用者在平臺方授權頁面登入後,跳轉的redirect_uri中,引數段(如http://cakkback_url/?code=aaaaa&state=ssss)帶code引數;此時應用需要再次向平臺方的指定介面(一般為獲取Access Token介面)發起請求,用code引數換取access token。

這是OAuth 1.0中幾乎唯一定義過的業務場景,主要用於傳統客戶端和有伺服器參與的網站授權。

2013091312140589672.png
圖:rfc6749 第4.1節Authorization Code Grant流程圖

2013091312152793993.jpg
圖:Authorization Code Grant常見的實現模式:以網站應用為例

(B)Implicit Grant(隱式許可)

使用者在平臺方授權頁面登入後,跳轉的redirect_uri中,uri片段(如http://cakkback_url/#access_token=aaaaaa&uid=aaaaa)直接帶access token。

這種場景不驗證應用的有效性,主要用於無應用方伺服器參與的純瀏覽器javascript/HTML5互動。

2013091312170299688.png
圖:rfc6749 第4.2節Implicit Grant流程圖

2013091312175289681.jpg
圖:Implicit Grant常見的實現模式:以無應用伺服器的瀏覽器外掛為例

(C)Resource Owner Password Credentials Grant(資源所有者密碼憑據許可;XAuth即為此類)

應用直接向平臺方的指定介面(一般為專用的XAuth登入介面;或者為獲取Access Token介面)發起請求,直接用使用者名稱和密碼獲取Access Token。

2013091312190147596.png
圖:rfc6749 第4.3節Resource Owner Password Credentials Grant流程圖

2013091312200841422.jpg

圖:Resource Owner Password Credentials Grant常見的實現模式:以傳統客戶端應用為例

(2)簡化和不作強制要求:落空的開發者保安全願望

從具體技術實現來講,OAuth 2.0為了讓平臺方可以以最小的業務改造代價整合已有資源,對於許多方面並不作強制要求,這其中一個核心精神,就是將應用層簽名流程簡化(甚至去除),並依賴傳輸層加密(TLS)。在業界的實踐中,這種精神被轉化為無繫結token(Unbounded tokens)和無記名token(Bearer tokens) :OAuth 2.0中既不存在Access token secret等簽名專用引數,也放棄以請求引數為基礎生成一個簽名hash值的做法;整個api通訊過程在表面上和瀏覽器訪問https網站很相像,唯一不同的是cookies換成了access token。雖然標準有推薦類似OAuth-HTTP-MAC的簽名流程提案,但在實踐中並不待見。

這種簡化和不作強制要求,提高了平臺方和應用方的安全編碼要求——在沒有協議保障安全下(OAuth 1.0就是靠強制簽名),雙方(尤其是應用方)需要自行實施能夠相互配合的安全方案,才能保障整個OAuth 2.0的使用全過程,均是出於使用者自身意願的授權。但問題是,開發普遍有匱乏安全意識的客觀情況,對“認證”和“授權”之間的區別也難以細究,更遑論平臺方和應用方之間的安全不對等和相互推諉,這就使得靠開發保障安全的美好想法落空。

此處以新浪微博api為例給出兩個協議的區別:

【HTTP, Sina weibo OAuth 1.0a】

GET /users/show/123456.json?oauth_consumer_key=【應用APP KEY】&oauth_nonce=【OAuth隨機值】&oauth_signature=【查詢引數+應用APP SECRET+Access Token Secret三者共同進行簽名後的值】&oauth_signature_method=HMAC-SHA1&oauth_timestamp=【請求時間】&oauth_token=【Access Token】&oauth_version=1.0a HTTP/1.1
Host: api.t.sina.com.cn

【HTTPS, Sina weibo OAuth 2.0】

Host: api.weibo.com
GET /2/users/show.json?uid=123456 HTTP/1.1
Authorization: OAuth2 【Access Token】

0x02 攻陷應用方的賬號體系


OAuth 2.0的安全實施問題,有非常多是落在攻陷應用方的賬號體系上,這是因為應用方的水平參差不齊且不可控,其安全意識更弱,因此攻擊者會挑選最薄弱地帶攻擊。

當授權用於認證時的不當引數選擇或無驗證機制

漏洞頻率:常見

責任方:應用方(主要)、平臺方(無或次要)

wooyun案例:

2012-08-24 WooYun: 淘網址sina oauth認證登入漏洞

2013-01-14 WooYun: 啪啪任意進入他人賬號(OAuth 2.0無繫結token問題)

2013-01-19 WooYun: 金山快盤手機客戶端任意進入他人快盤賬號

漏洞成因和建議修復方案:

無論是OAuth 1.0還是OAuth 2.0,應用場景最多的就是第三方登入(賬號打通),其中關鍵步驟,在於當應用方透過平臺方的Access token獲取介面得到授權資訊(Access Token、uid、expire_time等)後,如何將其作為引數匹配到自己應用方的賬號,然後自動登入(或自動註冊)。針對這個流程常見的攻擊之一是修改授權資訊,如果後續的匹配處理邏輯出現紕漏(比如不當引數選擇或無驗證機制),那麼就有可能導致任意登入到任一應用方賬號的嚴重漏洞。

2013091312253323212.jpg
圖:攻擊Access token資料的薄弱點

在OAuth 1.0還是Authorization Code Grant一統天下的年代,由於主要用於伺服器網站應用,這個問題頂多算是潛在問題,畢竟如果要改授權資訊,只能操作伺服器或者在伺服器所在網站arp——都入侵到那種地步了有啥不可能。不過是世事無絕對,當年已經有開放平臺提前實現了Implicit Grant場景,然後有網站錯誤使用了這種模式,透過javascript獲取裡面的uid/access token,然後再提交給網站直接進行登入;結果由於這些授權資訊可以被攻擊者輕易地截包修改,造成安全問題——淘網址的漏洞,就是這麼來的。

而OAuth 2.0在對待手機、平板之類應用的授權的問題上,一般都傾向於返回access token;然後由應用將access token上報給伺服器,以進行應用自身的賬號認證登入。這種場景的變化導致被篡改的難度大大降低(簡單的驗證方法是使用fiddler2進行截包篡改),但許多手機開發者、乃至手機背後的伺服器api開發者並沒有意識到,結果錯誤選擇了授權資訊作為引數(比如單純選擇uid)、或者沒有對授權資訊(access token)進行來源驗證,從而導致這類漏洞大爆發。

2013091312262655743.jpg
圖:手機開發者引入OAuth 2.0後,常犯的任意登入到應用方賬號嚴重漏洞成因

解決這類漏洞的關鍵點主要靠應用方,但平臺方也必須要參與:

(1)應用方需要認真考慮在整個自動登入/自動註冊的過程中,平臺方返回的授權資訊(尤其是access token和uid)會否被使用者篡改;如果任一個授權資訊都會被篡改,那麼在伺服器中必須再次使用平臺方給出的access token驗證介面,驗證該access token是否為指定來源應用所頒發,同時使用該access token驗證介面給出的uid,而不能使用可能被篡改的原uid值。

如果應用方已經收到該漏洞攻擊的影響,則需要對對所有已存入的繫結access_token進行核查,發現access_token中的平臺方uid和繫結的平臺方uid不一致、非自身客戶端應用appkey授權的access_token、過期access_token等異常情況均需要全部撤消,要求這些異常使用者重新授權登入。

(2)平臺方需要開發access token驗證介面,接收引數為access token等,返回結果應包括頒發的應用來源(一般是appkey)、uid、過期時間等。同時平臺方應針對受影響開發者,釋出安全公告和指引,說明易受攻擊和使用此介面的場景。

針對應用方csrf劫持第三方賬號

漏洞頻率:常見

責任方:應用方(主要)、平臺方(如果沒有配合應用方的csrf防禦,則為主要;否則無)

wooyun案例:

2012-11-10 WooYun: 優酷網存在賬號被劫持風險

2013-01-07 WooYun: 大麥網存在帳號被劫持風險

2013-03-01 WooYun: 美麗說oauth漏洞可劫持賬號

漏洞成因和建議修復方案:

有關應用方csrf劫持的問題,不得不提2012年11月份的一場大討論。那場討論的漏洞場景主要是使用Authorization Code Grant的應用(網站居多),主要的漏洞原因是redirect_uri中的code引數沒有和當前客戶端的狀態繫結,攻擊者可以透過傳送預先獲取好的code引數到受害者電腦,導致導致受害者當前登入的應用方賬號被繫結到攻擊者指定的平臺方(如微博)帳號上。當時我寫了篇文章《小議OAuth 2.0的state引數——從開發角度也說《網際網路最大規模帳號劫持漏洞即將引爆》》,詳細建議用state引數防禦這種csrf攻擊,此處不再重複。

2013091312300733582.jpg
圖:針對code引數的Authorization Code Grant攻擊;以及和rfc6749的流程圖關係

應用方要預防這種csrf劫持賬號,加入state引數是比較簡單的通行方法。根據rfc6749 章節10.12,該值既不可預測,又必須可以證明應用(client)和和當前第三方網站的登入認證狀態存在關聯(如果存在過期時間更好)。一種簡單的方法是:隨機算一個字串,然後儲存在session,回撥時檢查state引數和session裡面的值。

而平臺方也要在回撥時,支援應用方的state引數(當然如果允許redirect_uri引數中帶應用方自己的防csrf引數,其實也可以)。

但嚴格來講,僅有state引數,其實還不夠,還需要結合3.3提到的防禦手段。

更猥瑣的針對應用方csrf劫持第三方賬號:應用方授權動作本身的csrf + 平臺方的登入漏洞…...

漏洞頻率:常見

責任方:應用方(主要)、平臺方(主要?次要?)

wooyun案例:

暫無

其它案例:

webstersprodigy,2012-5-9,Common OAuth issue you can use to take over accounts:

http://webstersprodigy.net/2013/05/09/common-oauth-issue-you-can-use-to-take-over-accounts/

(csrf stackexchange(應用方) + csrf facebook(平臺方) = 繞過state引數 + 將受害者的stackexchange賬號繫結到攻擊著指定的facebook賬號)

漏洞成因和建議修復方案:

加入state引數是否就意味著沒有問題?比如承認,去年我在文章中僅關注僅關注state引數確實很片面,甚至是違反了“安全是一個整體”的原則,人為割裂了整個授權過程的整體分析,掩蓋了其它問題乃至攻擊角度:state引數確能有效保護授權過程中是當前使用者的唯一真實操作,但是發起授權前呢?授權後呢?國外的這個案例給了很好的答案(該案例在zone上有討論):

(1)facebook(平臺方)存在登入漏洞,可以被csrf

如果平臺方可以被xss、或者沒有xss但其登入流程有漏洞可以被csrf(比如登入表單沒有referer保護),那麼就可以讓受害者的電腦登入到攻擊者指定的平臺方賬號。這個的作用是幹啥?別急,往下看。

2013091312342271463.png
圖:webstersprodigy csrf facebook登入的poc

(2)stackexchange(應用方)csrf發起繫結請求

回想一下作為一個普通使用者,在應用方(stackexchange)繫結平臺方(facebook)賬號的過程:使用者到stackexchange繫結頁面,提示未繫結facebook,此時當然會點選“開始繫結”。那麼有沒有想過,“開始繫結”這個動作,其實是沒有做csrf保護的?這正是應用方(包括我自己)長期以來忽視的一個問題——在應用點選發起繫結授權時,並不等於向平臺方發起授權請求啊,它必須要做一些邏輯判斷(包括生成state引數)後才能跳轉到平臺方的授權頁面……

2013091312354673507.png
圖:webstersprodigy展示應用方的繫結頁面

因此,結合上面提到的facebook(平臺方)可以csrf登入,攻擊者首先讓受害者電腦登入到指定的facebook賬號,然後再csrf stackexchange(應用方)繫結請求,那麼就可以達到劫持應用方帳號的目的了。而這兩點成因,和state引數所防禦的攻擊場景有一定區別,所以完全可以bypass掉。

2013091312371472745.png

圖:webstersprodigy的csrf應用方繫結請求poc

2013091312385341559.jpg
圖:webstersprodigy的完整攻擊流程圖

@渥村萬濤 當年的評論,更能說明有關csrf劫持應用方帳號這類問題的本質,只可惜我醒悟得太遲:“其實, 這個漏洞的根本原因, 是違反了RFC6749, 沒有任何CSRF保護, 而不是沒有使用state引數 (state只是實現CSRF保護的一種). 根據RFC6749http://t.cn/zlTZyo6state是推薦(SHOULD), 而不是必須(MUST). 但CSRF保護是MUST. 沒有用state, 不違反標準, 但沒有CSRF保護, 則違反”(發表於2012-11-10 12:50)

而返回到這個漏洞,“安全是一個整體”再一次體現——只有平臺方和應用方的共同努力,才可能修補完全。不過各位都懂的,對於這種有多個責任方問題的漏洞,這幾乎不可能…...

針對平臺方的建議:

(1)檢查所有登入頁面和登入流程,防止出現登入漏洞。

比如在存在登入入口的頁面(尤其是在具有sso登入功能的頁面上)上,強制進行referer和一次性token驗證,以防止被csrf登入。

又比如檢查所有登入相關的流程,防止出現漏洞。以下是一些例子:

2013-02-19 WooYun: 豬八戒網不用賬號密碼登入任意賬號

2013-03-18 WooYun: 飯統網登入任意賬戶漏洞

(2)檢測會否能夠對帳號異地登入有反應並採取措施。

不過如果出現定向攻擊,這似乎沒啥用。

針對應用方的建議:

(1)做好發起繫結平臺方賬號(新浪微博、QQ空間、人人網等等)、解除繫結等等等等諸如此類的繫結相關動作的csrf防護。這是整個開發界一直以來忽視的點。

(2)在繫結頁面顯示繫結的平臺方暱稱、uid等資訊等,防止使用者無法自查繫結資訊。

(3)繫結和解綁時,通知使用者。

賬號體系的固有邏輯缺陷利用

漏洞頻率:少見

責任方:應用方(主要)

wooyun案例:

2012-03-14 WooYun: 5sing.com藉助第三方連線可建立重複暱稱賬戶

漏洞成因和建議修復方案:

實際上這類漏洞和OAuth協議(或者說任何一個賬號互通登入協議)沒有關聯,純粹是應用方設計的帳號體系邏輯存在問題。將其放在這裡主要是希望提醒應用方開發者,仔細審查賬號設計體系和實現方式,在使用平臺方的賬號互通時要留意對方帳號體系的不同點(在OAuth實現中,則主要體現在應用方賬號繫結和註冊中的程式碼邏輯),避免出現重複帳號問題。

0x03 攻擊平臺方的賬號和資源體系


經過OAuth 1.0的洗禮,平臺方在安全上有了更多的認識,比如強制限定回撥地址(較多是驗證域名部分)以降低redirect_uri跳轉的範圍,強制access token有效期(甚至基本不提供refresh token之類的東西)以限制應用方的長時間資源佔用和濫用等。但業務場景的多樣化,使得攻擊者遊走在場景之間以點撕面;而平臺方則受制於防禦成本處處受困(無論是來自自身還是來自應用方)。

Implicit Grant場景的無奈(response_type=token)

漏洞頻率:常見

責任方:應用方(主要或次要)、平臺方(主要或次要)

wooyun案例:

2012-04-15 WooYun: 人人網Oauth 2.0授權可導致使用者access_token洩露

2012-08-27 WooYun: 透過[新浪微博]官方來源呼叫API發表微博.無需client_sec

2012-09-20 WooYun: 無需client_sec可用QQ登入平臺發表空間日誌等高許可權操作(WooYun-2012-11314衍生)

2012-09-25 WooYun: QQ互聯開放平臺QQ登陸oauth授權介面可以劫持access_token

2012-09-25 WooYun: 百度開放平臺oauth授權介面可以劫持access_token

其它案例:

Egor Homakov,How we hacked Facebook with OAuth2 and Chrome bugs,2013-2-19:
http://homakov.blogspot.com/2013/02/hacking-facebook-with-oauth2-and-chrome.html

(利用OAuth 2.0 Implicit Grant特性 + Chrome bug獲取facebook的access token)

漏洞成因和建議修復方案:

有關Implicit Grant場景的討論,可見2012年9月撰寫的zone文章《從wooyun-2012-11314小議OAuth 2.0認證缺陷》。此處將一些關鍵點拿出來再討論。

Implicit Grant場景的特點是授權驗證時只需要client_id和redirect_uri這兩個引數作應用標識,返回的時候也就直接在uri片段中返回access token。這個場景的提出,和客戶端(client-side)業務需求有著密不可分的關聯,典型例子就是無伺服器參與的純javascript互動的瀏覽器外掛、各種網站掛件。在這種業務下,客戶端難以保密雙secret(app secret,access token secret)也難以加密,因此乾脆將這些限制均進行簡化。

但Implicit Grant場景也在安全問題上深深地困擾著平臺方:

(1)由於缺失了雙secret的簽名,api僅憑access token基本難以分辨應用請求來源

(2)絕大多數開放平臺透過Implicit Grant方式認證獲取的client-side access token,可用於伺服器的api通訊中(即許可權等同於走Authorization Code Grant方式獲取到的server-side access token)

(3)各開放平臺由於要實施諸如網站掛件之類的應用,經常會對自己開放平臺的中轉頁面或者跨域檔案大開綠燈。也就是說redirect_uri會放行兩類域名:應用方自己的域名、平臺方自己指定的中轉域名。

(4)client_id(即應用appkey)和redirect_uri基本屬於公開資訊。

以上困擾造就一種最常見且棘手的網站安全問題,那就是隻要合作方網站(最常見)、平臺方網站甚至是瀏覽器三者之一有任何一個xss,攻擊者無需知道app secret,就很容易xss獲取到access token,然後以此攻擊受害者的平臺方賬號。

另一種困擾則是“當授權用於認證時的不當引數選擇或無驗證機制”所闡述的,既然api分辨不了應用請求來源,那麼只要掌握了A應用中受害者的access token,並且在B應用中的某些關鍵請求步驟中替換掉,那麼就有可能順利登入到B應用的受害者應用方賬號。 

第三種則是應用冒充,攻擊者只使上述公開引數用就能冒充成其它應用調出授權頁面,獲取到的access token可以用於控制受害者的平臺方賬號。如果是高許可權client_id,獲取到的access token顯然更有破壞力。

解決這個問題,rfc6749第10.16小節就只是語焉不詳的說需要額外的安全措施,這也反映了這種場景的防禦難處。從實踐來看,有一種方法是必須的:平臺方必須對應用方的應用強制進行分類——即應用方在申請client_id(即應用appkey)時,需要選擇屬於哪類應用;平臺方再根據分類開放對應許可權,並且進行特定的防禦和監控措施,以下以手機sso登入sdk進行分析。

Implicit Grant場景的無奈手機版:手機SSO登入SDK

漏洞頻率:常見

責任方:平臺方(主要)

wooyun案例:

2013-03-27 WooYun: 開放平臺單點登入SSO方案設計缺陷導致釣魚風險

其它案例:

@囧虎張建偉,新浪微博Android客戶端SSO授權認證缺陷,2013-09-08:http://www.blogjava.net/zh-weir/archive/2013/09/08/403829.html

漏洞成因和建議修復方案:

2013091312452447715.png
圖:新浪微博開放平臺開發文件移動應用SSO授權

手機應用sso登入sdk,一般是指應用方使用該sdk後,當使用者點選授權時,如果如果已經安裝了平臺方的官方手機應用,就會跳到那裡,由該官方應用代為授權,免去重新輸入使用者名稱和密碼。

如果這其中有OAuth參與,就會發現各家的實現方式會有Implicit Grant的影子。在早期,應用在初始化sso sdk的時候,只需要client_id(即應用appkey)和redirect_uri即可發起授權請求。而這兩個引數基本是公開的;即便再加上client_secret,在反編譯/逆向後拿到手也是易如反掌(後面將闡述)。所以攻擊可以進行應用冒充,獲取access token來控制使用者在平臺方的賬號。

平臺方一開始是著重防禦授權頁面被偽造和重放攻擊(這也確實要做的),所以官方手機應用彈出的授權頁url是有引數簽名的,但這防禦不了惡意使用client_id的問題。後來大家意識到進行手機應用的包名和簽名驗證,才算比較好的解決了這個問題。不過在這裡要提醒,如果fallback機制不對(比如沒裝官方客戶端後的授權流程沒做好)、或者簽名對比機制本身就有漏洞,也可能會被繞過......

較大爭議的Xauth場景(Resource Owner Password Credentials Grant;grant_type=password)

漏洞頻率:不常見

責任方:平臺方(主要)

wooyun案例:

2012-11-05 WooYun: 開心網android客戶端暴力破解漏洞,測試2000帳號,成功132個

其它案例:

2013-03-15,CCTV 2013年315晚會中“指控”高德地圖低版本“收集新浪微博使用者名稱和密碼”(後高德發表宣告否認):http://jingji.cntv.cn/2013/03/15/ARTI1363354929366253.shtml

漏洞成因和建議修復方案:

這是一個存在較大爭議的場景:在談判桌上,這是體現應用方公司和平臺方公司之間的實力角逐;在開發界裡,這是提升使用者體驗和轉化率的利好方法;在安全界中,卻是有著偷竊隱私和危害使用者的後門行為。這個引起開發界和安全界爭論不休的東西,叫做XAuth,叫做Resource Owner Password Credentials Grant,又或者,叫做直接用平臺方使用者名稱和密碼獲取access token。

XAuth常見的目標業務有這兩種:(1)內部或自身官方應用的服務呼叫;(2)應用方的高階合作和深度整合。可以說,XAuth代表著的高階授權認證,是平臺方對應用方最大的信任和合作。

但畢竟XAuth是由應用方代為提交使用者名稱和密碼到介面,而繞過了平臺方本身的授權認證頁面,因此從安全來說,在無法確保應用方能力信譽和安全狀況的情況下,難以保證使用者名稱和密碼不會被洩露。比如如果是網站類應用允許使用XAuth,按照深度整合的流程,一般都會設計成直接在應用方的網站上彈出代理登入介面;使用者輸入平臺方賬號和密碼後,透過應用方伺服器同步登入到平臺方和應用方賬號。但這種設計流程,很容易在傳輸到應用方網站的過程、乃至在應用方伺服器上就洩露了賬號密碼等敏感資訊。手機類應用也可類比(參見高德低版本微博登入流程)。

2013091312480448767.png
圖:常見的XAuth威脅

另外一點,由於XAuth的高階授權認證,限制通常會放得比較寬,這會導致常規登入的保護流程在XAuth介面處失效,那麼攻擊者就可以實施撞庫掃號攻擊。

然而完全取消XAuth在業務上也並不現實,因此還必須立足在業務上提出切實的解決方法:

(1)對於外部合作方,最大限度取消且不開放XAuth的授權。對於因為合同原因而導致無法取消的情況,需要加強監控。不得不說,2013 CCTV 315晚會可是幫了各大平臺方一把,使得在談判時,更有底氣說不開放XAuth了。

(2)內部應用一樣要劃分等級,無必要的應用一律禁止使用XAuth和內部介面。對於官方應用也不建議直接使用XAuth,最好走代理介面,原因就在接下來討論的問題:高許可權client_id等應用標識洩露。

堵不住的高許可權client_id(appkey)和client_secret(app secret)洩露

漏洞頻率:常見

責任方:平臺方(主要)、應用方(次要或主要)

wooyun案例:

2011-06-01 WooYun: 金山毒霸微服務Oauth key洩露問題

2011-12-02 WooYun: 新浪微博可能導致使用者資訊洩露的BUG

其它案例:

2013-03-08,John Leyden,Leaked: The 'secret OAuth app keys' to Twitter's VIP lounge:http://www.theregister.co.uk/2013/03/08/twitter_oauth_leaked_keys/

2013-4-10,Nicolas Seriot(HITBSECCONF2013 - AMSTERDAM),busing Twitters API and OAuth Implementation :http://conference.hitb.org/hitbsecconf2013ams/materials/D1T2%20-%20Nicolas%20Seriot%20-%20Abusing%20Twitters%20API%20and%20OAuth%20Implementation.pdf

(主要講述反編譯/逆向twitter官方應用獲取appkey和app secret(即client_id和client_secret),然後假冒官方應用使用;最後認為將OAuth應用在傳統客戶端在根本上是錯誤的)

漏洞成因和建議修復方案:

導致高許可權client_id和client_secret洩露的原因有許多種,比如:

(1)官方或者高階合作伙伴的客戶端反編譯/逆向。這是許多有關OAuth可否使用在客戶端(無論是傳統桌面客戶端還是手機客戶端等)的討論焦點之一。

(2)應用方原始碼洩露client_id和client_secret。

由於Implicit Grant場景只需要client_id和redirect_uri就可以造成破壞,因此僅洩露高許可權client_id的原因也需要考慮在內:

(1)代理介面錯誤設計。有些OAuth代理介面設計成傳遞client_id使用,結果被截獲。

(2)高階應用方(高階合作伙伴)使用了開放平臺掛件等。

洩露通常會帶來資源濫用的後果,常見的有:

(1)應用冒充:比如替換client_id和client_secret,將android手機應用裝成iphone客戶端,官方還不能封鎖,因為這個client_id代表官方應用,封了等於斷自己生意;又比如在Implicit Grant場景下,只使用client_id就能冒充成其它應用,從而控制受害者的平臺方賬號,此部分前面已經闡述。

(2)非合作資料探勘:比如爬資料,又比如自動批次私信騷擾等。

(3)非正常的高階介面呼叫。

緩解client_id的洩露以及所帶來的資源濫用,以下解決方法可以參考:

(1)應用方正確設計一組代理介面,在不洩露client_id和client_secret的情況下對OAuth進行一層包裝。

例子為新浪微博手機客戶端,它在後續的版本就不走OAuth流程,而是改為訪問代理介面,該代理介面的使用過程中也不會傳遞client_id和client_secret。改造後,既解決了client_id和client_secret洩漏問題,又可以更好地調整手機型號的判斷。

(2)平臺方從協議入手阻斷批次呼叫不同client_id。

例子為騰訊開放平臺。由於使用者關係是QQ的核心,所以騰訊為反關係資料探勘,對OAuth標準進行了一些改動,每個client_id獲取的使用者openid(使用者QQ號碼轉化得到的ID)均不一樣,這樣,就能夠防止攻擊者批次呼叫不同client_id進行資料探勘和使用者騷擾。

2013091312511474841.png

圖:騰訊開放平臺資料庫OpenAPI呼叫相關問題

不過要在這裡說明的是,實際上無論是學術研究、商業資料探勘還是垃圾資訊傳送者,其實他們根本就不會乖乖走OAuth,畢竟要濫用資源辦法實在是太多了,眾包爬頁面客戶端插入都是方法。因此對平臺方來講,討論OAuth會否導致資源濫用可能並不重要,重要的是討論使用OAuth後能否遏制其它方面的資源濫用——畢竟OAuth訂立了一種和外界商業合作的態度和框架,那麼平臺方就可以據此遏制這個框架外的未授權資源濫用。貌似和安全無關,扯遠了…...

(3)平臺方完善介面許可權控制和行為監測,發現異常進行處理和報警。

沒有考慮全面的協議實現

漏洞頻率:不常見

責任方:平臺方(主要)

wooyun案例:

2012-10-30 WooYun: 騰訊微博開放平臺openid、openkey擷取

2013-04-11 WooYun: 搜狐微博OAuth2.0獲取Authorization Code過程隱患

漏洞成因和建議修復方案:

這一塊主要是因為對場景考慮不周導致的OAuth 2.0協議實施不全面。由於本人沒有做過平臺開發,因此除了建議考慮場景之外,無法給出更具體的分析和建議了。

其它雜項

以下內容並非是OAuth協議獨有(甚至和OAuth無關),它只是反映了當前在實現api協議的時候共同面臨的問題,故歸到雜項。

api介面和主業務流的失調

漏洞頻率:常見

責任方:平臺方(主要)

wooyun案例:

(與主業務流脫節)

2012-11-24 WooYun: 繞過騰訊微博運營限制繼續發微博

(與主業務流錯誤整合混用)

2012-03-06 WooYun: 新浪微博開放平臺介面惡意利用漏洞可導致病毒傳播

2012-07-20 WooYun: 新浪微博加關注CSRF漏洞(已經氾濫)

2012-11-10 WooYun: 新浪微博安全漏洞,導致微博帳號被輕易盜用

2013-04-02 WooYun: 豆瓣API 2.0介面CSRF

漏洞成因和建議修復方案:

業務流失調問題並不是OAuth協議獨有,所有存在多套業務流(尤其是不同入口均可完成同一任務)的軟體開發都容易出現這類bug(進一步就是漏洞),它反映的是業務劃分沒有定式的難題。上面的案例就反映出api介面和主業務流(一般用在平臺方主站點)之間有著太多選擇問題:

一方面,api介面希望保持邏輯獨立性,以方便全平臺擴充套件;但如果api滯後於主業務流,那麼就會出現脫節現象。比如由於開發計劃滯後,暫時只在主站限制了實名發微博,但api還沒上這個策略,那麼攻擊者就可以直接用api繞過這個限制。

另一方面,主業務流也希望將自身整合到api介面中,以確保全平臺策略一致性;但如果本著“不重複造輪子”,錯誤整合混用的話,那麼就會出現干擾問題。比如主站可以用登入cookies當作access token直接呼叫api介面,這就容易實施各種csrf攻擊。

解決業務流失調的關鍵還是在於業務範圍大小範圍劃分以及服務粒度粗細(還有api粒度粗細)範圍劃分,這都需要平臺方內部數個(乃至數十個)業務流相關專案組的共同討論和配合執行。這個話題非常大,對架構師的要求較高。

攻擊api介面或者配套系統(傳統web安全問題)

漏洞頻率:常見

責任方:平臺方(主要)、應用方(主要)

wooyun案例:

(平臺方api介面問題)

2012-10-08 WooYun: 網易 Oauth 身份驗證機制存在 XSS

(平臺方api介面 + 平臺方sdk或應用方輸出過濾問題)

2012-06-05 WooYun: ”用qq登陸“api介面xss

(平臺方api配套系統問題)

2010-11-08 WooYun: 人人網某頻道XXS漏洞

2012-07-08 WooYun: 騰訊開放平臺儲存型xss漏洞

2013-04-28 WooYun: 優酷開放平臺 儲存型XSS指令碼攻擊漏洞 成功劫持後臺

漏洞成因和建議修復方案:

由於OAuth本質上是http服務,故無論是api介面本身還是配套系統也會有諸如xss(經常出現在各種jssdk和網站掛件中)、csrf、sql注射、甚至ddos等等的安全威脅。其根源和解決(緩解)方法與傳統web安全在部分課題上基本一致,但也有一部分也存在差異,見雲舒有關cc攻擊的研究PPT

在這裡要特別提醒應用方和做官方SDK的平臺方開發人員,api傳遞回來的資料可能並沒有經過過濾,此時仍需要以“輸入不可信”的處理方法進行過濾。

不能釋懷的瀏覽器控制元件(如WebView)

漏洞頻率:常見

責任方:平臺方(主要?次要?)、應用方(主要?次要?)

wooyun案例:

2013-03-18 WooYun: 微信存非法記錄其他網站賬號密碼行為

(注意:該案例僅是webview自帶的自動記錄功能,claudxiao進行了分析和說明: http://blog.claudxiao.net/2013/03/android-webview-cache/

其它案例:

淘寶開放平臺,無線開放平臺開發要求“無線類應用授權必須走瀏覽器模式而非webview模式”,2013-9-12訪問和驗證:http://open.taobao.com/doc/detail.htm?spm=0.0.0.0.L44DxW&id=972

漏洞成因和建議修復方案:

手機開發中,瀏覽器控制元件一般用於在應用內嵌入網頁,以進行應用和網站之間的html5混合互動和提升使用者體驗。android和ios上一般指基於webkit引擎的WebView元件Windows Phone則有基於IE的WebBrowser控制元件(以下內容未對WP實證)。

有一些使用者無法信任應用使用瀏覽器控制元件開啟OAuth授權認證登入頁面,其主要原因有:

(1)無法看到開啟的url,容易被釣魚

(2)瀏覽器控制元件可被注入應用的惡意js程式碼,導致賬號被洩露等。

當然,最近大熱的WebView介面編碼不當導致任意程式碼執行也不是不可能存在,不過從該問題的歷史討論來講,這個並不是主要擔憂原因。

要讓使用者信任瀏覽器控制元件內的應用授權頁面,當前主要實踐模式都是平臺方開發互動性更加便捷的官方手機應用SDK(比如手機SSO SDK等),並在提交應用審查時要求使用官方SDK或者遵守相關開發要求。目前在國內最嚴格的是淘寶開放平臺,在無線開放平臺開發要求明確要求“無線類應用授權必須走瀏覽器模式而非webview模式(具體實現可以參看兩種無線sdk下載包中的文件)”,當然在前期這個舉措,使得淘寶有著較大壓力和遇到碎片化難題(討論見123)。

除了SDK和開發要求外,平臺方還有一個問題,那就是授權頁面本身如何防止瀏覽器控制元件和瀏覽器自動記錄功能(無論在手機還是PC)。這個時候,autocomplete=off就要派上用場了

來自https的煩惱

漏洞頻率:常見

責任方:平臺方(主要?次要?)

wooyun案例:

其它案例:

《Why Eve and Mallory Love Android: An Analysis of Android SSL (In)Security》中文簡翻(附原文):http://zone.wooyun.org/content/1396

漏洞成因和建議修復方案:

由於https比tls更加眾所周知,所以此處用https這個詞了。OAuth 2.0將安全性基本押寶在傳輸層加密上,所以https的安全問題也會影響到OAuth 2.0(或者其它協議)安全,但具體分析這個問題也是煩惱不斷。

一方面,https在網路不穩定的情況下容易出現超時。在2012年[email protected] 給了一個血淚教訓:“在手機上使用 https 協議要慎重。在北上廣深以外的中國廣大城市,有 20%~25% 的使用者都會遇到 https 連線困難。排查發現問題和接入點無關,訊號和網路不穩定導致 https 請求很難完成。”。

另一方面,即使使用了https,由於絕大部分應用的程式碼不會去檢查證照,這就導致一旦遇到arp和中間人攻擊,基本game over。

所以在這個問題上各平臺方和應用方的解決平衡之道可謂是五花八門(比如其中一種是讓重要介面和流程走https,而其它還是走回類似OAuth 1.0形式的http+請求引數簽名),雖然從理論上,讓任何OAuth 2.0流程都不走https的方法,都有違反協議所訂立的安全前提嫌疑。

而對於一些重要介面的應用開發,在使用https的時候還是建議開啟檢查證照的程式碼(最好進行證照鎖定),不過帶來的問題是不好除錯,此時就是各開發者進行debug log能力大比拼了。

0x04 附錄:那些在OAuth 1.0年代的安全案例

以下錯誤不代表OAuth 2.0沒有,只是說大家吸取教訓,已經開始少見。

(1)平臺方授權頁面的csrf

2012-02-15 WooYun: CSRF導致微博應用自動授權

2012-07-20 WooYun: 第三方APP強制新浪使用者OAUTH授權漏洞

2012-12-03 WooYun: 網易開放平臺第三方應用oauth強制使用者授權漏洞

(2)OAuth 1.0 session fixation

攻擊根源:回撥url引數oauth_callback可被攻擊者控制,導致任意跳轉。

攻擊過程:

(A)攻擊者從應用方預先獲取帶REQUEST TOKEN引數的授權認證頁面url,但並不跳轉,而是記錄下原來的oauth_callback引數,並將其替換成攻擊者的url。

(B)受害者訪問該惡意構造的授權認證頁面url後,使用自己的平臺方賬號進行授權。完畢後平臺方根據oauth_callback,連同REQUEST TOKEN等引數,指示受害者瀏覽器跳轉到攻擊者的url。

(C)攻擊者打時間差,搶先訪問原來的oauth_callback引數,至此成功登入到受害者的應用方賬號上。整個過程不需要知道APP SECRET和REQUEST TOKEN SECRET,也可以bypass應用方的csrf防禦。

防禦方法:

後續規範OAuth1.0a和RFC 5849中,明確規定oauth_callback引數需要加入生成REQUEST TOKEN的簽名中;並且平臺方在返回回撥url時,帶上不可預測的oauth_verifier引數。相關詳細資料請參考:http://sakinijino.com/archives/1208

和OAuth 2.0的比較:

由於OAuth 2.0沒有簽名,故平臺方的開放平臺應用管理介面上,有“繫結域名”或者“回撥url”設定選項,不符合這些設定的會在授權頁面上報錯(比如invalid_redirect_uri);oauth_verifier引數則被code引數取代。

案例:

2010-11-03 WooYun: Sina 微博OAuth 提供者存在session fixation attack漏洞

2011-02-18 WooYun: 新浪微博應用URL跳轉

2011-04-29 WooYun: 街旁網第三方登入劫持漏洞

2013-07-01 WooYun: 圖蟲網第三方認證缺陷導致可以劫持帳號

2013-07-23 WooYun: 團800oauth缺陷可能導使用者帳號被劫持

(3)沒有考慮全面的協議實現之OAuth 1.0版

2012-12-02 WooYun: 139郵箱OAuth 1.0標準協議設計缺陷

2012-12-04 WooYun: 天涯開放平臺第三方應用oauth冒名授權漏洞

0x05 附錄:致謝和部分參考文章列表


該文章的編寫基於各類文獻資料和漏洞案例,在此向所有作者和白帽子致謝。

有一部分OAuth相關的文章並沒納入本文中,如有需要,請點選此處參閱清單。

作者已經做成pdf供各位方便下載儲存:20130914_pdf_pub_OAuth-2.0_security_case_review.pdf

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

相關文章