縱觀賬號互通發展史,可以發現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實施過程進行分點回顧,也在整體上反映國內開放平臺的歷史關注度。為簡化責任說明,本文主要有如下角色:平臺方、應用方、用戶。本文可能有錯誤,敬請指正。
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更像是一種框架式指引,這其中主要的特點有:
從業務出發點來講,制定OAuth 2.0協議的最大動力之一,是希望用一個協議適應多個業務場景授權,即需要既能滿足傳統客戶端授權場景,又要滿足無服務器參與的授權場景,甚至還有手機應用授權場景等等等等。
而這種拉大業務場景的結果,一般也意味著薄弱點的增多,這是因為在場景復雜化的情況下,開發方容易考慮不周、或者對應用方的相關安全指示不足,應用方也容易錯誤使用應用場合,而協議對這些場景也沒有更加深入的指引。另外它也可能導致場景之間的安全問題產生了交叉,一些本來屬于潛在威脅,很容易通過場景轉換變成了顯性漏洞。對于擅長“由點到面”的攻擊者來說,現在只需要針對常見薄弱點(尤其是授權認證流程中的薄弱點)就有可能攻擊成功。
OAuth 2.0的rfc定義了幾種場景授權模式,并允許平臺方自行擴充,本文討論的有:
用戶在平臺方授權頁面登錄后,跳轉的redirect_uri中,參數段(如http://cakkback_url/?code=aaaaa&state=ssss)帶code參數;此時應用需要再次向平臺方的指定接口(一般為獲取Access Token接口)發起請求,用code參數換取access token。
這是OAuth 1.0中幾乎唯一定義過的業務場景,主要用于傳統客戶端和有服務器參與的網站授權。
圖:rfc6749 第4.1節Authorization Code Grant流程圖
圖:Authorization Code Grant常見的實現模式:以網站應用為例
用戶在平臺方授權頁面登錄后,跳轉的redirect_uri中,uri片段(如http://cakkback_url/#access_token=aaaaaa&uid=aaaaa)直接帶access token。
這種場景不驗證應用的有效性,主要用于無應用方服務器參與的純瀏覽器javascript/HTML5交互。
圖:rfc6749 第4.2節Implicit Grant流程圖
圖:Implicit Grant常見的實現模式:以無應用服務器的瀏覽器插件為例
應用直接向平臺方的指定接口(一般為專用的XAuth登錄接口;或者為獲取Access Token接口)發起請求,直接用用戶名和密碼獲取Access Token。
圖:rfc6749 第4.3節Resource Owner Password Credentials Grant流程圖
圖:Resource Owner Password Credentials Grant常見的實現模式:以傳統客戶端應用為例
從具體技術實現來講,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】
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等)后,如何將其作為參數匹配到自己應用方的賬號,然后自動登錄(或自動注冊)。針對這個流程常見的攻擊之一是修改授權信息,如果后續的匹配處理邏輯出現紕漏(比如不當參數選擇或無驗證機制),那么就有可能導致任意登錄到任一應用方賬號的嚴重漏洞。
圖:攻擊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)進行來源驗證,從而導致這類漏洞大爆發。
圖:手機開發者引入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防御,則為主要;否則無)
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攻擊,此處不再重復。
圖:針對code參數的Authorization Code Grant攻擊;以及和rfc6749的流程圖關系
應用方要預防這種csrf劫持賬號,加入state參數是比較簡單的通行方法。根據rfc6749 章節10.12,該值既不可預測,又必須可以證明應用(client)和和當前第三方網站的登錄認證狀態存在關聯(如果存在過期時間更好)。一種簡單的方法是:隨機算一個字符串,然后保存在session,回調時檢查state參數和session里面的值。
而平臺方也要在回調時,支持應用方的state參數(當然如果允許redirect_uri參數中帶應用方自己的防csrf參數,其實也可以)。
但嚴格來講,僅有state參數,其實還不夠,還需要結合3.3提到的防御手段。
漏洞頻率:常見
責任方:應用方(主要)、平臺方(主要?次要?)
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保護),那么就可以讓受害者的電腦登錄到攻擊者指定的平臺方賬號。這個的作用是干啥?別急,往下看。
圖:webstersprodigy csrf facebook登錄的poc
(2)stackexchange(應用方)csrf發起綁定請求
回想一下作為一個普通用戶,在應用方(stackexchange)綁定平臺方(facebook)賬號的過程:用戶到stackexchange綁定頁面,提示未綁定facebook,此時當然會點擊“開始綁定”。那么有沒有想過,“開始綁定”這個動作,其實是沒有做csrf保護的?這正是應用方(包括我自己)長期以來忽視的一個問題——在應用點擊發起綁定授權時,并不等于向平臺方發起授權請求啊,它必須要做一些邏輯判斷(包括生成state參數)后才能跳轉到平臺方的授權頁面……
圖:webstersprodigy展示應用方的綁定頁面
因此,結合上面提到的facebook(平臺方)可以csrf登錄,攻擊者首先讓受害者電腦登錄到指定的facebook賬號,然后再csrf stackexchange(應用方)綁定請求,那么就可以達到劫持應用方帳號的目的了。而這兩點成因,和state參數所防御的攻擊場景有一定區別,所以完全可以bypass掉。
圖:webstersprodigy的csrf應用方綁定請求poc
圖: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實現中,則主要體現在應用方賬號綁定和注冊中的代碼邏輯),避免出現重復帳號問題。
經過OAuth 1.0的洗禮,平臺方在安全上有了更多的認識,比如強制限定回調地址(較多是驗證域名部分)以降低redirect_uri跳轉的范圍,強制access token有效期(甚至基本不提供refresh 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進行分析。
漏洞頻率:常見
責任方:平臺方(主要)
wooyun案例:
2013-03-27 WooYun: 開放平臺單點登錄SSO方案設計缺陷導致釣魚風險
其它案例:
@囧虎張建偉,新浪微博Android客戶端SSO授權認證缺陷,2013-09-08:http://www.blogjava.net/zh-weir/archive/2013/09/08/403829.html
漏洞成因和建議修復方案:
圖:新浪微博開放平臺開發文檔移動應用SSO授權
手機應用sso登錄sdk,一般是指應用方使用該sdk后,當用戶點擊授權時,如果如果已經安裝了平臺方的官方手機應用,就會跳到那里,由該官方應用代為授權,免去重新輸入用戶名和密碼。
如果這其中有OAuth參與,就會發現各家的實現方式會有Implicit Grant的影子。在早期,應用在初始化sso sdk的時候,只需要client_id(即應用appkey)和redirect_uri即可發起授權請求。而這兩個參數基本是公開的;即便再加上client_secret,在反編譯/逆向后拿到手也是易如反掌(后面將闡述)。所以攻擊可以進行應用冒充,獲取access token來控制用戶在平臺方的賬號。
平臺方一開始是著重防御授權頁面被偽造和重放攻擊(這也確實要做的),所以官方手機應用彈出的授權頁url是有參數簽名的,但這防御不了惡意使用client_id的問題。后來大家意識到進行手機應用的包名和簽名驗證,才算比較好的解決了這個問題。不過在這里要提醒,如果fallback機制不對(比如沒裝官方客戶端后的授權流程沒做好)、或者簽名對比機制本身就有漏洞,也可能會被繞過......
漏洞頻率:不常見
責任方:平臺方(主要)
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,按照深度整合的流程,一般都會設計成直接在應用方的網站上彈出代理登錄界面;用戶輸入平臺方賬號和密碼后,通過應用方服務器同步登錄到平臺方和應用方賬號。但這種設計流程,很容易在傳輸到應用方網站的過程、乃至在應用方服務器上就泄露了賬號密碼等敏感信息。手機類應用也可類比(參見高德低版本微博登錄流程)。
圖:常見的XAuth威脅
另外一點,由于XAuth的高級授權認證,限制通常會放得比較寬,這會導致常規登錄的保護流程在XAuth接口處失效,那么攻擊者就可以實施撞庫掃號攻擊。
然而完全取消XAuth在業務上也并不現實,因此還必須立足在業務上提出切實的解決方法:
(1)對于外部合作方,最大限度取消且不開放XAuth的授權。對于因為合同原因而導致無法取消的情況,需要加強監控。不得不說,2013 CCTV 315晚會可是幫了各大平臺方一把,使得在談判時,更有底氣說不開放XAuth了。
(2)內部應用一樣要劃分等級,無必要的應用一律禁止使用XAuth和內部接口。對于官方應用也不建議直接使用XAuth,最好走代理接口,原因就在接下來討論的問題:高權限client_id等應用標識泄露。
漏洞頻率:常見
責任方:平臺方(主要)、應用方(次要或主要)
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進行數據挖掘和用戶騷擾。
圖:騰訊開放平臺資料庫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協議的時候共同面臨的問題,故歸到雜項。
漏洞頻率:常見
責任方:平臺方(主要)
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粒度粗細)范圍劃分,這都需要平臺方內部數個(乃至數十個)業務流相關項目組的共同討論和配合執行。這個話題非常大,對架構師的要求較高。
漏洞頻率:常見
責任方:平臺方(主要)、應用方(主要)
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傳遞回來的數據可能并沒有經過過濾,此時仍需要以“輸入不可信”的處理方法進行過濾。
漏洞頻率:常見
責任方:平臺方(主要?次要?)、應用方(主要?次要?)
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下載包中的文檔)”,當然在前期這個舉措,使得淘寶有著較大壓力和遇到碎片化難題(討論見1、2、3)。
除了SDK和開發要求外,平臺方還有一個問題,那就是授權頁面本身如何防止瀏覽器控件和瀏覽器自動記錄功能(無論在手機還是PC)。這個時候,autocomplete=off就要派上用場了。
漏洞頻率:常見
責任方:平臺方(主要?次要?)
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能力大比拼了。
以下錯誤不代表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冒名授權漏洞
該文章的編寫基于各類文獻資料和漏洞案例,在此向所有作者和白帽子致謝。
有一部分OAuth相關的文章并沒納入本文中,如有需要,請點擊此處參閱清單。
作者已經做成pdf供各位方便下載保存:20130914_pdf_pub_OAuth-2.0_security_case_review.pdf