Posted by Fred Chung, Android Developer Relations team
This post highlights a few of the security enhancements in Android 4.2 that are especially important for developers to be aware of and understand. Regardless whether you are targeting your app to devices running Jelly Bean or to earlier versions of Android, it's a good idea to validate these areas in order to make your app more secure and robust.
Content Provider default access has changed
Content providers are a facility to enable data sharing amongst app and system components. Access to content providers should always be based on the principle of least privilege — that is, only grant the minimal possible access for another component to carry out the necessary tasks. You can control access to your content providers through a combination of the
exported attribute in the provider declaration and app-specific permissions for reading/writing data in the provider.
In the example below, the provider
ReadOnlyDataContentProvider sets the
exported attribute to "true", explicitly declaring that it is readable by any external app that has acquired the
READ_DATA permission, and that no other components can write to it.
<provider android:name=”com.example.ReadOnlyDataContentProvider” android:authorities=”com.example” android:exported=”true” android:readPermission=”com.example.permission.READ_DATA” />
exported attribute is an optional field, potential ambiguity arises when the field is not explicitly declared in the manifest, and that is where the behavior has changed in Android 4.2.
Prior to Jelly Bean, the default behavior of the
exported field was that, if omitted, the content provider was assumed to be "exported" and accessible from other apps (subject to permissions). For example, the content provider below would be readable and writable by other apps (subject to permissions) when running on Android 4.1 or earlier. This default behavior is undesirable for sensitive data sources.
<provider android:name=”com.example.ReadOnlyDataContentProvider” android:authorities=”com.example” />
Starting in Android 4.2, the default behavior for the same provider is now “not exported”, which prevents the possibility of inadvertent data sharing when the attribute is not declared. If either the
targetSdkVersion of your app is set to 17 or higher, the content provider will no longer be accessible by other apps by default.
While this change helps to avoid inadvertent data sharing, it remains the best practice to always explicitly declare the
exported attribute, as well as declaring proper permissions, to avoid confusion. In addition, we strongly encourage you to make use of Android Lint, which among other things will flag any exported content providers (implicit or explicit) that aren't protected by any permissions.
New implementation of SecureRandom
Android 4.2 includes a new default implementation of
SecureRandom based on OpenSSL. In the older Bouncy Castle-based implementation, given a known seed,
SecureRandom could technically (albeit incorrectly) be treated as a source of deterministic data. With the new OpenSSL-based implementation, this is no longer possible.
In general, the switch to the new
SecureRandom implementation should be transparent to apps. However, if your app is relying on
SecureRandom to generate deterministic data, such as keys for encrypting data, you may need to modify this area of your app. For example, if you have been using
SecureRandom to retrieve keys for encrypting/decrypting content, you will need to find another means of doing that.
A recommended approach is to generate a truly random AES key upon first launch and store that key in internal storage. For more information, see the post "Using Cryptography to Store Credentials Safely".
On the one hand, this was a flexible mechanism; on the other hand, any untrusted content hosted in a WebView could potentially use reflection to figure out the public methods within the
Beginning in Android 4.2, you will now have to explicitly annotate public methods with
targetSdkVersion to 17 or higher.
Secure USB debugging
Android 4.2.2 introduces a new way of protecting your apps and data on compatible devices — secure USB debugging. When enabled on a device, secure debugging ensures that only host computers authorized by the user can access the internals of a USB-connected device using the ADB tool included in the Android SDK.
Secure debugging is an extension of the ADB protocol that requires hosts to authenticate before accessing any ADB services or commands. At first launch, ADB generates an RSA key pair to uniquely identifies the host. Then, when you connect a device that requires secure debugging, the system displays an authorization dialog such as the one shown below.
The user can allow USB debugging for the host for a single session or can give automatic access for all future sessions. Once a host is authorized, you can execute ADB commands for the device in the normal way. Until the device is authorized, it remains in "offline" state, as listed in the
adb devices command.
For developers, the change to USB debugging should be largely transparent. If you've updated your SDK environment to include ADB version 1.0.31 (available with SDK Platform-tools r16.0.1 and higher), all you need to do is connect and authorize your device(s). If your development device appears in "offline" state, you may need to update ADB. To so so, download the latest Platform Tools release through the SDK Manager.
Secure USB debugging is enabled in the Android 4.2.2 update that is now rolling out to Nexus devices across the world. We expect many more devices to enable secure debugging in the months ahead.
More information about security best practices
For a full list of security best practices for Android apps, make sure to take a look at the Security Tips document.