{securing}

Flutter Apps

Majid Hajian

mhadaily

More than 75% of mobile applications will fail basic security tests

https://www.pixelcrayons.com/blog/mobile-app-statistics/

Flutter Security Key Pillars

Identify

Detect

Protect

Respond

Recover

  • OWASP
  • OWASP Top 10
  • OWASP for Flutter
  • Modern Approach
    • RASP

Agenda

ME.dart

import 'package:flutter/material.dart';
MaterialApp(
   ThemeData(
        name: "Majid Hajian",
        location: "Oslo, Norway",
        description: '''
                Google Developer Expert
        	Passionate Software engineer, 
	        Community Leader, Author and international Speaker
         ''',
        main: "Head of DevRel at Invertase.io",
        homepage: "https://www.majidhajian.com",
        socials: {
          twitter: "https://www.twitter.com/mhadaily",
          github: "https://www.github.com/mhadaily"
        },
        author: {
          Pluralsight: "www.pluralsight.com/authors/majid-hajian",
          Apress: "Progressive Web App with Angular, Book",
          PacktPub: "PWA development",
          Udemy: "PWA development",
        }
        founder: "Softiware As (www.Softiware.com)"
        devDependencies: {
          tea: "Ginger", 
          mac: "10.14+",
        },
        community: {
          MobileEraConference: "Orginizer",
          FlutterVikings: "Orginizer", 
          FlutterDartOslo: "Orginizer",
          GDGOslo: "Co-Orginizer",
          DevFestNorway: "Orginizer",
          ...more
        }));

mhadaily

Find me on the internet by

Head of DevRel at Invertase

{OWASP}

Open Web Application Security Project

https://owasp.org/Top10/

https://owasp.org/www-project-mobile-top-10/

Web

Mobile

M1. Improper Platform Usage

  • Misuse of the iOS Touch ID feature
  • Incorrect use of the iOS Keychain
  • Requesting excessive or wrong platform permissions
  • Adhere to the platform development best practices and guidelines.

  • Use secure configuration and coding to harden the server side.

  • Restrict applications from transmitting user data.

  • Restrict file access permissions.

  • Encrypt and store data securely.

Examples:

Solutions:

Stay up to date

Latest Flutter stable

Latest libraries updates

Latest guidelines for publishing apps

Regularly checking security guidelines by flutter team 

https://docs.flutter.dev/security

Handle Permissions

https://pub.dev/packages/permission_handler

if (await Permission.contacts.request().isGranted) {
  // Either the permission was already granted before or the user just granted it.
}

// You can request multiple permissions at once.
Map<Permission, PermissionStatus> statuses = await [
  Permission.location,
  Permission.storage,
].request();
print(statuses[Permission.location]);

M2. Insecure Data Storage

  • Unencrypted storage / caching for storing sensitive data
  • Storing sensitive data in Shared preferences
  • encryption effectively
  • obfuscation and protection against buffer overflows & so on.
  • Avoid storing/caching data where feasible

Examples:

Solutions:

Handle sensitive

  • Usernames,
  • Authentication tokens,
  • Passwords,
  • Cookies,
  • Location data,
  • UDID/IMEI, Device Name,
  • Network Connection Name,
  • Debug information,
  • Personal Information (e.g., date of birth, address, Social, credit card data),
  • Application Data,
  • Stored application logs (e.g., for an Android App ADB logcat tool),
  • Cached application messages,
  • Transaction histories.

https://pub.dev/packages/flutter_secure_storage

 

Flutter Secure Storage provides API to store data in secure storage. Keychain is used in iOS, KeyStore based solution is used in Android.

https://pub.dev/packages/hive

 

Lightweight and blazing-fast key-value database written in pure Dart and strongly encrypted using AES-256.

Background snapshots protection

https://pub.dev/packages/secure_application

SecureApplication(
        onNeedUnlock: 
        (secure) => print(
            'need unlock maybe use biometric 
            to confirm and 
            then use sercure.unlock()'),
        child: MyApp(),
)

M3. Insecure Communication

  • Unencrypted data in transit 
  • Sending data as cleartext that can be intercepted by anyone checking the network
  • Use SSL/TLS certificates for secure transmission
  • Use signed and trusted CA certificates
  • Use encryption protocols
  • Implement encryption before SSL channel transmission

Examples:

Solutions:

Certificate pinning 

https://pub.dev/packages/http_certificate_pinning

 

Certificate pinning allows mobile applications to restrict communication only to servers with a valid certificate matching the expected value (pin). The connection is terminated immediately if communication is attempted with any server that doesn't match this "expected" value.

(MitM attacks)

openssl x509 -noout -fingerprint -sha256 -inform pem -in [certificate-file.crt]
// The Result is like:
// '59:58:57:5A:5B:5C:5D:59:58:57:5A:5B:5C:5D:59:58:57:5A:5B:5C:5D:59:58:57:5A:5B:5C:5D:59:58:57:5A:5B:5C:5D'
import 'package:http_certificate_pinning/secure_http_client.dart';
  
  // Uses SecureHttpClient to make requests
  SecureHttpClient getClient(List<String> allowedSHAFingerprints){
      final secureClient = SecureHttpClient.build(certificateSHA256Fingerprints);
      return secureClient;
  }

  myRepositoryMethod(){ 
    secureClient.get("myurl.com");
  }    
// Other client - backend 

import 'package:http_certificate_pinning/http_certificate_pinning.dart';
  
Future myCustomImplementation(String url, Map<String,String> headers, List<String> allowedSHAFingerprints) async {
  try{
    final secure = await HttpCertificatePinning.check(
      serverURL: url,
      headerHttp: headers,
      sha: SHA.SHA256,
      allowedSHAFingerprints:allowedSHAFingerprints,
      timeout : 50
    );

    if(secure.contains("CONNECTION_SECURE")){
      return true;
    }else{
      return false;
    }
  }catch(e){
    return false;
  }
}

M4. Insecure Authentication

  • Only client-side authentication
  • Rely on local authentication
  • Avoid local authentication methods. Instead, shift this responsibility to the server and download application data only after successful authentication.
  • Refrain from using vulnerable authentication methods (such as device identity), don’t store passwords locally, implement multi-factor authentication (MFA), disallow using all four-digit PINs as passwords where feasible, etc.

Examples:

Solutions:

Local Authentication

https://pub.dev/packages/local_auth

final List<BiometricType> availableBiometrics =
    await auth.getAvailableBiometrics();

if (availableBiometrics.isNotEmpty) {
  // Some biometrics are enrolled.
}

if (availableBiometrics.contains(BiometricType.strong) ||
    availableBiometrics.contains(BiometricType.face)) {
  // Specific types of biometrics are available.
  // Use checks like this with caution!
}

M5. Insufficient Cryptography

  • Improperly managing digital keys
  • Using deprecated encryption protocols
  • Bypassing built-in code encryption algorithms
  • Use robust cryptography algorithms
  • Avoid storing any sensitive data on the device whenever possible

Examples:

Solutions:

1- AES (Advanced Encryption Standard) Algorithm

2- Fernet Algorithm

3- Salsa Algorithm

& ...

 

  • Symmetric
  • Asymmetric

Use of Insecure and/or Deprecated Algorithms

  • RC2
  • MD4
  • MD5
  • SHA1

Secure developer identity

Any data that may expose developer identity needs to be encrypted. Encrypt sensitive files like key.jks & keystore.properties with GPG. Avoid keeping track of unencrypted sensitive data in your repository.

Encrypt your keys

https://pub.dev/packages/encrypt

import 'package:encrypt/encrypt.dart';

void main() {
  final plainText = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit';
  final key = Key.fromUtf8('my 32 length key................');
  final iv = IV.fromLength(16);

  final encrypter = Encrypter(AES(key));

  final encrypted = encrypter.encrypt(plainText, iv: iv);
  final decrypted = encrypter.decrypt(encrypted, iv: iv);

  print(decrypted); // Lorem ipsum dolor sit amet, consectetur adipiscing elit
  print(encrypted.base64); // R4PxiU3h8YoIRqVowBXm36ZcCeNeZ4s1OvVBTfFlZRdmohQqOpPQqD1YecJeZMAop/hZ4OxqgC1WtwvX/hP9mw==
}

https://pub.dev/packages/crypto

M6. Insecure Authorization

  • fails to verify users and grant permissions
  • Client-side authorization
  • Verify requests with the backend
  • Validate the roles and permissions of an authenticated user using the information with backend not the data on the device or what you have stored

Examples:

Solutions:

M7. Client Code Quality

  • Integrating a 3rd party library without checking code quality 
  • Relying on manual checking rather automated tools
  • Enforce good coding practices (come up with consistent pattern)

  • Perform static code analysis

  • Use automated tools to test memory leaks, buffer overflow, and code execution

Examples:

Solutions:

https://dart.dev/guides/language/effective-dart/design

M8. Code Tampering

  • a hacker modifies the app’s binary to include malicious content, install a backdoor
  • Implement anti-tamper techniques that prevent illicit apps from executing via the implementation of checksums, digital signatures, code hardening, and other validation methods.

Examples:

Solutions:

Rooting or Jailbreaking protection

https://pub.dev/packages/flutter_jailbreak_detection

import 'package:flutter_jailbreak_detection/flutter_jailbreak_detection.dart';

bool jailbroken = await FlutterJailbreakDetection.jailbroken;
bool developerMode = await FlutterJailbreakDetection.developerMode; // android only.

M9. Reverse Engineering

  • de-obfuscate the code using tools like IDA Pro and Hopper
  • Check if it’s possible to decompile the application
  • Ensure robust obfuscation (including metadata)
  • Use binary packaging to prevent attackers from decompiling code
  • Block debugging tools

Examples:

Solutions:

Obfuscation

https://docs.flutter.dev/deployment/obfuscate

 flutter build apk --obfuscate --split-debug-info=/project/debuginfo

 

Binary build 

https://docs.flutter.dev/resources/faq#run-android

M10. Extraneous Functionality

  • A developer may accidentally include a password as a comment in a hybrid app
  • Disabling 2-factor authentication during testing
  • Examine the app’s configuration settings to discover any hidden switches;
  • Verify that all test code is not included in the final production build of the app;
  • Examine all API endpoints accessed by the mobile app to verify that these endpoints are well documented and publicly available;
  • Examine all log statements to ensure nothing overly descriptive about the backend is being written to the logs;

Examples:

Solutions:

RASP - Runtime Application Self-Protection*

Static versus Dynamic Analysis

Hook

Root

Debugger

Emulator

Fingerprints

https://pub.dev/packages/freerasp

@override
void initState() {
  //  config
  callback = TalsecCallback(
  // For Android
  androidCallback: AndroidCallback(
    onRootDetected: () => print('root'),
    onEmulatorDetected: () => print('emulator'),
    onHookDetected: () => print('hook'),
    onTamperDetected: () => print('tamper'),
    onDeviceBindingDetected: () => print('device binding'),
    onUntrustedInstallationDetected: () => print('untrusted install'),
  ),
  // For iOS
  iosCallback: IOSCallback(
      onSignatureDetected: () => print('signature'),
      onRuntimeManipulationDetected: () => print('runtime manipulation'),
      onJailbreakDetected: () => print('jailbreak'),
      onPasscodeDetected: () => print('passcode'),
      onSimulatorDetected: () => print('simulator'),
      onMissingSecureEnclaveDetected: () => print('secure enclave'),
      onDeviceChangeDetected: () => print('device change'),
      onDeviceIdDetected: () => print('device ID'),
      onUnofficialStoreDetected: () => print('unofficial store')),
  // Common for both platforms
  onDebuggerDetected: () => print('debugger'),
  );
}

Security is progressive

Security Testing

https://mas.owasp.org/

Majid Hajian

@mhadaily

Slides and link to source code

slides.com/mhadaily

SVG icons credited to undraw.co