Let’s write Swift code to intercept SSL Pinning HTTPS Requests
One of the popular ways to inspect HTTPS requests in iOS Apps is the Man-in-the-middle (MITM) attack. This technique requires a machine to be used as a proxy server for the client. For this to work, the client has to install the proxy server’s certificate into the device global trust store. By doing this, the client whitelists the certificate and hence allows HTTPS communication with the proxy server.
Here’s an example of mitmproxy being used to inspect CNN iOS app. Prior to this, I have already installed the proxy server’s certificate on the device. Instructions can be found on mitmproxy website here
SSL Certificate Pinning
One way to protect your app against MITM is to use SSL certificate pinning. This involves having a copy of the trusted server’s certificate packaged into your iOS app and some additional code to ensure that the app only communicates with servers using that particular certificate. When SSL certificate pinning is active, the app will not allow any requests to be sent out to any untrusted server. Hence, MITM proxy servers will not be able to pick up the requests because the requests are not sent over the secured network channel.
Twitter iOS app employs SSL certificate pinning as a security feature for requests sent to https://api.twitter.com. MITM tools such as mitmproxy and Charles Proxy wont be able to inspect any Twitter api requests.
A solution to get around SSL certificate pinning is to attempt to intercept the requests BEFORE it gets sent over the secured HTTPS channel. This technique requires us to plant codes into the app so that we have direct access to the URLRequest object we want to inspect. So let’s first visit Apple’s URL Loading System.
URLProtocol — Apple’s URL Loading System
In Apple’s URL loading system, different URLProtocols are defined to handle different types of URL. Here’s the steps to create our own custom URLProtocol subclass.
1. Each URLProtocol subcalss class should minimally define the following
2. Register the new URLProtocol subclass with the loading system
3. Adding custom logging functions in canInit(with:) function.
We will be logging a string representation of the URLRequest instance in cURL command format to the console and to a slack channel (see line 28).
Putting all these together
Here’s the plan to allow us to inspect all network requests.
- Create a new Xcode Dynamic Framework Project. Here’s the github reference for this. https://github.com/depoon/NetworkInterceptor
Take note! This post is based on tag `0.0.1`.
- Create our own custom URLProtocol. eg CustormUrlProtocol. Add in custom code to create cURL command strings. In addition we will print out the cURL strings to the device console as well as sending a copy to a slack channel (just for the fun of it). https://github.com/depoon/NetworkInterceptor/blob/master/NetworkInterceptor/Source/RequestInterceptor/CustomUrlProtocolRequestInterceptor.swift#L51-L155
- We will register the new URLProtocol subclass into the loading system and perform method swizzling to ensure our protocol class gets evaluated before any existing apple protocol classes. https://github.com/depoon/NetworkInterceptor/blob/master/NetworkInterceptor/Source/RequestInterceptor/CustomUrlProtocolRequestInterceptor.swift#L11-L49
- I have created a Slack channel request logger for this project. https://github.com/depoon/NetworkInterceptor/blob/master/NetworkInterceptor/Source/RequestLogger/SlackRequestLogger.swift
- Build the framework
- You can drag and drop the framework into your other Xcode projects and start using this feature. Do check the console and your slack channel for the cURL commands.
- For iOS Device .ipa files, you will need to inject the framework (in iphoneos architecture) into the ipa file.
The Dynamic Library framework code injection technique can be found in my previous medium post. Great thing about this is that you do not need a jail-broken device for this to work.
Code injection is process of introducing external code into an existing software system. In this post, I will share the…medium.com
Do take note that you wont be able to perform code injection on production appStore iOS Apps as they are digital rights management (DRM) protected. Fortunately, you can find cracked versions of appstore apps on https://www.iphonecake.com. However, proceed at your own risk, you do not know whether these cracked apps have been previously altered with malicious codes.
Tinder’s API Request
Here are the requests I managed to see when I load the dynamic framework onto the Tinder iOS app.
Hmmm, I guess I did not like someone’s Tinder profile. Api request to “Pass” up on someone.
You will also notice that Tinder is also sending requests to Facebook Api. That is because Tinder has FacebookSDK embedded into the app and uses features like login.
Sadly, SSL Certificate pinning was not enabled on Tinder app. Anyone can trivially use a MITM tool to inspect all the requests. So let’s find another app.
Twitter’s API Request
As mentioned earlier, MITM tools will not be able to see any api.twitter.com requests on the console due to SSL certificate pinning. Attempts to login on the Twitter will fail as the app throws an authentication error and does not allow the request to be sent over the network.
After injecting our framework and disabling our proxy, we are able to see the login api request “/auth/1/xauth_password.json” including our ID and password values in the parameters (look at the 2nd last line shown in the Slack channel message).
Do note that upon successfully login into Twitter, the app crashed as the app detected that I am using my own development provisioning profile to sign the app and the app’s signature conflicted with KeyChain security. This is a trivial issue to resolve but for this medium post, I do not wish to further share app specific exploits outside of our main topic.
Tech Talk 2018
Here’s the iOS Dev Scout Meetup talk I gave on 30th May 2018 in Singapore. Towards the end, I showcased how I could inspect Twitter app’s HTTPS requests even when SSL pinning is active.
Speaker: Kenneth Poon - Write swift codes to intercept https requests - Intercept https requests even with SSL…engineers.sg
GitHub Repository References
NetworkInterceptor - Demo Project on how to intercept outgoing network requests on iOS Appsgithub.com
iOSDylibInjectionDemo - Using this Repository to demo how to inject dynamic libraries into cracked ipa files for jailed…github.com
I hope this article has given you insights. Feel free to try out the codes and inspect requests in your favourite iOS app. Do drop me an email email@example.com when you manage to succeed or require additional help to get it working.