“Gartner Listed - mobile application security guide”

April 3, 2017

OWASP Mobile Top 10 2016: M1 Improper Platform Usage

Modern connected mobile applications are coming under increased pressure from hackers and malware, on both iOS and Android. Several high-profile cases have highlighted the ease with which hackers can target mobile applications, and the lax security practices at some of the world’s largest organisations. Here at Codified Security we take mobile app security testing seriously, and we see the OWASP Mobile Top 10 as key to helping mobile developers understand and improve app security. 

The Open Web Application Security Project is an online community of volunteers who maintain a freely-available wiki of articles, documentation and best practices around web application security. The OWASP Mobile Top 10 is a mobile-specific extension to this great resource, focusing on both the mobile client architecture and the server-side infrastructure that supports it. It recently achieved ‘final’ status for the latest 2016 version but is still considered a work in progress. We’ve decided to fill-in some of the blanks with a few examples that many apps can make immediate use of.

M1 – Improper Platform Usage

The OWASP Mobile Top 10 identifies the top mobile risk areas numbered from M1-M10. The first of these covers the misuse of platform features and failure to use platform security controls. This includes misuse of Touch ID, the Keychain, Android intents, platform permissions, or other security features that are a part of the mobile operating system.

OWASP Mobile Top 10: M1 – iOS

Touch ID

Touch ID on iOS gives a user a way to authenticate and unlock their iPhone using their fingerprint in place of their passcode. It also has a use case for developers who want app level authentication using Touch ID.

There are two ways to add Touch ID to an app:

  1. Using Keychain Access Control Lists (ACLs)
  2. Using the LocalAuthentication framework to authenticate the user

When the LocalAuthentication framework is used it is vulnerable to bypassing either via modification of the local check at runtime, or patching the binary through overriding the LAContext evaluatePolicy:localizedReason:reply:method implementation. iOS uses this method to run a user presence check before returning Keychain items to the app.

How to fix it?

When implementing Touch ID for app-level authentication you should instead use the Keychain to store the app’s secret with an assigned ACL. This ACL should contain the kSecAccessControlUserPresence policy, which will be enforced by the OS. This example from Apple shows how to use Touch ID with Keychain.

Stack Overflow is a great source for Touch ID examples. This WWDC video from 2014 gives a great overview of the security features introduced in iOS 8, including Touch ID and the LocalAuthentication framework.

Keychain

The iOS Keychain gives users secure storage of passwords, keys and certificates. The Keychain secures data by encrypting it before storing it in the filesystem, relieving the need for the developer to implement their own encryption. The system also carefully controls which applications can access keychain items through Keychain Access Groups (for iCloud synchronized items) and Access Control Lists (ACLs).

Keychain items are generally unlocked when the user’s device is unlocked, using either the user’s passcode or TouchID depending upon the device settings and capabilities. By following this pattern the Keychain provides transparent authentication; that is, (after unlocking the keychain) the user does not have to log in separately to any services whose passwords are stored in the keychain.

There are several ways for the Keychain to be compromised and decrypted. Keychain controls are useless when a device is jailbroken, letting other apps read the keychain items. Older devices, such as the iPhone 4, are also vulnerable to BootROM exploits when there is physical access to the device.

How to fix it?

Set the attribute values for the keychain that will give you the highest level of protection without interfering with your app’s functions. Apps that utilise background refresh services may need to drop down to one of the AfterFirstUnlock constants for Keychain items that need to be accessed during background updates.

  • kSecAttrAccessibleWhenUnlocked
      • The Keychain item is accessible only after the device is unlocked
      • Data protection class keys required to decrypt the keychain items are loaded into memory only when the device is unlocked, and the encryption keys are automatically purged in 10 seconds once the device is locked
      • This is the default value for keychain items added without explicitly setting an accessibility constant
  • kSecAttrAccessibleAfterFirstUnlock
      • The Keychain item is accessible only after the first unlock of the device until reboot
      • Data protection class keys required to decrypt the keychain items are loaded into memory only when the user unlocks the device after a reboot and the keys remain in the memory till next reboot of the device.
  • kSecAttrAccessibleAlways
      • The Keychain item is accessible even when the device is locked
      • Data protection class keys required to decrypt the keychain items are always loaded into memory.
  • kSecAttrAccessibleWhenUnlockedThisDeviceOnly
      • The Keychain item is accessible only after the device is unlocked and the item cannot be migrated between devices
  • kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
      • The Keychain item is accessible after the first unlock of the device and the item cannot be migrated between devices
  • kSecAttrAccessibleAlwaysThisDeviceOnly
      • Keychain item is accessible even the device is locked and the item cannot be migrated between devices.

You should generally encrypt Keychain items with the ThisDeviceOnly constants where possible, otherwise it is possible for data to be exposed to other devices through iTunes backups or the iCloud Keychain.

Due to the known exploits above it is recommended that developers who need to protect sensitive data use app-level protection in addition to the Keychain security. One method could be to perform in-app authentication and then use that passcode to encrypt the data that is going to be stored in the Keychain.

If you’d like to learn more this article from SPR Consulting has some excellent detail around iOS Keychain security. The official iOS Security Guide from Apple is also very useful, and gives some detail regarding Apple’s implementation.

OWASP Mobile Top 10: M1 – Android

Intents

Intents are used in a number of ways on the Android platform:

  • To start an Activity – coordinating with other programs like browsing a web page
    • Using Context’s startActivity() method
  • As broadcasts to inform interested programs of changes or events
    • Using Context’s sendBroadcast()sendStickyBroadcast(), and
      sendOrderedBroadcast() family of methods
  • As a way to start, stop or communicate with background Services
    • Using Context’s startService()stopService(), and bindService() methods
  • To access data through ContentProviders, such as the user’s contacts
    • Using Context’s getContentResolver() or Activity’s managedQuery()
  • As call-backs to handle events, like returning results or errors asynchronously with
    PendingIntents provided by clients to servers through their Binder interfaces

Misuse of intents may launch vulnerable activities, interfere with other apps and lead to data leakage.

How to fix it?

Since intents are sent to other Android components such as Activities, Services and BroadcastReceivers, these components may be public or private. Set these components to android:exported=false in the app Manifest to stop this.

<service
 android:name=".RSSPullService"
 android:exported="false"/>

If you require your components to only be accessible to other applications from the same organisation and signed with the same key then it is recommended to use the <permission> element, with a protection level of signature in the Manifest.

<!-- Create a unique permission for your apps -->

    <permission android:name="com.mycompany.message.permission.OUR_MESSAGE" android:protectionLevel="signature" />

    <uses-permission android:name="com.mycompany.message.permission.OUR_MESSAGE" />

The Android security documentation is a great resource in this area. This guide from ISEC Partners is also very useful.

Intent Sniffing

A malicious Android application can register to receive broadcast or implicit intents from any other app. Malicious apps can then read the data passed with the intent, which may be considered sensitive. This process is called intent sniffing, and is quite easy to achieve with readily-available tools.

For example, if an app opens the web browser with a URL the malicious application could read the data within the URL. Another possibility is that an app may supply a user’s typed-in credentials to a broadcast intent to launch authenticated activities.

How to fix it?

You should always use explicit intents, rather than passing data between apps using broadcast intents. To create an explicit intent, ensure that you define a component name for the Intent object:

Our Intent explicitly starts the DownloadService class in our app

Intent downloadIntent = new Intent(this, DownloadService.class);
 downloadIntent.setData(Uri.parse(fileUrl));
 startService(downloadIntent);

You should also set android:exported to false on any activities or services that you don’t want other apps to call:

<service
 android:name=".RSSPullService"
 android:exported="false"/>

The Android Intent documentation goes into a lot more detail regarding intents, filtering and security. You can also find some great examples on Stack Overflow. For further reading we recommend The Mobile Application Hacker’s Handbook.

Insecure File Permissions

Insecure file permissions are one of the most common mistakes when it comes to using the Android platform’s facilities for data storage. Using the ‘world readable’ and ‘world writeable’ file permissions can cause data leaks and expose apps to attackers who are able to overwrite the app’s data.

One especially risky area is when dynamically loading code from files outside of your application APK, which can leave the application open to code injection. Dynamically loaded code runs with the same permissions as the rest of the application, so it must come from a verifiable source and only be accessible to your main application code.

How to fix it?

Follow the principle of least privilege when assigning permissions and avoid giving a file MODE_WORLD_READABLE or MODE_WORLD_WRITEABLE permissions. These permissions do not provide the ability to limit access to particular apps or provide any control of data format.

You should instead use a ContentProvider to share a file between apps, which can offer read and write permissions and can make dynamic permission grants on a case-by-case basis. You can also encrypt files using a key placed in the KeyStore and protect it with a user password that is not stored on the device.

The Android Security Tips article has some great detail around storing data and permissions. This McAfee white paper on Secure Coding for Android is also a good resource.

Codified Security is here to help make your mobile app secure whether it’s for iOS, Android, or to make sure you’re clearing the OWASP Mobile Top 10.