This post is part of a multi-part blog series about reverse engineering. In this post, I’ll cover some of the basics of iOS pentesting and describe some of the common tools and methods pentesters use for testing iOS apps.
What is a Mobile App Pentest?
It’s quite common for the developers of mobile applications to hire an independent 3rd party to conduct penetration testing to test the application’s security defenses and assess the application’s ability to resist various attack scenarios. In this post, I’ll cover some of the most common tools and techniques used for pentesting iOS apps. I’ll also explain why and how these tools and methods are used, so that you can prepare yourself for what you might expect if you have a pentest or vulnerability scan conducted on your iOS application. Finally, I’ll provide some mobile app security best practices that you can implement immediately in order to ensure your iOS app can pass a mobile pentest or vulnerability scan (or to remediate deficiencies found as a result of a pentest or vulnerability scan of your iOS app). If you’re interested Android, you can read an earlier post in which I covered common methods for pentesting Android apps.
Top iOS Pentesting Tools and Methods
Below are some widely used methods, tools and techniques used in penetration testing iOS apps. If you recently failed a penetration test for your iOS application, chances are it was due to weaknesses in your app security model or weak/missing in-app protection in one or more of the following areas. Note, this is by no means intended to be a comprehensive list, as there are countless tools and techniques available to compromise iOS apps. This post covers some of the most popular.
Jailbreaking & Jailbreak Bypass
One of the very first things most pen testers will do is attempt to Jailbreak iOS to gain administrative control over the operating system and file system. Why? Because jailbreaking makes it much easier to compromise an iOS app and bypass other security defenses. On a Jailbroken device, the attacker can gain full control over the operating system, file system, environment, and more easily attack any mobile application running on the device. This leaves any mobile application in a vulnerable position, especially if specific measures have not been taken to secure the application using mobile app security best practices.
Checkra1n is the most widely used Jailbreak tool currently because it uses a firmware exploit to achieve the jailbreak (that effectively means that Apple cannot effectively patch the vulnerabilities that Checkra1n exploits because they would need to replace the hardware itself). There are lots of other Jailbreak options, such as Unc0ver or Chimera. And if your app has Jailbreak prevention, the tester may use to tool like FlyJB or LibertyLite, and attempt to bypass the jailbreak detection or prevention.
The main goal of Jailbreaking is for the attacker to elevate privileges in order to compromise the app more easily. Once the iOS device is successfully jailbroken, the pen tester may seek to abuse these elevated privileges or elevate them further, increase their level of visibility and control, or to enable more powerful tools in their jailbroken environment. For example, they might install Cydia, which is an app store / repository for Jailbreaking, which gives the pen tester access to hundreds of other jailbreak tools or 3rd party extensions that they can use in their effort to compromise your app. From Cydia, they may install Mobile Substrate, which makes it easier to install and run programs on a Jailbroken phone. They might also install a file system manager like Filza or PlankFilza to gain unfettered access and control over the iOS file system.
And they will no doubt use OpenSSH so they can gain shell access, copy files back and forth onto Jailbroken devices, and run and execute commands and scripts. Having shell access will make it easier to disable, change or bypass other security controls.
Because Jailbreaking iOS allows an attacker to break down the security model, it’s always important to include in-app Jailbreak prevention in your app’s security defense.
Static Analysis Using Disassemblers
An iOS pentester may likely to use a disassembler like Hopper to analyze an executable and inspect the machine-level code that composes the binary. Using Hopper allows one to disassemble iOS apps to search for valuable data stored in strings preferences or to examine the app’s bytecode (a more human-readable format) so that they can understand what the code does and infer how the app works – all without running the app. For example, most disassemblers (like Hopper or IDA-pro) allow you to search string tables for values or keywords (such as method names or functions). The tool will map to the relevant classes, objects, values, variables, libraries associated with each function or method or construct relevant pseudo-code. This provides the attacker with an understanding of where best they should focus their efforts to compromise the app.
The tester may also build a call graph of the app, in order to understand the app’s logical control-flow. This allows the tester to understand the path of each function or method call, and the instructions/operations/arguments which are run as the code executes. Hopper provides the pen tester with several options for performing operations such as producing assembly text files, producing a new executable by patching or overriding the existing code to create a new .ipa.
App Tampering, Bypassing or Disabling Security Controls
Whether or not the tester has jailbroken iOS or not, they will undoubtedly look for other in-app security protections and attempt to disable them. Anti-tampering (if the app has it) is one of the main protections they would look to disable or bypass, as this would allow them to more easily maneuver in their effort to find data or compromise the app further.
For example, you implemented an anti-tampering library in the app’s code, the pen tester might use a disassembler like IDA-pro to examine the app’s bytecode, and then locate the specific address space where anti-tampering is implemented. Once they find the code and understand the way the anti-tampering is implemented, they can take the appropriate measure to bypass or disable the protection (by changing the code or logical flow).
With tamper protection disabled, they could then make many other unwanted modifications such as altering the core binary or resources within the bundle. They could also locate and modify properties files by altering key/value pairs stored in plists (or info.plist). Depending on what’s stored in the plist, they could do things like: alter bundle IDs, change configuration, preferences, permissions, or alter any values that might be stored as key/value pairs or dictionaries values stored in plists, etc. They might conduct these activities to determine how easy it might be for attackers to create clones or mods of your app, or to re-package or re-redistribute your app through alternative appstores. To prevent such activities, it’s important to implement comprehensive anti-tampering and application shielding that can detect and prevent the many methods attackers have at their disposal to make unwanted modifications to apps.
Hardcoded App Values or Insecurely Stored Data
All mobile apps use and store sensitive data, and there are lots of places within the app where data is stored. In order to deliver a functional app that users love, access to such data is often shared with other apps or subcomponents with the app. This is central to the app experience, and simply put, it’s all necessary – but that data needs to be protected. The problem is most pentesters and hackers know where to find this data, and they have dozens of tools at their disposal to reverse engineer the app to figure out where in the code important data is stored. And most of this data is not encrypted by default, which means that anybody that can find the data will be able to read it.
Below are some key locations/areas in iOS apps that are used to store data of different types for different purposes. The pen tester is likely to search and attempt to find/extract sensitive data stored in some of these locations:
- Property Lists (eg: info.plist stores bundle id, app-specific values, app permission info, IDFA info, 3rd party advertising and attribution libs/SDKs)
- Strings – CFStrings is often used to store user data that is commonly used by other internal components or external systems (such as authentication credentials)
- User Defaults eg: NSUserDefaults is often used to store user preference information, sometimes may store authentication state or access tokens so a different UI can be displayed depending on whether user was logged in).
- SQLite: The SQLite database that comes with iOS doesn’t encrypt by default. For example, to provide offline email access, the Gmail iOS app stores all the emails in a SQLite database file in plain-text
- Core Data – used to store permanent application data for offline use, and to manage relationships of different objects used data for to display in UI
- Keychain – can be used to store user passwords, cloud storage credentials, API keys, etc.
And because data stored in the above locations is not encrypted by default (with the exception of the keychain), the pentester is likely to find insecurely stored data if they look there, unless the developer has implemented data at rest encryption.
SSL Pinning Bypass / MitM Attack
Another common part of a pentester’s test plan is to test if they can compromise the networking connections or the chain of trust that the app uses when it communicates with backend servers. And since mobile apps operate in zero-trust environments, there are many ways they can do this. If they can successfully compromise the networking layer, that could enable an attacker to read, analyze or even modify network traffic, harvest sensitive data, or intercept credentials that can be used to compromise backend systems or steal data or funds directly.
Some common ways to do this are via a MitM attack, swapping out the app’s digital certificate, and replacing it with the certificate of their proxy tool of choice (common proxy tools are: Charles Proxy, Burp Suite, Wireshark, etc). This will allow the tester to re-route the app’s traffic to their own proxy so they can attempt to analyze, change, or further compromise the app. For this reason, protective techniques such as certificate pinning and other techniques are commonly used to protect data in transit.
Debugging, Dynamic Instrumentation
Now the pen tester might move on to dynamic hacking techniques, where they run the application in a controlled environment so they can analyze, observe behavior, or modify the application while running it. The pentester has a wide range of techniques they can perform, ranging from common debugging techniques using LLDB, all the way to advanced techniques like dynamic binary instrumentation, code injection, and other malicious methods used to modify an iOS application while it runs.
Method Hooking, Code Injection with Frida
Frida is a very powerful dynamic instrumentation toolkit that allows an attacker to discover, attach to, and interact with running processes of iOS apps and change the app’s behavior dynamically while the app runs. So first the tester might trace a running iOS process using the Frida Trace module and attach to it via function hooking. They can then interact dynamically with the target application, and replace the output by injecting custom code into the app.
With Frida, the injected code can be highly contextual to the target app, and further customized using automated scripts. Frida is often used in iOS pentests in combination with other tools in order to locate sensitive code and bypass an application’s security protections. If you think your pentester may use Frida as part of the penetration test, then it would be wise to consider implementing Frida prevention capabilities as part of the security model.
How To Pass an iOS Pentest – Guaranteed Certified Secure
Realistically speaking, if the pentester is successful in compromising your app in one or multiple of the above areas, that could result in ‘failure’ of the pentest or significant deficiencies that could delay your release (or even worse if your iOS app is compromised in the wild). Check out this post to learn the 5 Steps you can take immediately that will ensure your app can pass a mobile penetration test – guaranteed.