Memoirs of an API Hacker: Intercepting Encrypted Mobile Traffic to Hack a Bank's API Server
“Abashed the devil stood and felt how awful goodness is and saw Virtue in her shape how lovely: and pined his loss” -John Milton
In a recent penetration test of a large bank, I was able to transfer money to any account and change any customer's ATM debit card PIN with no authentication through the bank's API servers the mobile application communicates with. While I was able to successfully reverse engineer the Android app using MobSF, I wasn't so successful in finding the numerous POST and GET requests the mobile app uses when communicating with the bank. A HTTP POST is a type of HTTP request that instructs the receiving web server to accept and store the contents found in the body of the HTTP request, often times a file upload or user input to the fields of a web form.
Thus began my adventures into finding a more creative way of finding the correct API calls manually by intercepting the traffic between my mobile phone and the bank's API server. Once I had all of the numerous strings snagged in mitmproxy, I was able to then load the POST requests complete with the expected HTTP header fields into Postman -- an API client capable of sending requests to an API server allowing the user to inspect the response for further analysis or debugging.
Wireshark is shown here in this article to provide evidence of the captured network traffic after successfully setting up my iMac to capture my iPhone’s traffic. Mitmproxy was used as the SSL person-in-the-middle (PITM) tool to decrypt the SSL traffic. While Wireshark can not be used to inspect SSL/TLS encrypted traffic leaving your phone, it is important to use in a penetration test to confirm the mobile app is not sending any sensitive data unencrypted over HTTP. Therefore, I’ve broken this article up into two approaches, one using Wireshark to inspect unencrypted HTTP traffic and another using mitmproxy for the attack I employed against the API server once I had the URIs.
This article explains how to intercept the traffic egressing an iPhone using a Mac. In my setup, I'm using an iPhone 11 Max Pro and iMac Pro 2017 running MacOS Catalina 10.15.2.
Step 1: Discover your phone's unique identifier. Before doing anything, you'll first want to make sure XCode is installed on your Mac. To do so, simply search for XCode in the Mac app store. Once XCode is installed, connect your iPhone to your Mac using a lightning cable and look for the Identifier for your phone as seen in my screenshot below in Figure 1.
Don't worry about having to manually write down the entire identifier as the field allows highlight for a copy/paste in the next step.
Step 2: Create the network interface for your iPhone on your Mac. Next you'll want to create the interface that we'll listen on with Wireshark. This is the network interface that all of the iPhone's network traffic will be transmitted over for you to listen on using Wireshark, tcpdump, or any other network sniffer of your choosing. List the network interfaces currently enabled on your system by starting Terminal in your app drawer and running ifconfig (Figure 2).
Step 3: Start the interface. Using rvictl, start the network interface allowing you to sniff the network traffic leaving your iPhone (Figure 3). This will create a new interface name called rvi0.
Step 4: Capture iPhone network traffic. By using Wireshark, you can confirm your Mac is seeing all of the ingress/egress traffic from your iPhone as well as determine if any sensitive data is being passed by the banking app in clear text over HTTP.
Next you'll want to start Wireshark to capture the traffic leaving the iPhone, making sure to select the new interface you created with rvictl to listen on (Figure 4). In the below screenshot, you can see the traffic between my iPhone and the API server indicating your new rvio interface is working.
You're not done. We'll want to now dig into any SSL/TLS encrypted traffic using mitmproxy.
Step 5: Install and run mitmproxy. Next, you'll want to download and install mitmproxy, a free, open source tool for intercepting, inspecting, and/or replaying SSL/TLS encrypted traffic. To install mitmproxy on Mac, it's quite simple with a command line utility called Homebrew. Once installed, use brew to install mitmproxy.
$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
$ brew install mitmproxy
Start your web browser on your iPhone and visit domain http://mitm.it and click on the iOS icon to install the certificate onto your device.
Simply start mitmproxy either using the -P flag or -T --host.
$ mitmproxy -T --host
Step 6: Set the proxy on your iPhone. Next, find out the IP address of your Mac that is running mitmproxy. Both your iPhone and host should be on the same wireless network. Set the proxy on your iPhone to the IP address and port number that mitmproxy is running on.
To do this:
Settings > Wi-Fi > [i] Info (for your wireless network) > Configure Proxy > Set to Manual
In the below screenshot, you'll see where I was able to now see the URIs in the encrypted SSL/TLS traffic (Figure 5). After clicking on one of the API POST requests, I was able to document what I needed to properly format my POST requests in Postman in the next step.
You're done. At this point you should be able to intercept and decrypt all SSL/TLS traffic between your mobile device and the API server so long as the app you're capturing the traffic from doesn't have any security functionality to crash the app if a proxy is set or use certificate pinning. Certificate pinning should be used in any sensitive app, which effectively maps a specific host with an expected X.509 certificate/public key to prevent person-in-the-middle attacks, such as what we are attempting to do here.
This effort all led up to the final results shown below allowing me to perform money transfers and change ATM debit card PIN codes for any bank customer without authentication (Figure 6).