In the previous chapter, we provided an overview of the iOS platform and described the structure of iOS apps. In this chapter, we'll introduce basic processes and techniques you can use to test iOS apps for security flaws. These basic processes are the foundation for the test cases outlined in the following chapters.
Unlike the Android emulator, which fully emulates the hardware of an actual Android device, the iOS SDK simulator offers a higher-level simulation of an iOS device. Most importantly, emulator binaries are compiled to x86 code instead of ARM code. Apps compiled for a real device don't run, making the simulator useless for black box analysis and reverse engineering.
The following is the most basic iOS app testing setup:
laptop with admin rights
Wi-Fi network that permits client-to-client traffic or USB multiplexing
at least one jailbroken iOS device (of the desired iOS version)
Burp Suite or other interception proxy tool
Although you can use a Linux or Windows machine for testing, you'll find that many tasks are difficult or impossible on these platforms. In addition, the Xcode development environment and the iOS SDK are only available for macOS. This means that you'll definitely want to work on a Mac for source code analysis and debugging (it also makes black box testing easier).
You should have a jailbroken iPhone or iPad for running tests. These devices allow root access and tool installation, making the security testing process more straightforward. If you don't have access to a jailbroken device, you can apply the workarounds described later in this chapter, but be prepared for a difficult experience.
iOS jailbreaking is often compared to Android rooting, but the process is actually quite different. To explain the difference, we'll first review the concepts of "rooting" and "flashing" on Android.
Rooting: This typically involves installing the
su binary on the system or replacing the whole system with a rooted custom ROM. Exploits aren't required to obtain root access as long as the bootloader is accessible.
Flashing custom ROMs: This allows you to replace the OS that's running on the device after you unlock the bootloader. The bootloader may require an exploit to unlock it.
On iOS devices, flashing a custom ROM is impossible because the iOS bootloader only allows Apple-signed images to be booted and flashed. This is why even official iOS images can't be installed if they aren't signed by Apple, and it makes iOS downgrades only possible for as long as the previous iOS version is still signed.
The purpose of jailbreaking is to disable iOS protections (Apple's code signing mechanisms in particular) so that arbitrary unsigned code can run on the device. The word "jailbreak" is a colloquial reference to all-in-one tools that automate the disabling process.
Cydia is an alternative app store developed by Jay Freeman (aka "saurik") for jailbroken devices. It provides a graphical user interface and a version of the Advanced Packaging Tool (APT). You can easily access many "unsanctioned" app packages through Cydia. Most jailbreaks install Cydia automatically.
Developing a jailbreak for a given version of iOS is not easy. As a security tester, you'll most likely want to use publicly available jailbreak tools. Still, we recommend studying the techniques that have been used to jailbreak various versions of iOS-you'll encounter many interesting exploits and learn a lot about OS internals. For example, Pangu9 for iOS 9.x exploited at least five vulnerabilities, including a use-after-free kernel bug (CVE-2015-6794) and an arbitrary file system access vulnerability in the Photos app (CVE-2015-7037).
End users often jailbreak their devices to tweak the iOS system's appearance, add new features, and install third-party apps from unofficial app stores. For a security tester, however, jailbreaking an iOS device has even more benefits. They include, but aren't limited to, the following:
root access to the file system
possibility of executing applications that haven't been signed by Apple (which includes many security tools)
unrestricted debugging and dynamic analysis
access to the Objective-C or Swift runtime
There are tethered, semi-tethered, semi-untethered, and untethered jailbreaks.
Tethered jailbreaks don't persist through reboots, so re-applying jailbreaks requires the device to be connected (tethered) to a computer during every reboot. The device may not reboot at all if the computer is not connected.
Semi-tethered jailbreaks can't be re-applied unless the device is connected to a computer during reboot. The device can also boot into non-jailbroken mode on its own.
Semi-untethered jailbreaks allow the device to boot on its own, but the kernel patches (or user-land modifications) for disabling code signing aren't applied automatically. The user must re-jailbreak the device by starting an app or visiting a website (not requiring a connection to a computer, hence the term untethered).
Untethered jailbreaks are the most popular choice for end users because they need to be applied only once, after which the device will be permanently jailbroken.
Jailbreaking an iOS device is becoming more and more complicated because Apple keeps hardening the system and patching the exploited vulnerabilities. Jailbreaking has become a very time-sensitive procedure because Apple stops signing these vulnerable versions relatively soon after releasing a fix (unless the jailbreak benefits from hardware-based vulnerabilities, such as the limera1n exploit affecting the BootROM of the iPhone 4 and iPad 1). This means that you can't downgrade to a specific iOS version once Apple stops signing the firmware.
If you have a jailbroken device that you use for security testing, keep it as is unless you're 100% sure that you can re-jailbreak it after upgrading to the latest iOS version. Consider getting one (or multiple) spare device(s) (which will be updated with every major iOS release) and waiting for a jailbreak to be released publicly. Apple is usually quick to release a patch once a jailbreak has been released publicly, so you have only a couple of days to downgrade (if it is still signed by Apple) to the affected iOS version and apply the jailbreak.
iOS upgrades are based on a challenge-response process (generating as a result the named SHSH blobs). The device will allow the OS installation only if the response to the challenge is signed by Apple. This is what researchers call a "signing window," and it is the reason you can't simply store the OTA firmware package you downloaded via iTunes and load it onto the device whenever you want to. During minor iOS upgrades, two versions may both be signed by Apple (the latest one, and the previous iOS version). This is the only situation in which you can downgrade the iOS device. You can check the current signing window and download OTA firmware from the IPSW Downloads website.
Different iOS versions require different jailbreaking techniques. Determine whether a public jailbreak is available for your version of iOS. Beware of fake tools and spyware, which are often hiding behind domain names that are similar to the name of the jailbreaking group/author.
The jailbreak Pangu 1.3.0 is available for 64-bit devices running iOS 9.0. If you have a device that's running an iOS version for which no jailbreak is available, you can still jailbreak the device if you downgrade or upgrade to the target jailbreakable iOS version (via IPSW download and iTunes). However, this may not be possible if the required iOS version is no longer signed by Apple.
The iOS jailbreak scene evolves so rapidly that providing up-to-date instructions is difficult. However, we can point you to some sources that are currently reliable.
Note that any modification you make to your device is at your own risk. While jailbreaking is typically safe, things can go wrong and you may end up bricking your device. No other party except yourself can be held accountable for any damage.
Some apps attempt to detect whether the iOS device on which they're running is jailbroken. This is because jailbreaking deactivates some of iOS' default security mechanisms. However, there are several ways to get around these detections, and we'll introduce them in the chapters "Reverse Engineering and Tampering on iOS" and "Testing Anti-Reversing Defenses on iOS."
Once you've jailbroken your iOS device and Cydia has been installed (as shown in the previous screenshot), proceed as follows:
From Cydia install aptitude and OpenSSH.
SSH into your iOS device.
The default users are
The default password is
Change the default password for both users
Add the following repository to Cydia:
Install Frida from Cydia.
Cydia allows you to manage repositories. One of the most popular repositories is BigBoss, which contains various packages, such as the BigBoss Recommended Tools package. If your Cydia installation isn't pre-configured with this repository, you can add it by navigating to Sources -> Edit, then clicking "Add" in the top left and entering the following URL:
You may also want to add the HackYouriPhone repository to get the AppSync package:
The following are some useful packages you can install from Cydia to get started:
BigBoss Recommended Tools: Installs many useful command line tools for security testing including standard Unix utilities that are missing from iOS, including wget, unrar, less, and sqlite3 client.
adv-cmds: Advanced command line. Includes finger, fingerd, last, lsvfs, md, and ps.
IPA Installer Console: Tool for installing IPA application packages from the command line. Package name is
Class Dump: A command line tool for examining the Objective-C runtime information stored in Mach-O files.
Cydia or Mobile Substrate: A platform that makes developing third-party iOS add-ons easier via dynamic app manipulation or introspection.
AppList: Allows developers to query the list of installed apps and provides a preference pane based on the list.
PreferenceLoader: A Mobile Substrate-based utility that allows developers to add entries to the Settings application, similar to the SettingsBundles that App Store apps use.
AppSync Unified: Allows you to sync and install unsigned iOS applications.
Your analyst workstation should have at least the following installed:
an SSH client
an interception proxy. In this guide, we'll be using BURP Suite.
Other useful tools we'll be referring throughout the guide:
The preferred method of statically analyzing iOS apps involves using the original Xcode project files. Ideally, you will be able to compile and debug the app to quickly identify any potential issues with the source code.
Black box analysis of iOS apps without access to the original source code requires reverse engineering. For example, no decompilers are available for iOS apps (although most commercial and open-source disassemblers can provide a pseudo-source code view of the binary), so a deep inspection requires you to read assembly code. We won't go into too much detail of assembly code in this chapter, but we will revisit the topic in the chapter "Reverse Engineering and Tampering on iOS."
The static analysis instructions in the following chapters are based on the assumption that the source code is available.
Several automated tools for analyzing iOS apps are available; most of them are commercial tools. The free and open source tools MobSF and Needle have some static and dynamic analysis functionality. Additional tools are listed in the "Static Source Code Analysis" section of the "Testing Tools" appendix.
Don't shy away from using automated scanners for your analysis - they help you pick low-hanging fruit and allow you to focus on the more interesting aspects of analysis, such as the business logic. Keep in mind that static analyzers may produce false positives and false negatives; always review the findings carefully.
Life is easy with a jailbroken device: not only do you gain easy access to the app's sandbox, the lack of code signing allows you to use more powerful dynamic analysis techniques. On iOS, most dynamic analysis tools are based on Cydia Substrate, a framework for developing runtime patches that we will cover later, or Frida, a dynamic introspection tool. For basic API monitoring, you can get away with not knowing all the details of how Substrate or Frida work - you can simply use existing API monitoring tools.
Needle is an all-in-one iOS security assessment framework. The following section includes the steps necessary to install and use Needle.
The following commands install the dependencies required to run Needle on Linux.
# Unix packages$ sudo apt-get install python2.7 python2.7-dev sshpass sqlite3 lib32ncurses5-dev# Python packages$ sudo pip install readline paramiko sshtunnel frida mitmproxy biplist# Download source$ git clone https://github.com/mwrlabs/needle.git
The following commands install the dependencies required to run Needle on macOS.
# Core dependencies$ brew install python$ brew install libxml2$ xcode-select --install# Python packages$ sudo -H pip install --upgrade --user readline$ sudo -H pip install --upgrade --user paramiko$ sudo -H pip install --upgrade --user sshtunnel$ sudo -H pip install --upgrade --user frida$ sudo -H pip install --upgrade --user biplist# sshpass$ brew install https://raw.githubusercontent.com/kadwanev/bigboybrew/master/Library/Formula/sshpass.rb# mitmproxy$ wget https://github.com/mitmproxy/mitmproxy/releases/download/v0.17.1/mitmproxy-0.17.1-osx.tar.gz$ tar -xvzf mitmproxy-0.17.1-osx.tar.gz$ sudo cp mitmproxy-0.17.1-osx/mitm* /usr/local/bin/# Download source$ git clone https://github.com/mwrlabs/needle.git
The only prerequisite is a Jailbroken device, with the following packages installed:
Apt 0.7 Strict
(For nonessential prerequisites, please refer to Device Dependencies).
Add the following repository to the Cydia Sources: mobiletools.mwrinfosecurity.com/cydia/
Search for the NeedleAgent package and install it.
If the setup process is successful, you'll find the NeedleAgent app on the home screen.
First, the NeedleAgent needs to be started on the device. This can be accomplished by following these steps:
Open the NeedleAgent app on your device.
Tap on "Listen" in the top left corner, and the NeedleAgent will start listening on port
4444 by default. The default port can be changed via the field in the top right.
Next, Needle needs to be launched on the host machine. To launch Needle, open a console and type:
$ python needle.py__ _ _______ _______ ______ ______| \ | |______ |______ | \ | |______| \_| |______ |______ |_____/ |_____ |______Needle v1.0 [mwr.to/needle][MWR InfoSecurity (@MWRLabs) - Marco Lancini (@LanciniMarco)][needle] > helpCommands (type [help|?] <topic>):---------------------------------back exit info kill pull reload search shell show useexec_command help jobs load push resource set shell_local unset[needle] > show optionsName Current Value Required Description------------------------ ------------- -------- -----------AGENT_PORT 4444 yes Port on which the Needle Agent is listeningAPP no Bundle ID of the target application (e.g., com.example.app). Leave empty to launch wizardDEBUG False yes Enable debugging outputHIDE_SYSTEM_APPS False yes If set to True, only 3rd party apps will be shownIP 127.0.0.1 yes IP address of the testing device (set to localhost to use USB)OUTPUT_FOLDER /root/.needle/output yes Full path of the output folder, where to store the output of the modulesPASSWORD ******** yes SSH Password of the testing devicePORT 2222 yes Port of the SSH agent on the testing device (needs to be != 22 to use USB)PUB_KEY_AUTH True yes Use public key auth to authenticate to the device. Key must be present in the ssh-agent if a passphrase is usedSAVE_HISTORY True yes Persists command history across sessionsSKIP_OUTPUT_FOLDER_CHECK False no Skip the check that ensures the output folder does not already contain other files. It will automatically overwrite any fileUSERNAME root yes SSH Username of the testing deviceVERBOSE True yes Enable verbose output[needle] >
You will be presented with Needle's command line interface.
The tool has the following global options (list them via the
show options command and set them via the
set <option> <value> command):
USERNAME, PASSWORD: SSH credentials of the testing device (default values are "root" and "alpine", respectively)
PUB_KEY_AUTH: Use public key authentication for the SSH service running on the device. The key must be in the ssh-agent if a passphrase is used.
IP, PORT: The session manager embedded in Needle's core can handle Wi-Fi or USB SSH connections. If SSH-over-USB is chosen, the IP option must be set to localhost ("set IP 127.0.0.1") and PORT must be set to anything other than 22 ("set PORT 2222").
AGENT_PORT: Port on which the installed NeedleAgent is listening.
APP: This is the bundle identifier of the app that will be analyzed (e.g., "com.example.app"). If you don't know it beforehand, you can leave the field empty. Needle will then launch a wizard that prompts the user to select an app.
OUTPUT_FOLDER: This is the full path of the output folder, where Needle will store all module output.
SKIP_OUTPUT_FOLDER_CHECK: If set to "true," the output folder will not be checked for pre-existing files.
HIDE_SYSTEM_APPS: If set to "true," only third-party apps will be shown.
SAVE_HISTORY: If set to "true," the command history will persist across sessions.
VERBOSE, DEBUG: If set to "true," this will enable verbose and debug logging, respectively.
In order to use the modules in Needle, you may have to install its dependencies. Use this command in Needle:
Other modules may prompt you the
apt-get command has not been installed. To get
apt-get, go to your Cydia and look for
CyDelete and install it.
During a real black box test, a reliable Wi-Fi connection may not be available. In this situation, you can use usbmuxd to connect to your device's SSH server via USB.
Usbmuxd is a socket daemon that monitors USB iPhone connections. You can use it to map the mobile device's localhost listening sockets to TCP ports on your host machine. This allows you to conveniently SSH into your iOS device without setting up an actual network connection. When usbmuxd detects an iPhone running in normal mode, it connects to the phone and begins relaying requests that it receives via
Connect macOS to an iOS device by installing and starting iproxy:
$ brew install libimobiledevice$ iproxy 2222 22waiting for connection
The above command maps port
22 on the iOS device to port
2222 on localhost. With the following command, you should be able to connect to the device:
$ ssh -p 2222 root@localhostroot@localhost's password:iPhone:~ root#
You can also connect to your iPhone's USB via Needle.
We already know now that we can use iproxy to use SSH via USB. The next step would be to use the SSH connection to route our traffic to Burp that is running on our computer. Let's get started:
First we need to create the SSH connection
$ iproxy 2222 22waiting for connection
The next step is to make a remote port forwarding of port 8080 on the iOS device to the localhost interface on our computer to port 8080.
ssh -R 8080:localhost:8080 root@localhost -p 2222
You should now be able to reach Burp on your iOS device. Open Safari and go to 127.0.0.1:8080 and you should see the Burp Suite Page. This would also be a good time to [install the CA certificate](https://support.portswigger.net/customer/portal/articles/1841109-installing-burp-s-ca-certificate-in-an-ios-device "Installing Burp's CA Certificate in an iOS Device") of Burp on your iOS device.
The last step would be to set the proxy globally on your iOS device.
Go to Settings
Connect to any Wi-Fi (you can literally connect to any Wi-Fi as the traffic for port 80 and 443 will be routed through USB, as we are just using the Proxy Setting in the Wi-Fi so we can set a global Proxy)
Once connected click on the small blue icon on the right side of the connect Wi-Fi
Configure your Proxy by selecting Manual
Type in 127.0.0.1 as Server
Type in 8080 as Port
Open Safari and go to any webpage, you should see now the traffic in Burp. Thanks @hweisheimer for the initial idea!
System applications are in the
/Applications directory. You can use IPA Installer Console to identify the installation folder for user-installed apps (available under
/private/var/mobile/Containers/ since iOS 9). Connect to the device via SSH and run the command
ipainstaller (which does the same thing as
installipa) as follows:
iPhone:~ root# ipainstaller -l...sg.vp.UnCrackable1iPhone:~ root# ipainstaller -i sg.vp.UnCrackable1...Bundle: /private/var/mobile/Containers/Bundle/Application/A8BD91A9-3C81-4674-A790-AF8CDCA8A2F1Application: /private/var/mobile/Containers/Bundle/Application/A8BD91A9-3C81-4674-A790-AF8CDCA8A2F1/UnCrackable Level 1.appData: /private/var/mobile/Containers/Data/Application/A8AE15EE-DC8B-4F1C-91A5-1FED35258D87
The user-installed apps have two main subdirectories (plus the
Shared subdirectory since iOS 9):
The Application subdirectory, which is inside the Bundle subdirectory, contains the name of the app. The static installer files are in the Application directory, and all user data is in the Data directory.
The random string in the URI is the application's GUID. Every app installation has a unique GUID. There is no relationship between an app's Bundle GUID and its Data GUID.
App files are stored in the Data directory. To identify the correct path, SSH into the device and use IPA Installer Console to retrieve the package information (as shown previously):
iPhone:~ root# ipainstaller -l...sg.vp.UnCrackable1iPhone:~ root# ipainstaller -i sg.vp.UnCrackable1Identifier: sg.vp.UnCrackable1Version: 1Short Version: 1.0Name: UnCrackable1Display Name: UnCrackable Level 1Bundle: /private/var/mobile/Containers/Bundle/Application/A8BD91A9-3C81-4674-A790-AF8CDCA8A2F1Application: /private/var/mobile/Containers/Bundle/Application/A8BD91A9-3C81-4674-A790-AF8CDCA8A2F1/UnCrackable Level 1.appData: /private/var/mobile/Containers/Data/Application/A8AE15EE-DC8B-4F1C-91A5-1FED35258D87
You can now simply archive the Data directory and pull it from the device with
iPhone:~ root# tar czvf /tmp/data.tgz /private/var/mobile/Containers/Data/Application/A8AE15EE-DC8B-4F1C-91A5-1FED35258D87iPhone:~ root# exit$ scp -P 2222 root@localhost:/tmp/data.tgz .
Keychain-dumper lets you dump a jailbroken device's KeyChain contents. The easiest way to get the tool is to download the binary from its GitHub repo:
$ git clone https://github.com/ptoomey3/Keychain-Dumper$ scp -P 2222 Keychain-Dumper/keychain_dumper root@localhost:/tmp/$ ssh -p 2222 root@localhostiPhone:~ root# chmod +x /tmp/keychain_dumperiPhone:~ root# /tmp/keychain_dumper(...)Generic Password----------------Service: myAppAccount: key3Entitlement Group: RUD9L355Y.sg.vantagepoint.exampleLabel: (null)Generic Field: (null)Keychain Data: SmJSWxEsGeneric Password----------------Service: myAppAccount: key7Entitlement Group: RUD9L355Y.sg.vantagepoint.exampleLabel: (null)Generic Field: (null)Keychain Data: WOg1DfuH
In newer versions of iOS (iOS 11 and up), additional steps are necessary. See the README.md for more details. Note that this binary is signed with a self-signed certificate that has a "wildcard" entitlement. The entitlement grants access to all items in the Keychain. If you are paranoid or have very sensitive private data on your test device, you may want to build the tool from source and manually sign the appropriate entitlements into your build; instructions for doing this are available in the GitHub repository.
If you haven't already done so, you need to install the Frida Python package on your host machine:
$ pip install frida-tools
To connect Frida to an iOS app, you need a way to inject the Frida runtime into that app. This is easy to do on a jailbroken device: just install
frida-server through Cydia. Once it has been installed, the Frida server will automatically run with root privileges, allowing you to easily inject code into any process.
Start Cydia and add Frida's repository by navigating to Manage -> Sources -> Edit -> Add and entering https://build.frida.re. You should then be able to find and install the Frida package.
Connect your device via USB and make sure that Frida works by running the
frida-ps command and the flag '-U'. This should return the list of processes running on the device:
$ frida-ps -UPID Name--- ----------------963 Mail952 Safari416 BTServer422 BlueTool791 CalendarWidget451 CloudKeychainPro239 CommCenter764 ContactsCoreSpot(...)
We will demonstrate a few more uses for Frida below.
Intercepting Objective-C methods is a useful iOS security testing technique. For example, you may be interested in data storage operations or network requests. In the following example, we'll write a simple tracer for logging HTTP(S) requests made via iOS standard HTTP APIs. We'll also show you how to inject the tracer into the Safari web browser.
In the following examples, we'll assume that you are working on a jailbroken device. If that's not the case, you first need to follow the steps outlined in the previous section to repackage the Safari app.
Frida comes with
frida-trace, a ready-made function tracing tool.
frida-trace accepts Objective-C methods via the "-m" flag. You can pass it wildcards as well-given
-[NSURL *], for example,
frida-trace will automatically install hooks on all
NSURL class selectors. We'll use this to get a rough idea about which library functions Safari calls when the user opens a URL.
Run Safari on the device and make sure the device is connected via USB. Then start
frida-trace as follows:
$ frida-trace -U -m "-[NSURL *]" SafariInstrumenting functions...-[NSURL isMusicStoreURL]: Loaded handler at "/Users/berndt/Desktop/__handlers__/__NSURL_isMusicStoreURL_.js"-[NSURL isAppStoreURL]: Loaded handler at "/Users/berndt/Desktop/__handlers__/__NSURL_isAppStoreURL_.js"(...)Started tracing 248 functions. Press Ctrl+C to stop.
Next, navigate to a new website in Safari. You should see traced function calls on the
frida-trace console. Note that the
initWithURL: method is called to initialize a new URL request object.
/* TID 0xc07 */20313 ms -[NSURLRequest _initWithCFURLRequest:0x1043bca30 ]20313 ms -[NSURLRequest URL](...)21324 ms -[NSURLRequest initWithURL:0x106388b00 ]21324 ms | -[NSURLRequest initWithURL:0x106388b00 cachePolicy:0x0 timeoutInterval:0x106388b80
We can look up the declaration of this method on the Apple Developer Website:
- (instancetype)initWithURL:(NSURL *)url;
The method is called with a single argument of type
NSURL. According to the Apple Developer documentation, the
NSRURL class has a property called
absoluteString, whose value should be the absolute URL represented by the
We now have all the information we need to write a Frida script that intercepts the
initWithURL: method and prints the URL passed to the method. The full script is below. Make sure you read the code and inline comments to understand what's going on.
Start Safari on the iOS device. Run the above Python script on your connected host and open the device log (we'll explain how to open device logs in the following section). Try opening a new URL in Safari; you should see Frida's output in the logs.
Many apps log informative (and potentially sensitive) messages to the console log. The log also contains crash reports and other useful information. You can collect console logs through the Xcode "Devices" window as follows:
Connect your device to your host computer.
Choose Devices from the window menu.
Click on your connected iOS device in the left section of the Devices window.
Reproduce the problem.
Click the triangle-in-a-box toggle located in the lower left-hand corner of the Devices window's right section to view the console log's contents.
To save the console output to a text file, go to the bottom right and click the circular downward-pointing-arrow icon.
Burp Suite is an integrated platform for security testing mobile and web applications. Its tools work together seamlessly to support the entire testing process, from initial mapping and analysis of attack surfaces to finding and exploiting security vulnerabilities. Burp Proxy operates as a web proxy server for Burp Suite, which is positioned as a man-in-the-middle between the browser and web server(s). Burp Suite allows you to intercept, inspect, and modify incoming and outgoing raw HTTP traffic.
Setting up Burp to proxy your traffic is pretty straightforward. We assume that you have an iOS device and workstation connected to a Wi-Fi network that permits client-to-client traffic. If client-to-client traffic is not permitted, you can use usbmuxd to connect to Burp via USB.
PortSwigger provides a good tutorial on setting up an iOS device to work with Burp and a [tutorial on installing Burp's CA certificate to an iOS device](https://support.portswigger.net/customer/portal/articles/1841109-installing-burp-s-ca-certificate-in-an-ios-device "Installing Burp's CA Certificate in an iOS Device").
"SSL Kill Switch 2" is one way to disable certificate pinning. It can be installed via the Cydia store. It will hook on to all high-level API calls and bypass certificate pinning.
The Burp Suite app "Mobile Assistant" can also be used to bypass certificate pinning.
In some cases, certificate pinning is tricky to bypass. Look for the following when you can access the source code and recompile the app:
the API calls
methods/strings containing words like "pinning," "X.509," "Certificate," etc.
If you don't have access to the source, you can try binary patching or runtime manipulation:
If OpenSSL certificate pinning is used, you can try binary patching.
Applications written with Apache Cordova or Adobe PhoneGap use a lot of callbacks. Look for the callback function that's called on success and manually call it with Cycript.
Sometimes, the certificate is a file in the application bundle. Replacing the certificate with Burp's certificate may be sufficient, but beware the certificate's SHA sum. If it's hardcoded into the binary, you must replace it too!
Certificate pinning is a good security practice and should be used for all applications that handle sensitive information. EFF's Observatory lists the root and intermediate CAs that major operating systems automatically trust. Please refer to the map of the roughly 650 organizations that are Certificate Authorities Mozilla or Microsoft trust (directly or indirectly). Use certificate pinning if you don't trust at least one of these CAs.
It is also possible to bypass SSL Pinning on non-jailbroken devices by using Frida and objection. As a prerequisite the iOS app would need to be repackaged and signed, which can be automated through objection (please take note that this can only be done on macOS with Xcode). For detailed information please visit the objection GitHub Wiki on how to repackage. By using the following command in objection you can disable SSL Pinning:
$ ios sslpinning disable
See also the GitHub Page
If you want to get more details about white box testing and typical code patterns, refer to "iOS Application Security" by David Thiel. It contains descriptions and code snippets illustrating the most common certificate pinning techniques.
To get more information about testing transport security, please refer to the section "Testing Network Communication."
You can remotely sniff all traffic in real-time on iOS by creating a Remote Virtual Interface for your iOS device. First make sure you have Wireshark installed on your macOS machine.
Connect your iOS device to your macOS machine via USB.
Make sure that your iOS device and your macOS machine are connected to the same network.
Open Terminal on macOS and enter the following command:
$ rvictl -s x, where x is the UDID of your iOS device. You can find the [UDID of your iOS device via iTunes](http://www.iclarified.com/52179/how-to-find-your-iphones-udid "How to Find Your iPhone's UDID").
Launch Wireshark and select "rvi0" as the capture interface.
Filter the traffic in Wireshark to display what you want to monitor (for example, all HTTP traffic sent/received via the IP address 192.168.1.1).
ip.addr == 192.168.1.1 && http
Sometimes an application can require to be used on an iPad device. If you only have iPhone or iPod touch devices then you can force the application to accept to be installed and used on these kinds of devices. You can do this by changing the value of the property UIDeviceFamily to the value 1 in the Info.plist file.
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"><dict><key>UIDeviceFamily</key><array><integer>1</integer></array></dict></plist>
It is important to note that changing this value will break the original signature of the IPA file so you need to re-sign the IPA, after the update, in order to install it on a device on which the signature validation has not been disabled.
This bypass might not work if the application requires capabilities that are specific to modern iPads while your iPhone or iPod is a bit older.
Possible values for the property UIDeviceFamily can be found in the Apple Developer documentation.
Burp Suite - https://portswigger.net/burp/communitydownload
Frida - https://www.frida.re
IDB - https://www.idbtool.com
Introspy - https://github.com/iSECPartners/Introspy-iOS
ipainstaller - https://github.com/autopear/ipainstaller
Keychain-dumper - https://github.com/ptoomey3/Keychain-Dumper/
Needle - https://github.com/mwrlabs/needle
Objection - https://github.com/sensepost/objection
SSL Kill Switch 2 - https://github.com/nabla-c0d3/ssl-kill-switch2
Usbmuxd - https://github.com/libimobiledevice/usbmuxd
Wireshark - https://www.wireshark.org/download.html
Xcode - https://developer.apple.com/xcode/