The other day I was debugging a really nasty bug that happens only in our iOS app. I was really frustrated because I couldn’t figure out why it happens. Everything looks good when debugging the iOS code, but for some reason – the server failed to deserialize the request body. I freaked out – nothing I tried seems to solve the issue. If only there was an easy way to view the actual request and response, maybe I could understand what the issue was…
This is where a proxy comes in handy: A proxy can inspect the traffic and print it an easy to understand manner. There are a lot of available proxies you can use (like Charles (commercial) or Fidler), but OWASP Zaproxy (Zap) is the best open source proxy that I know. Let’s see how easy it is to set it up:
Step 1 – Install Zap’s Root CA Certificate
Installing the root CA certificate on our iOS device is required in order to allow Zap to inspect HTTPS traffic – by acting as a TLS termination proxy. To install it, start by exporting the root CA from Zap. Go to Zap, and click Tools -> Options -> Dynamic SSL Certificates to open this menu:
Click the little save button, and choose where to save the certificate. Now it’s time to import it – this is a simple as dragging the certificate file and dropping it inside the simulator. Once you drop the certificate, a new Safari window will appear:
Press allow – only because you know what is this certificate. Careful before doing something similar on your personal phone, or with a certificate that you’re not trusting! Now you should see the following window:
Press the install button, and again on the install button in the next window – and we’re almost done! Now it’s important to activate the certificate – otherwise, it will not be trusted by iOS. Go to Settings -> General -> About -> Certificate Trust Settings:
Press the little switch button near “OWASP Zed Attack Proxy Root CA”. Doing so will show another dialog box. Press continue – and now you’re done! From now, Zap can intercept TLS traffic from an app running on this Simulator 👏🏽 👏🏽
Before moving to the next step – a quick reminder: If you’re app use certificate pinning, the above will not work. Certificate pinning protects your app from someone trying to intercept TLS traffic – and this is why you want it. Make sure to disable it in you’re app code before continue reading!
Step 2 – Configure Proxy Settings
The next step is to configure iOS simulator to use Zap as a proxy for all outgoing requests. As iOS simulator uses the OS proxy settings, this is done by changing them. Open System Preferences -> Network and choose your active network connection (e.g. Wifi). Click the advance button and go to proxies tab:
Make sure you check both Web Proxy and Secure Web Proxy and set the correct details of Zap on both of them. If Zap is running on your local machine – the settings in the picture should work. Now press the “ok” button and “apply” on the main network settings and you’re done!
Step 3 – Profit!
It’s time for the fun part! Open any app on the simulator – and you should see the requests on Zap proxy. For example, this is what I see on Zap when I try to open my blog using Safari browser on the simulator:
You can easily see all the requests and response nicely printed. Zap support advanced features like replaying the request. This is useful if you want to take the product request and send it to a service running locally. Check out the context menu on the request to see everything Zap can do. One last bonus point: because we’re using Zaproxy – we also get a free security test for our app. Make sure to take a look at the alert tab – you might discover a security issue in you’re app!