Sanitize All The Extras!
Earlier this year, I blogged about not having an accidental API.
Google themselves were caught out for having an accidental API, in
the form of App Ops. Originally, this was a simple accidental API, in
that they exported an activity for app ops. However, they had a more
subtle accidental API,
now revealed to be a more general security flaw
related to the use of Intent
extras.
For those of you, like me, who were wondering about the new isValidFragment()
we had to implement on PreferenceActivity
, it relates to this problem.
Tactically, do not export a PreferenceActivity
.
Strategically:
-
Do not export activities unless you want third parties to invoke them
-
Make sure that your extras make sense, on all of your activities, as for exported activities, those extras are part of your API
PreferenceActivity
supports extras to load specific PreferenceFragment
s
into the activity. This is used heavily by the Settings app, to allow apps
to drive straight into particular screens (actually fragments). Unfortunately,
there was no logic in PreferenceActivity
to ensure that only those fragments
that were supposed to be externally reachable were loaded via these extras —
hence, the addition of isValidFragment()
. So, a properly-crafted Intent
can open any exported PreferenceActivity
and launch any PreferenceFragment
from
it, in the absence of such defenses.
Usually, this would not be a security risk on its own, but if the fragments are also looking at extras, to configure their own behavior, being able to reach any fragment means that some fragments that were written assuming they were only internally reachable might be at risk. The article I linked to above cites one example, related to changing the device’s lock screen PIN or pattern.
As a reminder, an activity is exported if either:
-
The
<activity>
hasandroid:exported="true"
, or -
The
<activity>
has an<intent-filter>
and does not also haveandroid:exported="false"
The latter approach is an anti-pattern, as it can cause confusion with
choosers, since non-exported activities will appear in a chooser if the activities
match on the <intent-filter>
. Generally speaking, only have activities
with an <intent-filter>
if they actually are to be used by third-party
apps, such as the home screen, and get rid of <intent-filter>
from
everything else.
For those activities that you do export, typically via <intent-filter>
,
sanitize all the extras!. These are inputs, no different than parameters
you might have on some method that a third party could call. Apply defensive
programming techniques to make sure that the extras fit valid values (and
combinations of values, where applicable) before using them.