ANDROID.LIFECYCLE.SV.FRAGMENTINJ

Unvalidated fragment class name

For security reasons, an application cannot normally access another application's sensitive data. In some cases, to facilitate feature reuse, an application can invoke another application's components (such as activities). Since activities access the input Intent’s data, a bad application can invoke the exported activity and provide it with malicious data This may trigger vulnerabilities if the data is not properly sanitized or validated in the target application.

This vulnerability was discovered in Android 4.3 Jelly Bean and earlier.

Vulnerability and risk

Any app which extended the PreferenceActivity class using an exported activity is automatically vulnerable. The malicious application can make the PreferenceActivity load an arbitrary Fragment of the vulnerable application; which is normally loaded inside a user Activity. The malicious application can then control it.

All applications that use PreferenceActivity are vulnerable.

Mitigation and prevention

Google patched Android 4.4 KitKat by adding a new protected API, PreferenceActivity.isValidFragment, which is called before the Fragment is dynamically instantiated. The isValidFragment method must be overridden.

Klocwork reports an error if the method isValidFragment is not called for verification.

Example 1

11  public class MyActivity extends PreferenceActivity {
12    protected void onCreate(Bundle savedInstanceState) {
13        super.onCreate(savedInstanceState);
14        final String initialFragment = getIntent().getStringExtra("EXTRA_SHOW_FRAGMENT");
15        final Fragment f = Fragment.instantiate(this, initialFragment, null);
16        final FragmentTransaction transaction = getFragmentManager().beginTransaction();
17        transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
18        transaction.replace(11, f);
19        transaction.commitAllowingStateLoss();
20 }

ANDROID.LIFECYCLE.SV.FRAGMENTINJ is reported for line 19: intent is coming from outside the application. Extra information is used to instantiate the fragment. No verification of the information is done in between.

Example 2

11  public class MyActivity extends PreferenceActivity {
12      protected void onCreate(Bundle savedInstanceState) {
13          super.onCreate(savedInstanceState);
14          final String initialFragment = getIntent().getStringExtra("EXTRA_SHOW_FRAGMENT");
15          if (!isValidFragment(initialFragment)) {
16              throw new IllegalArgumentException("Invalid fragment for this activity");
17          }
18          final Fragment f = Fragment.instantiate(this, initialFragment, null);
19          final FragmentTransaction transaction = getFragmentManager().beginTransaction();
20          transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
21          transaction.replace(11, f);
22          transaction.commitAllowingStateLoss();
23      }
24  
25      public boolean isValidFragment(final String name) {
26          //validate here …
27      }

The defect is not reported here as validation is performed on the line 15.