For some experiments I am doing with apps in the time of writing I need to read the network traffic that they generate. However, most apps today have some kind of protection against MITM attacks, which is what allows me to read the traffic of the app. Almost all apps use SSL, so I am going to focus on how to bypass that. I am not the first that did this and surely will not be the last. Other scenario, for example, where bypassing SSL is a must is while pentesting a mobile app.
This post exists mostly for the future me in case I need to setup again my lab.
Since I have control of the phone I am running the app in, I can modify it as much as I need. The key thing in this bypass is that apps trust a set of certificates for connecting with SSL. If a certificate is invalid the connection will fail. A lot of apps trust the certificates installed in the device which are root certificates generated by trusted authorities (Trusted CAs). This certificates validate any certificate that was generated using the CAs certificate as a root. This approach is vulnerable to an attacker installing a certificated in this set of trusted certificates. In this scenario I am the attacker, so I can install whatever certificate I want on my device. To avoid this problem and others that the Trusted CAs infrastructure has there are more advanced SSL defenses that app developers use. The most common one I have seen in the wild is certificate pinning.
In certificate pinning the developers basically create a set of trusted certificates and the app will not trust any other certificate. This set of trusted certificates are embeded with the app and we can’t bypass that unless we modify the app somehow. With all this in mind there are two main tasks for each device; install a certificate that apps will trust, and bypass certificate pinning with some kind of patch.
For collecting my data I use mitmproxy and the documentation includes how to install the certificate both in Android and iOS.
Android has two set of certificates, system and user certificates. Up to Android 6 the apps would trust the certificates installed in the user set. Starting from Android 7 the user certificate is not trusted. There are solutions to this however.
The first solution requires a rooted phone with Magisk installed. Inside Magisk install the “Move Certificate” module. This module will move the certificates installed in the user set to the system set. Is trivial to see why this requires root.
The second approach requires to modify the APK of the app, more precisely, a file named
network_security_config.xml. I am not going to explain how to patch this file because the tool
apk-mitm which I will explain later already patches this.
First and foremost, jailbreak your iOS device if you want to analyze any kind of app that comes from the AppStore.
For bypassing certificate pinning in iOS you need to patch certain methods in the binary of the app. The easiest way to do this is dinamically patching the code in memory. iOS apps from the AppStore come encrypted and unless you decrypt it you can not see and modify the code of the app. For decrypting an iOS app you need a jailbroken device anyways. So it is much more easier to just run the patch dinamically from the device. I am aware of two methods, the first one relies on Frida and patches the app with it at startup. The tool is called Objection. However, it does not work in all the available APIs for certificate pinning.
If you have a jailbroken device you can install tweaks from Cydia. There is a tweak named SSLKillSwitch2 that basically does what its name implies. It adds a switch in the preferences app that allows to inject a bypass on almost all the APIs, and it works with iOS 12. This is my prefered method.
With Android you can use Objection too, but I found another tool named apk-mitm that injects the bypass statically by rewriting part of the bytecode. It also setups other switches that disable security features. This tool is easier to manage and setup. It also supports more SSL libraries than Objection.
Once you have patched the APK, just install it in the phone and run it.
If you have Android 5 or similar there are Xposed modules like SSLUnpinning_Xposed that implement the bypass. But because I can not use Xposed anymore I have not tested them.