Flutter Mobile Security: 5 easy steps to secure your app

A crucial component of information technology, mobile security guards gainst malware, cyberattacks, illegal access, and data leaks on smartphones, tablets, and other portable devices. Due to the widespread use of mobile devices in personal and professional settings, they frequently contain private/sensitive data, such as financial and business information, private messages, and photos. They are therefore “easy pickings” for cybercriminals.
In my day-to-day job, security has become a major foundation of our entire infrastructure, and I’ve had to implement a few strategies to ensure that our platforms and protocols are as secure as the current technology can offer.
Here are a few strategies that I would recommend when building a privacy- and security-focused mobile app in Flutter:
Root & Jailbreak checking
Rooting (Android) and Jailbreaking (iOS) give users superuser access to their mobile devices’ operating systems, allowing them to circumvent manufacturer limitations and make extensive modifications to system settings and configurations. While these methods give users more control over their devices and the opportunity to customize their software fully, they also undermine the security of such devices.
Malicious entities can take advantage of this state of reduced security and compromise the integrity of any app installed on such devices. A good example of this is “Man-in-the-Middle (MITM) Attacks.” Since compromised devices can have their network traffic intercepted more easily, attackers can exploit this lack of certain security layers (such as those that verify certificates) to intercept, modify, or redirect data transmitted to and from the device. This can be dangerous,, especially to basic or simple servers that do not have any further protection against such attacks.
How to mitigate:
We can use this https://pub.dev/packages/safe_device to check for root permission and make decisions based on the returned information. I went ahead and built a wrapper widget that builds UI conditionally depending on if the widget is rooted or not.
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:safe_device/safe_device.dart';
class RootChecker {
static Future<bool> get isDeviceRooted async {
final usbDebuggingCheck = await SafeDevice.usbDebuggingCheck;
final isSafeDevice = await SafeDevice.isSafeDevice;
return kReleaseMode && (usbDebuggingCheck || isSafeDevice == false);
}
static Widget rootedBuilder({
required Widget rootedView,
required Widget unRootedView,
}) {
return FutureBuilder<bool>(
future: isDeviceRooted,
builder: (context, snapshot) {
if (snapshot.hasData == false) {
return const Center(child: CupertinoActivityIndicator());
}
return switch (snapshot.data) {
false => UnRootedView(),
_ => RootedView(),
};
},
);
}
}
It is then used as follows:
...
MaterialApp(
...
home: RootChecker.rootedBuilder(
rootedView: const RootedUIPage(),
unRootedView: const SplashPage()
),
),
...
This ensures that the app never gets to run on rooted devices, reducing the risk of unwanted interactions with your app.
Certificate Pinning
Certificate pinning is a security technique used to ensure that a specific application communicates only with the designated server via HTTPS, and not through any intercepted connections. This is accomplished by associating a specific cryptographic certificate, typically the public key, with the server that the application expects to communicate with. By implementing certificate pinning, developers can prevent man-in-the-middle (MITM) attacks that exploit the vulnerabilities in the SSL/TLS protocols, which are used to secure network communications.
When employing certificate pinning, the application developer embeds the expected server certificate information directly into the program. When the app sends a network request, it compares the server-provided certificate against the pinned certificate’s information.
If there is a match, the connection will be established. If the certificates do not match, the connection is terminated to protect the user from possible MITM attacks.
Secure Local Storage
For mobile apps, storing data locally can be as important as storing them on a backend/remote database, because this can contain sensitive data about the user. So it is good practice to secure such data stored in local storage. A great way to do this is by utilizing the iOS keychain for iPhones and the Android Keystore for Android devices.
You can check out the following package to get started: https://pub.dev/packages/flutter_secure_storage
Package version Pinning
Package version pinning is a practice used in software development to ensure that a project consistently uses specific versions of dependencies. By pinning the version of a package, developers avoid the potential issues that may arise from automatic updates, such as breaking changes or compatibility problems. This practice enhances the stability and predictability of the application by maintaining a controlled environment. Version pinning is typically managed using the `pubspec.yaml` file in Dart projects, where exact versions of dependencies are specified, ensuring that the same versions are used across different development environments and builds.
Example:
name: example_project
description: An example Dart project with version pinning
version: 1.0.0
environment:
sdk: '>=2.12.0 <3.0.0'
dependencies:
flutter:
sdk: flutter
http: 0.13.4
provider: 5.0.0
json_annotation: 4.4.0
dev_dependencies:
flutter_test:
sdk: flutter
build_runner: 2.1.7
json_serializable: 6.1.4
flutter:
uses-material-design: true
Obfuscation and Shrinking
Obfuscation and shrinking in Flutter are techniques used to optimize the size and security of the application when building it for production.
Obfuscation
Obfuscation makes the application code harder to read and reverse-engineer. This process renames symbols in the compiled code, such as classes, methods, and variables, to make the code less human-readable, enhancing the application's security by making it more difficult for attackers to understand and modify the code.
Shrinking
Shrinking, also known as tree shaking, removes unused code and resources from the application. This process analyzes the code to determine which parts are not being used and eliminates them, reducing the overall size of the application. This leads to faster download times and improved performance on devices.
Enabling Obfuscation and Shrinking in Flutter
To enable obfuscation and shrinking in a Flutter project, you need to configure the build.gradle
file for your Android project and add specific flags to your build commands.
1. Edit the build.gradle
file:
Open the `android/app/build.gradle` file and add the following lines within the `android` block:
android {
…
buildTypes {
release {
…
minifyEnabled true // Enables code shrinking
shrinkResources true // Enables resource shrinking
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' // ProGuard configuration
}
}
}
2. Add ProGuard Rules:
Create or edit the proguard-rules.pro
file in the android/app
directory to include any necessary ProGuard rules. This file controls the obfuscation and optimization process.
3. Build the application:
When building the Flutter application for release, include the — obfuscate
and — split-debug-info
flags to enable obfuscation. The ` — split-debug-info` flag specifies the directory where the debug symbols will be stored.
flutter build apk - release - obfuscate - split-debug-info=/<project-name>/debug-info
Securing your Flutter mobile app doesn’t have to be a daunting task. By following these five easy steps, you can significantly enhance the security of your application and protect your users’ data.
Each step contributes to a robust security framework, from implementing proper authentication and encryption to using obfuscation and shrinking techniques. Remember, security is an ongoing process, so stay updated with the latest best practices and continuously monitor your app for potential vulnerabilities.
With these measures in place, you can confidently provide your users with a secure and reliable experience. Thank you for following along, and here’s to building safer mobile applications with Flutter! 🥂🥂
Stackademic 🎓
Thank you for reading until the end. Before you go:
- Please consider clapping and following the writer! 👏
- Follow us X | LinkedIn | YouTube | Discord
- Visit our other platforms: In Plain English | CoFeed | Differ
- More content at Stackademic.com