# 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)