mobileuser. Each app has a unique home directory and is sandboxed, so that they cannot access protected system resources or files stored by the system or by other apps. These restrictions are implemented via sandbox policies (aka. profiles), which are enforced by the Trusted BSD (MAC) Mandatory Access Control Framework via a kernel extension. iOS applies a generic sandbox profile to all third-party apps called container. Access to protected resources or data (some also known as app capabilities) is possible, but it's strictly controlled via special permissions known as entitlements.
UIImagePickerController(iOS 11+) and its modern replacement
PHPickerViewController(iOS 14+). These APIs run on a separate process from your app and by using them, the app gets read-only access exclusively to the images selected by the user instead of to the whole "Camera Roll". This is considered a best practice to avoid requesting unnecessary permissions.
Info.plistfile of the app under the
Typically you'll find the
armv7capability, meaning that the app is compiled only for the armv7 instruction set, or if it’s a 32/64-bit universal app.
UIRequiredDeviceCapabilitiesas a mere indication that the app is using some specific resources. Unlike the entitlements related to app capabilities, device capabilities do not confer any right or access to protected resources. Additional configuration steps might be required for that, which are very specific to each capability.
bluetooth-ledevice capability can be set in order to restrict non-BLE capable devices from downloading their app.
NSBluetoothPeripheralUsageDescriptionkey has to be included in the
Info.plistfile, meaning that the user has to actively give permission. See "Purpose Strings in the Info.plist File" below for more information.
Entitlements are key value pairs that are signed in to an app and allow authentication beyond runtime factors, like UNIX user ID. Since entitlements are digitally signed, they can’t be changed. Entitlements are used extensively by system apps and daemons to perform specific privileged operations that would otherwise require the process to run as root. This greatly reduces the potential for privilege escalation by a compromised system app or daemon.
<appname>.entitlementsfile as the
com.apple.developer.default-data-protectionentitlement with default value
NSFileProtectionComplete. In the IPA we might find this in the
Info.plistfile of the app.
Info.plistfile in the default editor and search for the keys starting with
"Privacy - Location When In Use Usage Description"will turn into
Info.plistis located in
plutil -convert xml1 Info.plist) as explained in the chapter "iOS Basic Security Testing", section "The Info.plist File".
Info.plistfile to check if the permission makes sense.
Info.plistfile used by a Solitaire game:
NSPhotoLibraryUsageDescriptioncan be considered as a storage permission giving access to files that are outside of the app's sandbox and might also be accessible by other apps. In this case, it should be tested that no sensitive data is being stored there (photos in this case). For other purpose strings like
NSLocationAlwaysUsageDescription, it must be also considered if the app is storing this data securely. Refer to the "Testing Data Storage" chapter for more information and best practices on securely storing sensitive data.
Payload/<appname>.app/) under the name
.entitlementsfiles. This could be also the case for the
embedded.mobileprovisionfile. Still, you should be able to extract the entitlements property lists from the app binary yourself (which you've previously obtained as explained in the "iOS Basic Security Testing" chapter, section "Acquiring the App Binary").
-e) all XML files (
-qcto quietly run one command and exit) to search all strings on the app binary (
izz) containing "PropertyList" (
plistfiles. If we inspect the first one (0x0015d2a4) we see that we were able to completely recover the original entitlements file from Telegram.
stringscommand will not help here as it will not be able to find this information. Better use grep with the
-aflag directly on the binary or use radare2 (
-a, --textflag (treats all files as ASCII text):
-A num, --after-context=numflag to display more or less lines. You may use tools like the ones we presented above as well, if you have them also installed on your jailbroken iOS device.
This method should work even if the app binary is still encrypted (it was tested against several App Store apps).
<appname>.entitlementsfile and the
Info.plistfile, it is time to verify how the requested permissions and assigned capabilities are put to use. For this, a source code review should be enough. However, if you don't have the original source code, verifying the use of permissions might be specially challenging as you might need to reverse engineer the app, refer to the "Dynamic Analysis" for more details on how to proceed.
Info.plistfile match the programmatic implementations.
CLLocationManagerimplement this method):
-Uconnects to the USB device.
-mincludes an Objective-C method to the traces. You can use a glob pattern (e.g. with the "*" wildcard,
-m "*[* *authorizationStatus*]"means "include any Objective-C method of any class containing 'authorizationStatus'"). Type
frida-trace -hfor more information.
0x4(CLAuthorizationStatus.authorizedWhenInUse) and was called by
+[TGLocationUtils requestWhenInUserLocationAuthorizationWithLocationManager:]. As we anticipated before, you might use this kind of information as an entry point when reverse engineering the app and from there get inputs (e.g. names of classes or methods) to keep feeding the dynamic analysis.
tg://resolve?domain=fridadotreis a custom URL scheme and uses the
https://telegram.me/fridadotreis a universal link and uses the
.entitlementsfile looking for
com.apple.developer.associated-domains. Each of the domains must be prefixed with
applinks:, such as
apple-app-site-associationfile from the server using the associated domains you got from the previous step. This file needs to be accessible via HTTPS, without any redirects, at
"paths": ["*"]) in order to allow all possible paths. Only if specific areas of the website should not be handled by some app, the developer can restrict access by excluding them by prepending a
"NOT "(note the whitespace after the T) to the corresponding path. Also remember that the system will look for matches by following the order of the dictionaries in the array (first match wins).
applinks) in its
com.apple.developer.associated-domainsentitlement. iOS will refuse to open those links if the verification did not succeed. Some reasons to fail verification might include:
appIDs do not match (this would be the case of a malicious app). iOS would successfully prevent any possible hijacking attacks.
application:continueUserActivity:restorationHandler:. If you have the original project try searching for this method.
openURL:options:completionHandler:to open a universal link to the app's website, the link won't open in the app. As the call originates from the app, it won't be handled as a universal link.
From Apple Docs: When iOS launches your app after a user taps a universal link, you receive an
NSUserActivityobject with an
NSUserActivityTypeBrowsingWeb. The activity object’s
webpageURLproperty contains the URL that the user is accessing. The webpage URL property always contains an HTTP or HTTPS URL, and you can use
NSURLComponentsAPIs to manipulate the components of the URL. [...] To protect users’ privacy and security, you should not use HTTP when you need to transport data; instead, use a secure transport protocol such as HTTPS.
NSUserActivityobject comes from the
continueUserActivityparameter, as seen in the method above.
Universal links offer a potential attack vector into your app, so make sure to validate all URL parameters and discard any malformed URLs. In addition, limit the available actions to those that do not risk the user’s data. For example, do not allow universal links to directly delete content or access sensitive information about the user. When testing your URL-handling code, make sure your test cases include improperly formatted URLs.
NSUserActivityobject with an
NSUserActivityTypeBrowsingWeb. The activity object’s
webpageURLproperty contains the HTTP or HTTPS URL that the user accesses. The following example in Swift verifies exactly this before opening the URL:
NSURLComponentsAPI can be used to parse and manipulate the components of the URL. This can be also part of the method
application:continueUserActivity:restorationHandler:itself or might occur on a separate method being called from it. The following example demonstrates this:
openURL:options: completionHandler:method and check the data being handled.
Note that the
openURL:options:completionHandler:method is not only used to open universal links but also to call custom URL schemes.
schemeto "https" before opening it and how it uses the option
UIApplicationOpenURLOptionUniversalLinksOnly: truethat opens the URL only if the URL is a valid universal link and there is an installed app capable of opening that URL.
openURL:options:completionHandler:is among the ones found (remember that it might be also present because the app opens custom URL schemes). Next, to ensure that no sensitive information is being leaked you'll have to perform dynamic analysis and inspect the data being transmitted. Please refer to "Identifying and Hooking the URL Handler Method" in the "Dynamic Analysis" of "Testing Custom URL Schemes" section for some examples on hooking and tracing this method.
To do it from Safari you will have to find an existing link on a website that once clicked, it will be recognized as a Universal Link. This can be a bit time consuming.
apple-app-site-associationof apple.com we have seen above we chose the following paths:
http://www.apple.com/shop/buy-iphone/iphone-xr) it only offers the option to open it (in the browser).
http://www.apple.com/today) it shows options to open it in Safari and in "Apple Store":
Note that there is a difference between a click and a long press. Once we long press a link and select an option, e.g. "Open in Safari", this will become the default option for all future clicks until we long press again and select another option.
application:continueUserActivity: restorationHandler:by either hooking or tracing, we will see how it gets called as soon as we open the allowed universal link. For this you can use for example
https://t.me/addstickers/radare(found through a quick Internet research) and open it from the Notes app.
__handlers__/to obtain more details:
NSUserActivity. If we look in the Apple Developer Documentation we can see what else we can call from this object.
-iincludes any method. You can also use a glob pattern here (e.g.
-i "*open*Url*"means "include any function containing 'open', then 'Url' and something else")
xcrun can be used invoke Xcode developer tools from the command-line, without having them in the path. In this case it will locate and run swift-demangle, an Xcode tool that demangles Swift symbols.
application:continueUserActivity:restorationHandler:from the app delegate as expected.
application:continueUserActivity:restorationHandler:handles the URL but does not open it, it calls
NSUserActivityobject. In the previous case there was no data being transferred but it might be the case for other scenarios. To see this, be sure to hook the
userInfoproperty or access it directly from the
continueUserActivityobject in your hook (e.g. by adding a line like this
log("userInfo:" + ObjC.Object(args).userInfo().toString());).
com.apple.developer.associated-domainsentitlement and in the server's
apple-app-site-associationfile (in both cases via the keyword
"activitycontinuation":). See "Retrieving the Apple App Site Association File" above for an example.
If the user is using a web browser on the originating device, and the receiving device is an iOS device with a native app that claims the domain portion of the
webpageURLproperty, then iOS launches the native app and sends it an
NSUserActivityobject with an
webpageURLproperty contains the URL the user was visiting, while the
userInfodictionary is empty.
NSUserActivityobject we've received meets exactly the mentioned points:
UIActivitySharing you should pay special attention to:
excludedActivityTypesproperty. It is highly recommended to do the tests using the latest versions of iOS as the number of activity types that can be excluded can increase. The developers have to be aware of this and explicitly exclude the ones that are not appropriate for the app data. Some activity types might not be even documented like "Create Watch Face".
excludedActivityTypes, if any.
application:openURL:options:(or its deprecated version
UIApplicationDelegate application:openURL:sourceApplication:annotation:) in the app delegate.
Info.plistfile and search for:
UTImportedTypeDeclarationsif the app declares exported/imported custom document types.
CFBundleDocumentTypesto see if the app specifies any document types that it can open.
Note that this is the same as if we would retrieve the IPA from the phone or accessed via e.g. SSH and navigated to the corresponding folder in the IPA / app sandbox. However, with objection we are just one command away from our goal and this can be still considered static analysis.