Why Flutter apps need specialised pentesting

Most pentest vendors treat Flutter apps like standard native Android apps. They run MobSF, check for a few common misconfigurations, and call it done. This misses the Flutter-specific attack surface entirely. The Dart runtime, platform channel communication, Flutter's own rendering engine, and the specific local storage libraries used in Flutter apps all require dedicated testing tools and techniques.

We have tested Flutter-based fintech apps from some of Nigeria's fastest-growing startups — digital banks, payment platforms, POS aggregators, and lending apps. The same vulnerability patterns appear across the ecosystem.

What we test in a Flutter penetration test

Dart binary analysis

Flutter compiles Dart to native ARM code, but function names and string constants are often preserved in the binary. We use tools like reFlutter, Blutter, and Doldrums to recover the app's class structure, API endpoint URLs, encryption key material, and business logic. Even without full decompilation, the recovered symbols reveal the app's architecture and attack surface.

Platform channel interception

Flutter communicates with native Android/iOS functionality through platform channels — MethodChannels, EventChannels, and BasicMessageChannels. We intercept these channels using Frida to observe and manipulate the data flowing between the Dart isolate and native code. This reveals biometric authentication responses, cryptographic operations, and native plugin data.

Local storage security

We audit every local storage mechanism: SharedPreferences (plaintext), Hive (optional encryption), sqflite (SQLite, often unencrypted), flutter_secure_storage (Keystore/Keychain-backed), and cached HTTP responses. In Nigerian fintech apps, we consistently find BVN data, session tokens, and PIN hashes stored in SharedPreferences or unencrypted Hive boxes.

SSL pinning and network security

We test certificate pinning implementations including dio with custom certificate validation, http_certificate_pinning, and native-level pinning. Flutter's SSL pinning can be bypassed using reFlutter's traffic interception mode or by hooking the Dart SecurityContext. We verify whether your pinning implementation survives these bypass techniques.

Authentication and biometric flows

We test the local_auth plugin implementation for biometric bypass, PIN brute-forcing, session token handling, and token refresh logic. Common Flutter findings include biometric results that are only validated client-side, PINs that are hashed with weak algorithms (MD5/SHA1), and refresh tokens stored alongside access tokens in unencrypted storage.

Backend API testing

From the Dart binary analysis, we extract every API endpoint and test them for BOLA/IDOR, broken authentication, mass assignment, and business logic flaws. Flutter apps frequently expose admin-level API endpoints that are hidden from the UI but accessible in the compiled binary's string table.

Real findings from Flutter pentests

Critical

Transaction PIN stored in SharedPreferences as plaintext

A Nigerian mobile banking app stored the user's 4-digit transaction PIN in SharedPreferences — an unencrypted XML file readable by any app with root access or by anyone with physical access to a backup. The PIN was stored immediately after login and never cleared. Combined with the session token (also in SharedPreferences), an attacker who obtained a device backup could perform transactions without any additional authentication.

High

Biometric authentication bypass via platform channel hook

The app used the local_auth Flutter plugin for fingerprint login. By hooking the platform channel response using Frida, we intercepted the native biometric result and replaced it with a success response. The Dart code trusted the channel response without server-side verification. An attacker with a rooted device could bypass fingerprint authentication and access any account on that device.

High

Internal admin API endpoints discoverable in Flutter binary

Using Blutter to analyse the compiled Dart code, we recovered string constants containing API endpoint paths. Among them were /api/admin/users, /api/admin/transactions/reverse, and /api/admin/kyc/override. While these endpoints required admin authentication, their discovery allowed us to test them directly. The /kyc/override endpoint accepted admin-level Basic authentication with a weak default password that had never been changed.

Building a fintech app with Flutter? We test the attack surfaces that generic pentest vendors miss — Dart binary analysis, platform channel interception, and Flutter-specific storage vulnerabilities.

Book a Flutter Pentest

Flutter vs React Native: security comparison

Nigerian CTOs frequently ask us which framework is more secure. The honest answer: both have vulnerabilities, but the attack profiles differ:

Frequently asked questions

Is Flutter more secure than React Native for fintech apps?

Flutter compiles Dart to native ARM code (AOT compilation), which makes reverse engineering harder than React Native's JavaScript bundles. However, Flutter is not immune to attack. Dart symbols can be recovered, platform channels can be intercepted, and local storage is frequently misused. The security difference between Flutter and React Native is smaller than most developers assume — both require proper hardening and penetration testing.

Can Flutter apps be reverse engineered?

Yes. While Dart AOT compilation produces native ARM machine code (not readable like JavaScript), tools like reFlutter, Doldrums, and Blutter can recover function names, class structures, and string constants from Flutter binaries. This is enough for an attacker to understand your app's architecture, identify API endpoints, and find cryptographic implementations.

What local storage vulnerabilities do you find in Flutter apps?

The most common finding is sensitive data stored in SharedPreferences (Android) or UserDefaults (iOS), which are plaintext XML/plist files. We also find apps using Hive databases without encryption, storing session tokens in unprotected SQLite databases, and caching API responses containing PII in the app's temporary directory. The fix is to use flutter_secure_storage, which wraps the platform Keystore/Keychain.

How long does a Flutter penetration test take?

A Flutter mobile app pentest typically takes 2-3 weeks, covering both Android and iOS builds plus the backend API. We provide a fixed-price quote after a free scoping call. For apps with complex features like biometric payment, agent banking, or multi-wallet systems, we may recommend 3-4 weeks to ensure thorough coverage.

Related reading

Blog: Flutter Security Audit Checklist · React Native Penetration Testing · Certificate Pinning · Biometric Spoofing

Guides: Mobile App Pentesting Guide · OWASP for Fintech

Services: Penetration Testing · API Security Testing