ANDROID.LIFECYCLE.SV.FRAGMENTINJ

未经验证的片段类名

出于安全考虑,应用程序通常无法访问其他应用程序的敏感数据。在某些情况下,为方便重复使用功能,应用程序可以调用其他应用程序的组件(例如活动)。由于活动可以访问输入 Intent 的数据,因此错误的应用程序可以调用已导出活动并向其提供恶意数据。如果未在目标应用程序中对数据进行适当地消毒或验证,上述情况可能触发漏洞。

在 Android 4.3 Jelly Bean 和更早版本中发现了此类漏洞。

漏洞与风险

通过使用已导出的活动扩展了 PreferenceActivity 类的所有应用程序都会自动出现漏洞。恶意应用程序可以让 PreferenceActivity 加载存在漏洞的应用程序的任意 Fragment,该项通常在用户 Activity 内加载。之后,恶意应用程序便可对其进行控制。

使用 PreferenceActivity 的所有应用程序均存在该漏洞。

缓解与预防

Google 通过添加新的受保护 API PreferenceActivity.isValidFragment(在动态实例化片段之前调用)修补了 Android 4.4 KitKat。必须覆盖 isValidFragment 方法。

如果未调用 isValidFragment 方法进行验证,Klocwork 将报告错误。

示例 1

复制
  public class MyActivity extends PreferenceActivity {
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        final String initialFragment = getIntent().getStringExtra("EXTRA_SHOW_FRAGMENT");
        final Fragment f = Fragment.instantiate(this, initialFragment, null);
        final FragmentTransaction transaction = getFragmentManager().beginTransaction();
        transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
        transaction.replace(11, f);
        transaction.commitAllowingStateLoss();
 }

针对第 19 行报告 ANDROID.LIFECYCLE.SV.FRAGMENTINJ:意图来自应用程序外部。额外的信息用于实例化片段。在此期间未进行任何信息验证。

示例 2

复制
  public class MyActivity extends PreferenceActivity {
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          final String initialFragment = getIntent().getStringExtra("EXTRA_SHOW_FRAGMENT");
          if (!isValidFragment(initialFragment)) {
              throw new IllegalArgumentException("Invalid fragment for this activity");
          }
          final Fragment f = Fragment.instantiate(this, initialFragment, null);
          final FragmentTransaction transaction = getFragmentManager().beginTransaction();
          transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
          transaction.replace(11, f);
          transaction.commitAllowingStateLoss();
      }
  
      public boolean isValidFragment(final String name) {
          //validate here …
      }

不会在此处报告缺陷,因为已在第 15 行执行验证。