Android框架层漏洞-Fragment注入

来源:互联网 发布:hive sql 平台 编辑:程序博客网 时间:2024/04/28 19:55

http://seclists.org/fulldisclosure/2013/Dec/55
http://blog.csdn.net/l173864930/article/details/17279165
http://securityintelligence.com/new-vulnerability-android-framework-fragment-injection/#.VHxDvOF_W5l
wyciwyg://0/http://www.2cto.com/Article/201401/270936.html


Android框架层漏洞-Fragment注入

http://bbs.pediy.com/showthread.php?p=1254113



标 题:已解答: 【翻译】Android框架层漏洞-Fragment注入
作 者: 往来一气
时 间: 2014-01-05,21:35:46
链 接: http://bbs.pediy.com/showthread.php?t=183459

原文:A New Vulnerability in the Android Framework: Fragment Injection
出处:http://securityintelligence.com/new-vulnerability-android-framework-fragment-injection/#comments
作者:Roee Hay,IBM Application Security Research Team
时间:2013.12.10


    最近我们给Android安全团队揭露了一个新的漏洞,该漏洞影响了许多应用程序,包括 设置(所有Android设备上的Settings),Gmail,Google Now,DropBox和Evernote。更准确的说,任何应用扩展PreferenceActivity类时使用 exported activity都是危险的。现在Android 4.4 KitKat已经提供了补丁.如果你想知道为什么你的代码出现问题,可以参考Android KitKat补丁中需要应用更换的新方法PreferenceActivity.isValidFragment,该方法现已添加到了Android框架.

    在这篇文章中,我们先开始简短介绍Android和沙箱相关知识,然后再深入到漏洞本身。为了简单起见,我们省略了一些细节,详细可以观看白皮书。


一,Android应用程序的UI构建块

    Android应用的UI由activities组成。一个activity提供了一个单一的屏幕和一些功能(例如:浏览器的书签管理器)。一个Fragment  可以被认为是sub-activity,这是应用程序UI的一个小部分。Fragments能够灵活的允许在不同的activities重用。当一个Fragment实例在Activity里面驻留耦合时,不同实例可以嵌入到不同的Activity中。图1即Activity和Fragment的关系。

名称:  365.png查看次数: 1文件大小:  12.8 KB

图1:Fragment和activity的关系

二,Android沙盒,权限,Inter-app通信和恶意程序攻击

    Android系统中,应用程序是相互孤立并且受制于他们声明的权限运行于沙盒中。通常应用是不能正常访问其他程序的敏感数据。但也就是说,通过其他方式应用还是可以调用其他应用组件(如 activities)特征重用。例如,谷歌Chrome浏览器调用Google play应用打开Google play URLs。这个调用使用 Intents即IPC对象从源应用程序传递到相应的API。 Intents不只是指定目标,他们在其他两个地方也包含了数据。第一个位置是data属性(URI类型),第二个是一个字典(Bundle)可以包含任意数量的信息(也称为Intent extras)。如果Activities在应用程序的manifest文件(ApplicationManifest.xml)中声明exported,则其可以被外部应用调用,即此形成了一个activity公开(exported)创建的Android沙箱潜在突破口。当Activities访问输入Intent的数据时,一个恶意的应用可以调用exported的activity并为其提供恶意数据,如果数据不正确santizied(santizied不理解)或未经目标应用的验证,则可能会触发漏洞。而Fragment可以接收通过访问嵌入activity的输入,即Intent或Fragment-specific参数。图2为攻击大概。

名称:  366.png查看次数: 1文件大小:  12.4 KB

图2:攻击exported activities.

三,PreferenceActivity

    PreferenceActivity是Android框架提供的基类,用来显示用户偏好的层次结构,偏好与PreferenceFragment相关联。PreferenceActivity占用少量Intent extras,其中一个是:android:show_fragment,用来告诉PreferenceActivity要先显示哪些fragment。动态Fragment的加载是通过开始于创建activity、结束在Fragment.instantiate的调用链实现的(见图3、4),随之加载使用Java Reflection API的Fragment。
代码:
Java@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);    String initialFragment = getIntent().getStringExtra(EXTRA_SHOW_FRAGMENT);   Bundle initialArguments = getIntent().getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS);    if (savedInstanceState != null) {    } else {       if (initialFragment != null && mSinglePane) {           // If we are just showing a fragment, we want to run in           // new fragment mode, but don't need to compute and show           // the headers.           switchToHeader(initialFragment, initialArguments);         } else {            if (mHeaders.size() > 0) {               if (!mSinglePane) {                   if (initialFragment == null) {                    } else {                      switchToHeader(initialFragment, initialArguments);                   }               }           }       }   }     } public void switchToHeader(String fragmentName, Bundle args) {   setSelectedHeader(null);   switchToHeaderInner(fragmentName, args, 0);} private void switchToHeaderInner(String fragmentName, Bundle args, int direction) {   getFragmentManager().popBackStack(BACK_STACK_PREFS,                                     FragmentManager.POP_BACK_STACK_INCLUSIVE);   Fragment f = Fragment.instantiate(this, fragmentName, args);   FragmentTransaction transaction = getFragmentManager().beginTransaction();   transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);   transaction.replace(com.android.internal.R.id.prefs, f);   transaction.commitAllowingStateLoss();}
图3:PreferenceActivity中结束于Fragment.instantiate的 调用链(Android 4.3中实现)

代码:
Figure 4: Fragment.instantiateJavapublic static Fragment instantiate(Context context, String fname, Bundle args) {    try {        Class<?> clazz = sClassMap.get(fname);        if (clazz == null) {            // Class not found in the cache, see if it's real, and try to add it            clazz = context.getClassLoader().loadClass(fname);            sClassMap.put(fname, clazz);        }        Fragment f = (Fragment)clazz.newInstance();        if (args != null) {            args.setClassLoader(f.getClass().getClassLoader());            f.mArguments = args;        }        return f;    }...}
图4:Android 4.3 Fragment.instantiate的实例

四,漏洞

    恶意应用程序可以调用任何exported的PreferenceActivity类,并提供:android:show_fragment Intent extra来执行加载任意类。攻击者的目标是执行一些代码来打破Android沙箱,来访问脆弱应用敏感信息,或滥用权限。由于攻击者不能提供自己的类,他只是有限的寻找脆弱应用的类加载器(Android框架类和应用程序类),而攻击并不简单。在我们的白皮书中描述了几个exploit技巧,其中一个相当酷。恶意应用可以使PreferenceActivity加载脆弱应用的任意Fragment ,这通常是装载在一个non-exported的Activity中的,几乎相当于把它从安居所放入了危险区,从而被不信任的恶意应用控制。参见图5的攻击大纲。

名称:  367.png查看次数: 1文件大小:  18.8 KB
图5:攻击 Fragment

五,攻击Android Settings

    正如我们上面所提到的,所有的应用用到PreferenceActivity都是脆弱的。我们针对Settings应用,因为它是一个高度特权应用,通过exploiting漏洞我们设法成功地破坏其完整性。应用程序的主activity( 已exported)com.android.settings.Settings由于扩展PreferenceActivity而变得脆弱。我们在应用包中寻找到有意思的fragments,其中一个是ChooseLockPassword$ChooseLockPasswordFragment,这个 Fragment是负责处理验证设备锁屏和设备管理策略信息的改变,Fragment所在的ChooseLockPassword Activity是non-exported的,通常Fragment先要求用户输入他的旧凭证(参见图6),除非嵌入的activity配置了一个名为“confirm_credentials” 的Intent extra,并设置为false。

名称:  368.png查看次数: 1文件大小:  6.8 KB
图6:ChooseLockPasswordFragment的默认行为

    由于activity是未exported的,该参数不容易被恶意应用操作,然而利用Fragments注入漏洞,我们可以把ChooseLockPassword$ChooseLockPasswordFragment嵌入exported 的activity,com.android.settings.Settings中,并提供恶意数据,confirm_credentials设置为false。攻击轮廓如图7所示,图8为结果。由于这种exploit需要用户介入而不能使用远程操作,因此需要攻击者实体改变证书。请注意,利用此漏洞的攻击者可以覆盖设备管理策略,如最低密码要求(不太理解the minimum password requirements,估计可能是PIN吧)。

名称:  369.png查看次数: 1文件大小:  18.2 KB 
图7:攻击Android的设置

名称:  370.png查看次数: 1文件大小:  6.7 KB
图8:用户不需要提供他的凭证

六,修复

    谷歌在Android 4.4KitKat中提供的补丁添加了一个新的保护API,PreferenceActivity.isValidFragment,通过PreferenceActivity调用之前的动态实例Fragment (见图9)。这个isValidFragment方法必须覆写,否则默认实例将抛出异常,详情参考SDK Reference。我们希望开发人员正确地实现这个方法(例如white-list),因为脆弱的实例将使你的应用易受攻击。

代码:
Javaprivate void switchToHeaderInner(String fragmentName, Bundle args, int direction) {        getFragmentManager().popBackStack(BACK_STACK_PREFS,                FragmentManager.POP_BACK_STACK_INCLUSIVE);        if (!isValidFragment(fragmentName)) {            throw new IllegalArgumentException("Invalid fragment for this activity: "                    + fragmentName);        }        Fragment f = Fragment.instantiate(this, fragmentName, args);        FragmentTransaction transaction = getFragmentManager().beginTransaction();        transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);        transaction.replace(com.android.internal.R.id.prefs, f);        transaction.commitAllowingStateLoss();    }
图9:Android KitKat中安全的Fragment实例

漏洞版本
Android 4.3 Jelly Bean及更低

没有漏洞版本
Android 4.4 KitKat

披露时间表
12/05/2013 Android安全团队回答:“问题已修复。
12/05/2013 请求的状态更新。
11/11/2013 Android安全团队回答:“修复进行中”
10/24/2013 请求的状态更新。
07/14/2013 Android安全团队回答:“我们正在调查这一问题”。
07/12/2013 披露给Android安全团队。

ps:
    初次翻译水平有限,不足之处请见谅.

    这个漏洞中文资料比较少,只发现了腾讯的一篇较短的总结,大致如下:

    Android框架层的注入漏洞形成的原因是因为Android框架支持在Activity包含多个Fragment的以展示界面。而Preference Activity是一个支持Fragment的基类activity,其会根据传入的参数EXTRA_SHOW_FRAGMENT, (‘:android:show_fragment’)动态创建fragment而现实相应的界面, 问题就出在Preference Activity没有检查传入的参数, 盲目的根据传入的参数构建对象。漏洞的主要原理是如果extend了PreferenceActivity的activity是属性为export,只要通过intent输入适当的extra就可以调用其内部的任意fragment。

    目前Google在最新的Android 4.4 KitKat系统已经修复了该漏洞问题,但是该漏洞还普遍存在于Android3.x-4.3的系统版本中,当有Activity继承Preference Activity类并且被声明成export=true的时候就具备了被攻击的条件,这很可能会遭到黑客的恶意利用。

    附为原文所述的白皮书,里面有更为详细的漏洞描述.
上传的附件文件类型: pdfandroid-collapses-into-fragments.pdf (323.4 KB, 141 次下载)

0 0
原创粉丝点击