This post is an overview of a mobile app MitM vulnerability I’ve found several times in the real world. I’ll explain how an attacker can exploit a vulnerable app’s broken SSL implementation and intercept cleartext HTTPS traffic – without the victim having installed any CA Certificates or accepting any additional untrusted certificates. I’ll first explain how this attack is made possible, then how it can be exploited, and finally how to create a setup to test for this flaw in your own research. (Versión en español muy pronto!)

Overview

The Scenario

An attacker can configure what is called a Rogue Access Point (or Rogue AP) in order to conduct a man-in-the-middle attack between a mobile app and its server. The attacker sets up a public WiFi network (the Rogue AP) in a place where there will be a lot of people who are likely to be looking for WiFi access on their devices, such as a coffee shop or an airport. The attacker can choose a deceiving name such as ‘MainStCafe_FreeWiFi’ or ‘Airport-Free-WiFi’ in order to appear more legitimate. Unfortunately, most people are unaware of the risks of connecting to an unsecured network, and can be easily tricked into connecting.

Now, the attacker is able to collect, intercept, and modify the traffic from the victim’s phone. When the victim is browsing the web, they will likely encounter a warning such as ‘Cannot verify the identity of XXX.com, this site may be impersonating XXX.com’. Mobile browsers and websites using HTTPS will be able to block or warn the user (although often people simply ignore these errors and click ‘Continue Anyway’ without a second thought). iOS apps, though, are supposed to simply refuse to send traffic in these scenarios.

However, in some cases, the attacker may be able to intercept cleartext HTTPS traffic from a victim’s phone. Obviously, this should not be able to happen; after all, we know that generally when we want to test a mobile app’s network activity we have to install Burp’s CA Certificate before we are able to capture any HTTPS traffic (assuming the app doesn’t use SSL pinning – if it does, that will require a little runtime manipulation). This is how it should work when SSL is implemented correctly. So how could the attacker be able to capture the victim’s decrypted HTTPS traffic – without the victim installing or accepting any additional certificates?

Root Cause

Sometimes, a developer will decide to create their own certificate chain verification logic, instead of using Apple’s provided libraries. Apple’s networking libraries have been developed over the years by experienced low-level engineers, and they have been tested rigorously. The chances of making a mistake when trying to build your own certificate handling code are much higher. Such a mistake can allow the attacker to trick the app into accepting an incorrect certificate impersonating the app’s server, if the app doesn’t properly validate certificate chains and their signatures. If done incorrectly, the entire app’s network security can break. And hence the attacker is able to intercept the victim’s HTTPS traffic, even though the victim does not have any special CA Certificates installed.

Impact

While this attack is localized to the area the attacker has set up their Rogue AP, and depends on one or more of the apps the victims use having this flaw, it works in the attacker’s favor in a few ways.

  • First, the attacker is able to cast a net, instead of having to target a specific individual – even if only a few people connect to the Rogue AP, the attacker’s odds of success are higher.
  • Second, the attacker doesn’t need to know or collect any information in order to target the victim(s). For example, when attempting a MitM attack with a tool like Bettercap, the attacker first needs to find the victim’s IP address to target. That step is eliminated here.

Clearly, this type of attack could be disastrous for the end user – the attacker can intercept and read all of the traffic in cleartext – this can often include usernames, passwords, private messages, images, or payment information. They can also modify any requests on the fly, for example changing a message a user is sending to say something else. With a MitM position, the attacker can attempt to perform Client Side Injection (CSI) attacks, in which the attacker is able to inject code or perform an action on the user’s behalf. Examples of such CSI attacks include inserting malicious payloads (usually JavaScript) into the server’s responses to be forwarded to the user. These types of CSI are quite similar to XSS. Another form of CSI involves taking an involuntary action on behalf of the user (similar to CSRF).

Exploitation

Now, I will show you how to setup your own Rogue AP for testing purposes. Here’s what you will need:

  • A computer running macOS (While setting up a Rogue AP is doable on other OSes, since I am a Mac user I will only be showing this method)
  • An ethernet cable
  • Burp Suite (Free or Pro)
  • Your mobile device (I am using an iPhone)

0. Set Up Internet Sharing

On your Mac, go to ‘System Preferences > Sharing’.

On the left hand side of the window, you will want to look for ‘Internet Sharing’, and check that box. Now, on the right, you’ll want to select your ethernet connection from the drop-down, and then check ‘WiFi’ under ‘To Computers Using’. The proper configuration is shown below:

You’ll then be asked to configure your new WiFi network. Choose whatever you’d like for the name and password, and settings. Then click ‘OK’.

Now, you can confirm that everything is working correctly by seeing the usual WiFi/Network icon on the top status bar looks like this:

1. Set Up Port Forwarding

Next, we are going to setup port forwarding to direct our new Rogue AP’s traffic to our proxy (Credit to this post from AppSec Consulting for initially teaching me how to get this started).

First, you’ll need to find the IP address of your newly created connection. This will be a private IP address, of the format ‘192.168.2.X’.

Open up a terminal, and type

ifconfig

You’ll see quite a bit of output – the interface we’re looking for is usually at the bottom, and will be prefixed with ‘bridge’. In my case, it’s called ‘bridge100’ :

I can see that my IP is ‘192.168.2.1’, next to the ‘inet’ field.

Next, we need to create an Anchor file, configuring our rules for forwarding. Again in terminal, create a new Anchor file (note that you can name this file whatever you want, I chose to call it ‘rogue’):

sudo vi /etc/pf.anchors/rogue

Paste in these lines, replacing ‘bridge100’ with the name of your interface you got from the ‘ifconfig’ output:

rdr pass on bridge100 inet proto tcp from 192.168.2.0/24 to any port http -> 127.0.0.1 port 8080
rdr pass on bridge100 inet proto tcp from 192.168.2.0/24 to any port https -> 127.0.0.1 port 8080

These two lines are instructing our new interface to forward TCP traffic, both HTTP and HTTPS, to 127.0.0.1 port 8080 (which we will be setting up Burp to listen on). Now save and close the file.

Finally, we just need to add our new file to the default port forwarding configuration file.

sudo vi /etc/pf.conf

You’ll need to add two lines. First, look for the one that reads ‘rdr-anchor “com.apple/*”‘. Underneath that line, add:

rdr-anchor "rogue"

Next look for the line ‘load anchor “com.apple” from “/etc/pf.anchors/com.apple”‘. Underneath, add:

load anchor "rogue" from "/etc/pf.anchors/rogue"

And last, make sure that you have left an extra blank line at the end of the file (you will get a syntax error if you forget this). Now, your config file will look like this:

Save and exit vim, and now we are ready for the final step – enabling port forwarding.

In terminal again, run this last command (note that you’ll need to run this again to enable PF after a restart):

sudo pfctl -ef /etc/pf.conf

If you don’t see any error messages, you are good to go.

2. Set Up the Proxy

With our AP’s traffic being forwarded to Burp, Burp will attempt to intercept it and establish itself as a MitM. It will generate custom SSL/TLS certificates impersonating the host the app is trying to connect to, and attempt to serve it to the app.

Start up Burp with the default configurations. Head over to the Proxy tab, and to the Options tab from there. Under the first section, ‘Proxy Listeners’, Burp will already have a default listener set on localhost port 8080. The only thing we need to change here is our request handling settings. Select the default listener, and click ‘Edit’. Click on the ‘Request Handling’ tab – at the bottom of the dialog, you will see a checkbox titled ‘Support invisible proxying (enable only if needed)’. Check that box. Additionally, you may want to make sure that the setting under the ‘Certificate’ tab is set to generate per-host certificates, although this should be selected by default.

If you’ve set everything up correctly, your ‘Proxy Listeners’ box should look like this:

And finally, we are ready to start testing!

3. Exploit

On your iPhone, you should now be able to see and connect to your new WiFi network. Go ahead and do that.

One thing that is important to double check – make sure that you have removed the Port Swigger CA Cert from your device if you have installed it before. If you forget this step, you will get a lot of ‘false positives’, thinking you’ve found a vulnerable app without realizing that the app is actually fine (although it doesn’t use SSL pinning). In real life, typical victims aren’t going to be wandering around with a Burp CA Cert installed on their phones.

Now, you can double check that everything is working properly by opening Safari on your iPhone, and navigating to an HTTP URL. Make sure you have turned on proxy intercept on Burp first! For example, you can go to ‘http://example.com’. If you’ve followed the steps correctly, you should see the request intercepted in Burp.

And finally, you can begin testing out apps for this vulnerability. Most apps will simply refuse to make any connections, as they should. Occasionally, they will display an alert to the user that the connection is insecure while they block the traffic. If you get lucky, you may find a vulnerable app that does send it’s traffic, with sensitive information inside! Here is a request from such a vulnerable app (redacted since it’s part of a private bounty program – If I can get permission to disclose, I will update this post with more details!):

Happy hunting!

Special shoutout to @ivRodriguezCA for helping me explain the root cause of this bug in the best way possible – check out his fantastic security blog too!