Did you know that you can remove plugins dynamically from a Flutter app on Android?
During the implementation of a new feature on freeRASP (more about it here), we noticed that unregistering of plugins is possible using the FlutterEngine class. While it may seem unimportant, we decided to push the limits and explore potential attack vectors tthat could lead to the complete disabling of plugins from an external source. As a result, we conducted a small check of the plugin architecture security on Flutter. During this investigation, we discovered what we consider to be a serious problem.
Malicious plugin can remove other plugins at runtime
In Flutter, the FlutterEngine
class plays a crucial role in managing plugins. The generated GeneratedPluginRegistrant
class utilizes it to register plugins, which are then executed during startup. However, you have the flexibility to create your own plugins, acquire plugin instances, and even unregister plugins if needed. Therefore you can create plugin which removes other plugins:
// Standard callback for every Flutter plugin on Android
override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
// Let's remove them all
flutterPluginBinding.flutterEngine.plugins.removeAll()
}
If you have a class reference available, you can also selectively remove specific plugins:
override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
// Registering plugin
flutterPluginBinding.flutterEngine.plugins.remove(PoorPlugin::class.java)
}
This can even be also achieved directly from your appβs MainActivity
on Android (which extends FlutterActivity
) without the need for malicious plugin. By leveraging a bit of reverse engineering and code injection (similar to what we discussed in our recent article), you can achieve this:
// We are now at the app level
class MainActivity : FlutterActivity() {
// Standard Android lifecycle method - called when the app starts
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Removing all plugins
flutterEngine?.plugins?.removeAll()
}
}
How can you secure your app?
You can follow these measures if you want to make sure, that your code is protected againsts such attacks:
π Opt for reputable plugins β Choose well-maintained plugins with a considerable number of likes and positive user feedback.
π Inspect the pluginβs source code β Take a closer look at the codebase for any suspicious lines or potential vulnerabilities.
π Always obfuscate your application β Apply obfuscation techniques to make your app less readable and more obscure.
How do we secure our solution?
We faced the same issue at Talsec (link), while trying to hack our own products RASP+ and freeRASP which are critical security components and should have maximum resilience. Finding at least a partial solution was very important to us. In our RASP solution, AppiCrypt (coincidentally) solves this problem.
RASP (Runtime Application Self Protection)
Security technique that actively defends application by real-time controlling the security state of the device, integrity of the OS and App.
For context, AppiCrypt is an app attestation tool that protects your API by generating a cryptogram β information about the security state of the device, which is then used in the request header. The backend then checks the cryptogram to determine whether the device is compromised and decides whether to allow or deny the request.
Since the plugin cannot generate a cryptogram (CryptogramFailureException
is thrown due to the PlatformException
thrown by MethodChannel), the app can be considered untrustworthy. Without a cryptogram, you cannot make network requests backed by AppiCrypt.
Therefore, as a security measure, we can also add:
π Dynamically validate plugin functionality β If the plugin throws a PlatformException
, it can indicate that it is unable to communicate with the native side.
While it wonβt directly tell you that the plugin has been disconnected, it can give a hint that something unusual is going on.
Stay safe and code with confidence! πͺ
Written by Jaroslav NovotnΓ½ β Flutter developer