Another Devlog

Intercepting Http Calls With Burpsuite and Flutter

In this blog post, I will try to explain to the best of my abilities how to utilize burpsuite to intercept HTTP (API) network calls requested by apps made in Flutter, why? Because I personally struggled with this and I do hope that someone stumbles upon this post and finds it helpful. I will go over 2 approaches:

  1. using an iOS and macOS devices (a simpler case)
  2. using a vpn server (and in my case Fedora)

Context

You can skip this section if you are aware of the problem and tools. To first give context about the tools and some background about the issue, I will start with burpsuite. Burpsuite is a software typically used for security assessment and penetration testing of mobile and web applications, it offers a lot of useful tools to test and find vulnerabilities like the tool we are interested in which is the HTTP interceptor, which allows the tester to capture and modify requests before reaching the target APIs. In order for HTTP capturing to work, burpsuite sets up a local reverse proxy and instructs the user to download and trust a certificate allowing for https traffic to be decrypted and viewed by burpsuite before redirecting it to the target.

Flutter is a cross-platform development framework developed by google that uses Dart as a programming language. It allows developers to type code in dart once and run on iOS, Android, Web, and Desktop. Although it is an impressive framework, it seems to have a fundamental issue with its standard library implementation for a http client (it’s not a bug, it’s a feature), where dart:io seems to ignore system level proxy settings. This means that instead of making a request through burpsuite, it simply says no and goes directly to the main target. If I am not mistaken, there is a work around for this which developers need to implement as part of their project, which seems like a lot won’t do.

Requirements

To get you prepared first before diving into the 2 approaches, here is what is required from you:

for both approaches you obviously need burpsuite downloaded, mobile device with burp’s certificate installed and trusted, and excitement or the pressure of having to get a task done in time!

It goes without saying, you should definitely skip to the approach you will be using.

Using MacOS and IOS

To start the simpler approach, if you are running a full apple setup, apple actually makes this easier for you by using their internet sharing feature. Let’s start with your burp’s proxy settings, assuming you already have a project started / created go to:

Proxy > Proxy Settings > Select a Proxy from Proxy Listeners > Edit

this is purely dependent on your set up, I usually prefer to do the following

burp_binding burp_request

with these 2 settings set up, we jump to your iOS and macOS settings, starting with macos, you will need to enable internet sharing for your iOS device by first connecting your iOS device, then going to

Mac Settings -> Sharing -> Internet Sharing

Then enable it for iphone USB, with this setting enabled you will no longer need wifi or cellular to be on, so turn them off as well on your iOS device.

Now to enable proper routing to burpsuite you need to create a packet filter, the filter basically lets all TCP traffic coming from any source route going to any destination route on bridge100 (your iOS device connection) interface to go through localhost on port 8080 (the port set in burpsuite listener).

To do that first create a file called pf.rules (can be called anything), that has the filter that we just described:

rdr pass on bridge100 inet proto tcp from any to any -> 127.0.0.1 port 8080

and then we need to apply this filter and enable ip forwarding on the macOS by running these 2 commands:

sudo pfctl -f pf.rules
sudo sysctl -w net.inet.ip.forwarding=1

congratulations! you should be able to now start the flutter application you are testing and viewing HTTP network calls requested by it.

Using a hosted VPN Server

To give you a heads up, this has some similarities with the macOS approach but it took more effort from my side due to Docker overriding ip rules with its own (especially FORWARD rules), which took me through a different rabbit hole…. However, I did set up 2 scripts that basically enabled me to start / stop this process especially since I am not using burpsuite or the hosted vpn server all the time.

To start with, let us first set up an openvpn server on your host machine, to keep it simple we can use openvpn-install.sh and running it to install and start the server.

wget https://git.io/vpn -O openvpn-install.sh
sed -i "$(($(grep -ni "debian is too old" openvpn-install.sh | cut  -d : -f 1)+1))d" ./openvpn-install.sh
chmod +x openvpn-install.sh
sudo ./openvpn-install.sh

I followed these configurations (mostly the defaults):

The rest did not matter that much, so choose what suits your situation best. After running openvpn-install.sh, you should have an interface defined (typically tun0) for your openvpn server, you can verify by simply running ifconfig. This set up will also provide a client configuration file (something like client.ovpn, or whatever you have named it in the set up process)

Now lets set up your phone, should be fairly simple, all you need to do is install the client configuration file created and download the openvpn client app on your device. The github gist referenced below offers a simple way, by just running a python http server that will let you download the file:

sudo python3 -m http.server 8080 --directory /PATH_TO_CLIENT_CONFIGURATION_FILE

You can then open your mobile’s browser and go to your machines IP address and download YOUR_FILE.ovpn. Open the client file in OpenVPN Connect app and set up your connection. Test connect to ensure everything is working correctly, this should simply give you a connected status, your device might not have internet connection depending on your firewall rules so don’t panic yet.

Now lets jump to burpsuite and do the same as the macOS section, here are the steps again (assuming a project is already set up):

Proxy > Proxy Settings > Select a Proxy from Proxy Listeners > Edit

this is purely dependent on your set up, I usually prefer to do the following

burp_binding burp_request

Finally the bash script that will apply a network routing rule such that requests with a destination port 443 (https) and port 80 (http) on tun0 get routed through your burp proxy

#!/bin/bash
if [ "$EUID" -ne 0 ]; then
  echo "This script must be run with sudo or as root." >&2
  exit 1
fi

echo "Setting up all ip rules for sniffing"

service openvpn-server@server start
iptables -P FORWARD ACCEPT
iptables -t nat -A PREROUTING -i tun0 -p tcp --dport 443 -j DNAT --to-destination YOUR_MACHINES_IP:BURP_PORT
iptables -t nat -A PREROUTING -i tun0 -p tcp --dport 80 -j DNAT --to-destination YOUR_MACHINES_IP:BURP_PORT

update the script to match your setup, call the bash script what ever you want and then run:

sudo ./YOUR_SCRIPT.sh

congratulations! you should be able to now start the flutter application you are testing and viewing HTTP network calls requested by it. In case you are done with you are testing you can just turn things off and reseting rules by creating and running this script:

#!/bin/bash
if [ "$EUID" -ne 0 ]; then
  echo "This script must be run with sudo or as root." >&2
  exit 1
fi

firewall-cmd --reload
service openvpn-server@server stop

In this case I am running Fedora, reloading the firewall will reset the ip rules, you can do the same with ufw by running:

sudo ufw reload

Conclusion

I hope this post covered all the requirements, do not hesitate to reach out to me for any issues or comments that you might have, I am more than happy to hear them out!

A special thanks to these posts / references that have helped me figure out how to achieve this.

#Flutter #Burp Suite #Intercept Http #Mobile Security #Vpn #Macos #Ios