As many pentesters might be familiar with, application development frameworks are now commonly used in developing web or mobile applications, eliminating the need to write everything from scratch. The application framework handles most of the common development procedures.
Majority of the mobile application frameworks such as Flutter and React Native can be used to build iOS and Android applications with the same codebase. Additionally, the Flutter framework has built-in security features such as secure data storage, trusted authentication plugins, and transport security. This has increased its popularity among business owners, who are prioritizing the security of their applications.
Why Flutter Is Different
When performing penetration testingpenetration testing on iOS and Android applications, it is usually the case that the proxy settings on the mobile device is set to an intercepting proxy controlled by the tester, to allow for interception of the traffic submitted and received by the mobile application. This can be performed for HTTPS traffic by importing the intercepting proxy’s certificate as a trusted certificate authority into the mobile device.
Due to Flutter’s built-in security features, mobile applications developed using Flutter do not follow the proxy settings defined on the mobile device, and make use of its own certificate store. This poses a problem when testing such applications, as the traditional method of importing the certificate to intercept HTTP traffic will no longer work.
The remaining sections detail down the steps taken to circumvent this security feature, and allow for interception of the HTTP traffic, for a recent mobile engagement performed on a Flutter-based mobile application available on both Android and iOS.
The Android Method
The following items are the prerequisites to intercept the Android Flutter application traffic.
- ProxyDroid on Android
- Rooted Android Device
- libflutter.so file extracted from the APK file
The file location of the libflutter.so might be different on different mobile applications. Hence, it is recommended that all the APK files should be extracted to locate the libflutter.so file. For this instance, the libflutter.so file was located within split_config.arm64_v8a.apk.
The above screenshot is what you see before the import of the libflutter.so file. Initially, the Ghidra application was run on a VM machine with 2GB RAM, but this was not sufficient enough to analyze the 64-bit libflutter.so file. According to the Ghidra Installation Guide, the Ghidra application requires a minimum of 4GB RAM. In this instance, I observed that the Ghidra application worked better with a minimum of 8GB RAM.
Based on the blog post mentioned in blog.nviso.eu, it was understood that the magic number 390 or 0x186 should be searched within the libflutter.so file via Ghidra as shown in the screenshot below. These magic numbers are used to locate where the OPENSSL_PUT_ERROR macro was called.
It was observed that no function name was indicated within the mov w3, #0x186 instruction. Therefore, further investigation should be performed by checking the decompiled function. The following screenshot shows the function FUN_006873d4 that was discovered in the mov w3, #0x186 instruction.
The following screenshot shows that the code within the function FUN_006873d4 was identical to the blog post mentioned in blog.nviso.eu. This function is thus where the OPENSSL_PUT_ERROR macro was called.
With the discovered function FUN_006873d4, it was possible to locate the address where the function was called.
It was understood that Ghidra uses 0x100000 as the base address. Therefore, the address discovered has to be subtracted from the Ghidra base address, which results in an offset of 0x5873d4.
The following Frida script was taken from blog.nviso.eu and the offset address was changed to bypass the SSL certificate validation.
The following output shows that the Flutter application’s function was successfully hooked with the following Frida command after the mobile application was launched.
After the Frida script is executed, the SSL certificate validation will be disabled. The following setting should be configured in ProxyDroid to intercept the HTTP traffic. In addition, the host and port parameters should also be configured with the Burp proxy listener IP address and port.
Based on observation, the base address of the OPENSSL_PUT_ERROR macro remained the same even after the Android devices were rebooted. In addition, Burp’s certificate was not required to be installed in the devices.
The following output shows that the HTTP/HTTPS request and response could be intercepted after running the hook.js Frida script.
The iOS Method
The following items are prerequisites to intercept the iOS application traffic.
- Kali machine
- OpenVPN server on Kali Machine
- OpenVPN client on iOS devices
- OpenSSH on iOS devices
- Jailbroken iPhone
Below is the diagram of how the iOS device, Kali VM machine, and Windows host were set up.
The iOS application that was developed via Flutter framework is not proxy aware. At this moment, iOS does not have applications that are similar to ProxyDroid, which can be used to redirect the traffic. Therefore, software such as OpenVPN should be installed in the iOS device to forward the HTTP traffic to the Burp proxy listener.
The following command was used to create the OpenVPN configuration file.
Once everything is set up, the OpenVPN configuration will be stored in Kali’s /root/ home directory. The following command was executed to start the OpenVPN service:
The OVPN configuration file that was stored in the /root/ home directory should be transferred to the iOS device. The OpenVPN should look similar to the screenshot before the configuration is imported to OpenVPN via the iOS devices.
Since the Kali VM machine was running on the NAT network adapter on the host machine, this means that the iOS devices would not be able to reach the Kali VM machine even within the same local area network. The workaround for the iOS devices to connect to the Kali VM machine’s OpenVPN server can be done by performing a reverse SSH port forwarding.
The following command can be executed from the Kali VM machine.
The following screenshot will be shown once the OpenVPN client has successfully connected to the Kali VM machine’s OpenVPN server.
The following commands are required to forward the iOS device HTTP traffic to the Burp proxy listener.
Do note that the following commands need to be issued whenever the Kali VM machine is rebooted as iptables rules do not persist.
For this instance, the following host machine IP address and port were configured to intercept the HTTP traffic.
In addition, the Support invisible proxying setting should also be enabled to allow non-proxy-aware clients to connect directly to the Burp proxy listener. It was observed that HTTP/HTTPS traffic could be intercepted after the Support invisible proxying setting was enabled.
After the above configuration has been made, it was possible to intercept the HTTP/HTTPS requests and responses. At the point of writing, it was not established why the OPENSSL_PUT_ERROR macro did not need to be hooked via Frida to achieve this, as per the example on the same Android application above.
There has been an upsurge of mobile applications developed via the Flutter framework in recent years. The security features are useful for developers, and will hinder traditional means of HTTP interception. However, this mechanism can still be bypassed by using tools such as Ghidra, ProxyDroid, iptables, Burp Suite and Frida. Hopefully, this will serve as a guide for prospective penetration testers to aid them in performing security testing.