# Pentesting Flutter mobile apps (Android)
Recently I had an opportunity to perform a penetration test of a mobile application created in [Flutter](https://flutter.dev) - a relatively new development framework created by Google. Flutter mobile applications are written in Dart. In this post I'll share some notes on the first steps I took when testing this application on Android:
* redirecting traffic to Burp (http.dart ignores system proxy settings, user certificates and Network Security Config),
* bypassing root detection.
If you want to try it yourself, I created a sample Flutter app [available here](https://github.com/lpilorz/flutter-app)
## Setting intercepting machine as a gateway
Because setting network proxy is not sufficient in this case, instead I set my Mac (IP 192.168.1.4) as a gateway for Android phone (IP 192.168.1.8). On the Mac:
> $ sudo sysctl -w net.inet.ip.forwarding=1
![](https://i.imgur.com/FliUaXu.png)
On the phone:
> ![](https://i.imgur.com/GD27JA7.png)
Now all the traffic goes through the intercepting Mac and is ready to be analysed with Wireshark/tcpdump/whatever. Based on analysis of the traffic generated by the Flutter application, let's redirect some of it to Burp Proxy.
## Redirecting traffic to Burp
Once the communication between the application and its server-side API is passing through the intercepting machine, it's easy to redirect specific connections to Burp:
> $ cat pfctl.txt
> rdr pass inet proto tcp from 192.168.1.8 to runic.pl port 443 -> 127.0.0.1 port 8443
>
> $ sudo pfctl -f pfctl.txt
>
> $ sudo pfctl -s nat
> rdr pass inet proto tcp from 192.168.1.8 to 37.187.60.243 port = 443 -> 127.0.0.1 port 8443
This redirects https traffic sent to runic.pl to Burp Proxy listening on 127.0.0.1:8443. In Proxy options, let's create a listener on port 8443 supporting invisible proxying:
> ![](https://i.imgur.com/Yiv6KGc.png)
Of course the application doesn't accept Burp Proxy SSL certificate as valid yet. There is a good post on fixing this in Android 7.0+ at [blog.ropnop.com](https://blog.ropnop.com/configuring-burp-suite-with-android-nougat/) - I won't repeat it here. You have to use the first method (installing Burp Proxy certificate as a system-level CA), because http.dart in Flutter ignores Network Security Config. This means a rooted device is needed.
Once this is done, all is ready to start testing HTTP traffic... unless there is root detection in place.
## Bypassing root detection
There are currently three root/jailbreak detection packages available for Flutter:
* https://pub.dev/packages/flutter_jailbreak_detection
* https://pub.dev/packages/root_checker
* https://pub.dev/packages/trust_fall
In the test app above I used the first one. After using dex2jar on the test app's APK and loading the generated jar file in JD-GUI, it's quite easy to find the class responsible for root detection on Android:
> ![](https://i.imgur.com/BwptDeL.png)
I used Frida to overload isRooted() method. The script is short:
```
console.log("Loading flutter_jailbreak_detection bypass...");
setImmediate(function() {
Java.perform(function () {
var root = Java.use("com.scottyab.rootbeer.RootBeer");
root.isRooted.overload().implementation = function() {
console.log("isRooted() called, returning false");
return false;
}
});
});
```
Once frida-server is running on Android device, let's run the script:
> $ frida -U -f pl.runic.ip -l frida-flutter-jailbreak-detection-bypass.js
> ![](https://i.imgur.com/LvbbdBD.png)
That's it - the app runs on a rooted device and the traffic passes through Burp - let's start testing!
---
If it helps you in any way, the Frida scripts for flutter_jailbreak_detection and root_checker bypasses are on Github:
* https://github.com/lpilorz/flutter-app/blob/master/frida-flutter-jailbreak-detection-bypass.js
* https://github.com/lpilorz/flutter-app/blob/master/frida-root-checker-bypass.js
I didn't check trust_fall plugin, but it uses RootBeer as the first one above, so I guess the script should work too.
---
2019-06-08 [@runicpl](https://twitter.com/runicpl)