{% hint style="success" %}
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.
In iOS, a distinction in privilege exists between the user-accessible applications and the system's core processes. Applications run under the mobile
user identity, while the crucial system processes operate as root
. This separation is enhanced by a sandbox mechanism, which imposes strict limitations on what actions applications can undertake. For instance, even if applications share the same user identity, they are prohibited from accessing or modifying each other's data.
Applications are installed in a specific directory (private/var/mobile/Applications/{random ID}
) and have restricted read access to certain system areas and functionalities, such as SMS and phone calls. Access to protected areas triggers a pop-up request for user permission.
iOS offers developers the Data Protection APIs, built atop the Secure Enclave Processor (SEP) — a dedicated coprocessor for cryptographic operations and key management. The SEP ensures data protection integrity via a unique device-specific key, the device UID, embedded within it.
Upon file creation, a unique 256-bit AES encryption key is generated, encrypting the file's content. This encryption key, alongside a class ID, is then encrypted using a class key and stored within the file's metadata. Decrypting a file involves using the system's key to access the metadata, retrieving the class key with the class ID, and then decrypting the file's unique encryption key.
iOS defines four protection classes for data security, which determine when and how data can be accessed:
- Complete Protection (NSFileProtectionComplete): Data is inaccessible until the device is unlocked using the user's passcode.
- Protected Unless Open (NSFileProtectionCompleteUnlessOpen): Allows file access even after the device is locked, provided the file was opened when the device was unlocked.
- Protected Until First User Authentication (NSFileProtectionCompleteUntilFirstUserAuthentication): Data is accessible after the first user unlock post-boot, remaining accessible even if the device is locked again.
- No Protection (NSFileProtectionNone): Data is only protected by the device UID, facilitating quick remote data wiping.
The encryption of all classes, except for NSFileProtectionNone
, involves a key derived from both the device UID and the user's passcode, ensuring decryption is only possible on the device with the correct passcode. From iOS 7 onwards, the default protection class is "Protected Until First User Authentication".
Developers can use FileDP, a tool for inspecting the data protection class of files on an iPhone.
# Example code to use FileDP for checking file protection class
# Note: Ensure your device is jailbroken and has Python installed to use FileDP.
# Installation and usage of FileDP:
git clone https://github.com/abjurato/FileDp-Source
cd FileDp-Source
python filedp.py /path/to/check
In iOS, a Keychain serves as a secure encrypted container for storing sensitive information, accessible only by the application that stored it or those explicitly authorized. This encryption is fortified by a unique password generated by iOS, which itself is encrypted with AES. This encryption process leverages a PBKDF2 function, combining the user's passcode with a salt derived from the device's UID, a component only the secure enclave chipset can access. Consequently, even if the user's passcode is known, the Keychain contents remain inaccessible on any device other than the one where they were originally encrypted.
Management and access to the Keychain data are handled by the securityd
daemon, based on specific app entitlements like Keychain-access-groups
and application-identifier
.
The Keychain API, detailed at Apple's Keychain Services documentation, provides essential functions for secure storage management:
SecItemAdd
: Adds a new item to the Keychain.SecItemUpdate
: Updates an existing item in the Keychain.SecItemCopyMatching
: Retrieves an item from the Keychain.SecItemDelete
: Removes an item from the Keychain.
Brute-forcing the Keychain password involves either attacking the encrypted key directly or attempting to guess the passcode on the device itself, hindered significantly by secure enclave's enforcement of a delay between failed attempts.
Data protection levels for Keychain items are set using the kSecAttrAccessible
attribute during item creation or update. These levels, as specified by Apple, determine when and how Keychain items are accessible:
kSecAttrAccessibleAlways
: Accessible anytime, regardless of device lock status.kSecAttrAccessibleAlwaysThisDeviceOnly
: Always accessible, but not included in backups.kSecAttrAccessibleAfterFirstUnlock
: Accessible after the first unlock post-restart.kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
: Same as above, but not transferable to new devices.kSecAttrAccessibleWhenUnlocked
: Only accessible when the device is unlocked.kSecAttrAccessibleWhenUnlockedThisDeviceOnly
: Accessible when unlocked, not included in backups.kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly
: Requires device passcode, not included in backups.
AccessControlFlags
further refine access methods, allowing for biometric authentication or passcode use.
{% hint style="warning" %} On jailbroken devices, the Keychain's protections are compromised, posing a significant security risk. {% endhint %}
Unlike app-specific data deleted upon app uninstallation, Keychain data persists on the device. This characteristic could enable new owners of a second-hand device to access the previous owner's application data simply by reinstalling apps. Developers are advised to proactively clear Keychain data upon app installation or during logout to mitigate this risk. Here's a Swift code example demonstrating how to clear Keychain data upon the first app launch:
let userDefaults = UserDefaults.standard
if userDefaults.bool(forKey: "hasRunBefore") == false {
// Remove Keychain items here
// Update the flag indicator
userDefaults.set(true, forKey: "hasRunBefore")
userDefaults.synchronize() // Forces the app to update UserDefaults
}
In the realm of app development, sandboxing plays a crucial role in enhancing security. This process ensures that each app operates within its own unique home directory, thus preventing it from accessing system files or data belonging to other apps. The enforcement of these restrictions is carried out through sandbox policies, which are a part of the Trusted BSD (MAC) Mandatory Access Control Framework.
Developers have the ability to configure certain capabilities or permissions for their apps, such as Data Protection or Keychain Sharing. These permissions are applied immediately after the app is installed. Nonetheless, for accessing certain protected resources, the app must obtain explicit consent from the user at the time of the first attempt. This is achieved through the use of purpose strings or usage description strings, which are presented to users in a permission request alert.
For those with access to the source code, verification of permissions included in the Info.plist
file can be done by:
- Opening the project in Xcode.
- Locating and opening the
Info.plist
file. - Searching for keys prefixed with
"Privacy -"
, with the option to view raw keys/values for clarity.
When dealing with an IPA file, the following steps can be followed:
- Unzip the IPA.
- Locate the
Info.plist
file withinPayload/<appname>.app/
. - Convert the file to XML format if necessary, for easier inspection.
For example, the purpose strings in the Info.plist
file might look like this:
<plist version="1.0">
<dict>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Your location is used to provide turn-by-turn directions to your destination.</string>
The Info.plist
file of an app specifies device capabilities that help the App Store filter apps for device compatibility. These are defined under the UIRequiredDeviceCapabilities
key. For instance:
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
This example indicates that the app is compatible with the armv7 instruction set. Developers may also specify capabilities like nfc to ensure their app is only available to devices supporting NFC.
Entitlements are another critical aspect of iOS app development, serving as key-value pairs that grant apps permission to perform certain operations beyond runtime checks. For example, enabling Data Protection in an app involves adding a specific entitlement in the Xcode project, which is then reflected in the app's entitlements file or the embedded mobile provision file for IPAs.
- https://mas.owasp.org/MASTG/iOS/0x06d-Testing-Data-Storage
- https://github.com/OWASP/owasp-mastg/blob/master/Document/0x06h-Testing-Platform-Interaction.md
- https://mas.owasp.org/MASTG/tests/ios/MASVS-PLATFORM/MASTG-TEST-0069/
- https://mas.owasp.org/MASTG/iOS/0x06h-Testing-Platform-Interaction/
{% hint style="success" %}
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.