Keychain Protection
iOS can use the Keychain APIs to store sensitive data, such as session tokens, or passwords. The Keychain is a SQLite database on the device that can only be accessed through the Keychain API's.
In iOS, the Keychain file is located at /private/var/Keychains/keychain-2.db
There are four Keychain API's that an app can use:
-
SecItemAdd
-
SecItemUpdate
-
SecItemCopyMatching
-
SecItemDelete
You can see if these APIs are in use by searching through the header files dumped from the executable binary, or by simply running the strings command against the executable binary of the application.
% grep -riI SecItem $HEADERS
% strings $BINARY | grep -i SecItem
Items stored in the Keychain can also have accessibility protections set for each entry. This determines how the data in the keychain entry can be accessed, whether it can be copied into a backup, or even transferred to a new device. Data protection for the Keychain items is set by using the kSecAttrAccessible key to SecItemAdd or SecItemUpdate.
There are several values that the kSecAttrAccessible key may have:
-
kSecAttrAccessibleAlways
-
kSecAttrAccessibleAlwaysThisDeviceOnly
-
kSecAttrAccessibleAfterFirstUnlock
-
kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
-
kSecAttrAccessibleWhenUnlocked
-
kSecAttrAccessibleWhenUnlockedThisDeviceOnly
-
kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly
In addition to accessibility protections, Keychain items may also have access control protections. These are set through the kSecAccessControl keys.
-
kSecAccessControlDevicePasscode
-
kSecAccessControlBiometryAny
-
kSecAccessControlBiometryCurrentSet
-
kSecAccessControlUserPresence
Any keys that are secured by biometrics (Touch ID or Face ID), are protected by the Secure Enclave Processor (SEP). In these cases, the Keychain does not hold the actual value of the key. Rather it holds a token that can be used to query SEP to obtain the actual key. This query will require you to provide a valid biometric authentication to obtain the key.
Dump Keychain with Objection
Objection has a built-in way to dump the Keychain entries for the running application.
-
Start Objection and connect to the application
% objection -g 'AppName' explore
-
Use the ios specific command to dump the Keychain (
ios keychain dump
)com.company.appname on (iPhone: 14.0) [usb] # ios keychain dump
-
You can also dump the Keychain entries out to a file in json format by adding
--json filename.json
com.company.appname on (iPhone: 14.0) [usb] # ios keychain dump --json keychain_dump.json
Note: You may be asked to authenticate using the devices passcode or TouchID
Dumping the iOS keychain...
Writing keychain as json to keychain_dump.json...
Dumped keychain to: keychain_dump.json(Note the entry for any biometrics keys)
-
The data is written into
keychain_dump.json
file in the current directory. You can review it from within Objectioncom.company.appname on (iPhone: 14.0) [usb] ## !cat keychain_dump.json
Running OS command: cat keychain_dump.json
[
{
"access_control": "None",
"accessible_attribute": "kSecAttrAccessibleWhenUnlockedThisDeviceOnly",
"account": "skillet-secure-storage",
"alias": "",
"comment": "",
"create_date": "2020-09-28 13:45:44 +0000",
"creator": "305406738",
"custom_icon": "",
"data": "",
"dataHex": "2df8a9f0ed4e8ba3da0fcfbf26xcx82c81b4acca9233d8xcx77c173fxcxfa4ba",
"description": "",
"entitlement_group": "4X5S3X9XX8.com.company.appname",
"generic": "",
"invisible": "1",
"item_class": "kSecClassGenericPassword",
"label": "",
"modification_date": "2020-09-28 13:45:44 +0000",
"negative": "",
"protected": "",
"script_code": "",
"service": "domain_key_1",
"type": "1985500759"
},
etc… -
Review these keys to ensure that proper protections are in place.