OWASP for iOS: M1 — Improper Platform usage, Part 1

This story describes how iOS developers can fight M1 category vulnerabilities from OWASP Mobile Top Ten 2016. The category covers misuse of a platform features or failure to use platform security controls. In Part 1 we’ll describe encryption tools provided by Apple and some other privacy-related features of iOS.

Anatoly Rosencrantz
7 min readDec 24, 2016

File Data Protection

Secure Enclave — coprocessor in A7 and later processors, uses encrypted memory and hardware random number generator to provide cryptographic operations for Data Protection Key management and Touch ID.

UID — unique identifier, AES 256-bit key fused into processor and Secure Enclave, unique for each device. Allows data to be tied to device.

All files on filesystem are protected by Data Protection technology (which is available for file and database APIs, including NSFileManager, CoreData, NSData, and SQLite):

  1. Every time a file on the data partition is created, Data Protection creates a new 256-bit key (the “per-file” key) and gives it to the hardware AES engine to encrypt the file.
  2. The per-file key is wrapped (in Secure Enclave) with one of several Data Protection class keys and stored in the file’s metadata together with notation on data protection class.
  3. The metadata of all files is encrypted with a file system key, which is created when iOS is first installed or after the device is wiped by a user. Erasing this key, user can make all files undecryptable.
  4. The Data Protection class key is protected with the UID and, for some classes, the user’s passcode
File Data Protection encryption flow

File keys are never exposed to processor. They are wrapped with ephemeral key known to AES engine and Secure Enclave only while travelling across system.

File Data Protection should be enabled in project settings (included into entitlements), but for all applications by default all the data is encrypted until first unlock.

Keychain Data Protection

iOS Keychain — SQLite database stored on the file system to handle passwords and other short but sensitive bits of data.

securityd daemon determines which keychain items each app can access according to it’s “keychain-access-groups”,“application-identifier,” and “application-group” entitlements. Since iOS9, Keychain cryptographic data is persisted in Secure Enclave (on iPhone 5S and higher).

There are five groups of items in Keychain: Generic Passwords, Internet Passwords, Identities, Certificates, and Keys.

Among other fields, each keychain item contain:

  1. Keychain Group Access (kSecAttrAccessGroup)allows apps of a developer to access shared keychain items on a device; apps must share the same bundle seed ID which can be set in entitlements.
  2. Data Protection Class (kSecAttrAccessible) — described in detail in next section.
  3. iCloud Keychain (kSecAttrSynchronizable) — allows users to securely sync their Keychain items between iOS devices and Mac computers without exposing that information to Apple. By default, keychain items added by third-party apps do not sync. Value should be used with compatible Data Protection Class (one without …ThisDeviceOnly suffix).
  4. administrative metadata, such as created and last updated timestamps, version number, per-item key wrapped with the protection class key,
  5. SHA-1 hashes of the attributes (such as the account and server name) used to query for the item without decrypting each item
  6. dictionary of attributes describing the item encoded as a binary plist and encrypted with the per-item key

“If someone steals your device, they’ll be able to read the contents of the Keychain. Generally, this is done by performing a temporary jailbreak and extracting the keys; using kSecAttrAccessibleAfterFirstUnlock will usually prevent this since a reboot is often required to perform the jailbreak. However, a code execution attack (such as someone exploiting a bug in a Wi-Fi driver) would give access to a device while it’s still running. In this case, kSecAttrAccessibleWhenUnlocked would be needed to prevent compromise of the keys, meaning that the attacker would need to determine the user’s passcode to extract secrets.”

David Thiel, “iOS Application Security”, 2016.

Example of all four functions to deal with Keychain: SecItemAdd, SecItemUpdate, SecItemDelete and SecItemCopyMatching. There are much more options: adding other attributes to query will let you feel the realm power of Keychain.

Data Protection Classes

Data Protection classes for File Data Protection and Keychain Data Protection

NSFileProtectionComplete / kSecAttrAccessibleWhenUnlocked(default): class key is protected with a key derived from the passcode and UID. Shortly after the user locks a device, the decrypted class key is discarded, making all data inaccessible until the user unlocks the device.

NSFileProtectionCompleteUnlessOpen: some files may need to be written while the device is locked. A good example of this is a mail attachment downloading in the background. This behaviour is achieved by using asymmetric elliptic curve cryptography.

NSFileProtectionCompleteUntilFirstUserAuthentication(default): class key is not removed from memory when the device is locked. Protects data from attacks that involve a reboot. Default class for all third-party app data. kSecAttrAccessibleAfterFirstUnlock: for keychain items that need to be accessed during background updates.

NSFileProtectionNone / kSecAttrAccessibleAlways: class key is protected only with the UID. Only affords fast remote wipe. By gossips, it was planned to be deprecated in iOS9, but at the moment (Dec-16) it still presents.

kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly behaves the same as kSecAttrAccessibleWhenUnlocked, but only available when the device is configured with a passcode. It is not included in any backups. If the passcode is removed or reset, the items will never be decrypted!

Other keychain classes have a …ThisDeviceOnly counterpart, which is always protected with the UID when being copied from the device during a backup, rendering it useless if restored to a different device.

When storing data, use the most restrictive protection class that still allows your application to function properly. To prevent Keychain item exposure via iTunes backup or iCloud Keychain, use one of …ThisDeviceOnly protection classes.

Keybags

The keys for both file and keychain Data Protection classes are collected and managed in keybags. iOS uses the following five keybags:

  1. User keybag is where the wrapped class keys used in normal operation
    of the device are stored. Binary plist in the No Protection class, but it’s contents are encrypted with a key wiped and regenerated each time a user changes their passcode.
  2. Device keybag is used to store the wrapped class keys used for device-specific data configured for shared use.
  3. Backup keybag is created when an encrypted backup is made by iTunes and stored on the computer to which the device is backed up. A new keybag is created with a new set of keys, and the backed-up data (except …ThisDeviceOnly keychain items) is re-encrypted to these new keys. The keybag is protected with the password set in iTunes (a brute-force attack could be attempted). In case of unencrypted backup, the files are not encrypted regardless of their Data Protection class, but the keychain remains protected with a UID-derived key and such backup can be used on same device only. So, keychain items migrate to a new device only if a backup password is set.
  4. Escrow keybag is used for iTunes syncing and MDM.
  5. iCloud Backup keybag is similar to the backup keybag. For all Data Protection classes except No Protection, the encrypted data is read from the device and sent to iCloud. The corresponding class keys are protected by iCloud keys.

Access to Safari saved passwords

iOS apps can interact with keychain items saved by Safari for password autofill using APIs:

  • SecRequestSharedWebCredential
  • SecAddSharedWebCredential

Access will be granted only if both the app developer and website administrator have given their approval, and the user has given consent. App developers express their intent to access Safari saved passwords by including an entitlement in their app. The entitlement lists the fully qualified domain names of associated websites. The websites must place a file on their server listing the unique app identifiers of apps they’ve approved. When an app with the com.apple.developer.associated-domains entitlement is installed, iOS makes a TLS request to each listed website, requesting the file/apple-app-site-association. If the file lists the app identifier of the app being installed, then iOS marks the website and app as having a trusted relationship. Only with a trusted relationship will calls to these two APIs result in a prompt to the user, who must agree before any passwords are released to the app, or are updated or deleted.

LocalAuthentication.framework vs Keychain Services Access Control

Touch ID — fingerprint sensing system. Works with Secure Enclave only, not backed up to anywhere.

Third-party apps can use system APIs to ask user to authenticate using Touch ID (or passcode if such fallback is allowed). App is only notified whether the authentication was successful or not.

There are two ways to force user pass Touch ID (or passcode) authentication from your app, but from user’s point of view they are same: system-styled UI will be presented, where developer did specify prompt string describing why user is asked to authenticate. All the actions with passcode or fingerprint will be performed by Secure Enclave.

Image from Biometric Authentication With Touch ID

First way, LocalAuthentication.framework, provides easy way for requesting authentication from users with specified security policies.

LocalAuthentication.framework provides quick way to verify that the device is Touch ID capable and ready, and present an authentication dialog to the user and evaluate whether or not their provided fingerprint or passcode matched.

More hardcore and low-level way: Keychain Access Control object can be included into SecItemAdd query while saving item to Keychain. Item will be returned from Keychain only after user will pass authentication. Access Control attribute kSecAttrAccessControl is mutually exclusive with the kSecAttrAccessible attribute:

Keychain Access Controls can be specified when storing data to Keychain by set of SecAccessControlCreateWithFlags attributes. This code does not use any wrappers, and you can see how verbose and it is with all the Unmanaged memory, pointers and C-functions.
Than, to access stored data, just query Keychain for a key. Optionally, prompt string can be specified. Keychain Services will present authentication dialog to the user and return data or nil depending on whether suitable fingerprint was provided or passcode matched.

Privacy controls

iOS helps prevent apps from accessing a user’s personal information without permission. If app tries, it will crash. In Settings users can see which apps they have permitted to access to (as of iOS10):

  • Contacts, Calendars, Reminders
  • Photos and Media Library
  • Motion activity on iPhone 5s or later
  • Social media accounts such as Twitter and Facebook
  • Microphone, Camera
  • HomeKit, HealthKit
  • Bluetooth sharing
  • Speech Recognition, CallKit and VoIP
  • TV Provider and SiriKit

Don’t request permissions that app does not need: if it will turn to be vulnerable, you will not unintentionally hurt users by providing backdoor to their more private zone. Also, try not asking for permission until it is absolutely necessary, so user will not get annoyed with all the request alerts jumping together on first start.

This text was written in December 2016, in respect of Swift3, Xcode8.1, iOS9 and iOS10. The article may be updated and complemented later.

--

--