diff --git a/MOBILE_CLIENT/IOS/_HARDENING/IOS_DYNAMIC_FRIDA_PROTECTION_MISSING/description.md b/MOBILE_CLIENT/IOS/_HARDENING/IOS_DYNAMIC_FRIDA_PROTECTION_MISSING/description.md new file mode 100644 index 00000000..f970e460 --- /dev/null +++ b/MOBILE_CLIENT/IOS/_HARDENING/IOS_DYNAMIC_FRIDA_PROTECTION_MISSING/description.md @@ -0,0 +1,7 @@ +The application remained functional while running under Frida-based dynamic instrumentation on iOS. + +This indicates that the application does not detect, or does not meaningfully respond to, runtime instrumentation through Frida or Frida Gadget. An attacker who can instrument the application at runtime may observe internal state, alter control flow, intercept sensitive method calls, bypass local protections, and tamper with client-side security checks without modifying the IPA on disk. + +On iOS this is especially relevant for checks implemented only in the client, such as jailbreak heuristics, local anti-debug logic, feature gates, fraud signals, certificate-pinning helpers, or business rules enforced solely on-device. If Frida-based instrumentation is not detected, those controls can often be bypassed or observed dynamically. + +This is a resilience weakness rather than a complete trust boundary failure: client-side anti-instrumentation can raise attacker cost, but sensitive authorization and trust decisions should still be enforced server-side. diff --git a/MOBILE_CLIENT/IOS/_HARDENING/IOS_DYNAMIC_FRIDA_PROTECTION_MISSING/meta.json b/MOBILE_CLIENT/IOS/_HARDENING/IOS_DYNAMIC_FRIDA_PROTECTION_MISSING/meta.json new file mode 100644 index 00000000..293f9eb9 --- /dev/null +++ b/MOBILE_CLIENT/IOS/_HARDENING/IOS_DYNAMIC_FRIDA_PROTECTION_MISSING/meta.json @@ -0,0 +1,37 @@ +{ + "risk_rating": "hardening", + "short_description": "The application does not detect or respond to Frida-based dynamic instrumentation on iOS.", + "title": "Missing iOS Frida Instrumentation Detection", + "privacy_issue": false, + "security_issue": true, + "references": { + "OWASP MASVS - MASVS-RESILIENCE-4": "https://mas.owasp.org/MASVS/controls/MASVS-RESILIENCE-4/", + "OWASP MASTG - Hardening Against Runtime Hooking": "https://mas.owasp.org/MASTG/best-practices/MASTG-BEST-0041/", + "OWASP MASTG - Hardening Against Reverse Engineering Tools": "https://mas.owasp.org/MASTG/best-practices/MASTG-BEST-0048/", + "Frida - Gadget": "https://frida.re/docs/gadget/", + "Apple Developer - Establishing your app's integrity": "https://developer.apple.com/documentation/devicecheck/establishing-your-app-s-integrity" + }, + "categories": { + "OWASP_MASVS_RESILIENCE": [ + "MSTG_RESILIENCE_4" + ], + "OWASP_MASVS_v2_1": [ + "MASVS_RESILIENCE_4" + ], + "PCI_STANDARDS": [ + "REQ_6_2", + "REQ_6_3" + ], + "SOC2_CONTROLS": [ + "CC_7_1", + "CC_7_2" + ], + "HIPAA_CONTROLS": [ + "SECURITY212", + "SECURITY213" + ], + "OWASP_MOBILE_TOP_10": [ + "M7_2024" + ] + } +} diff --git a/MOBILE_CLIENT/IOS/_HARDENING/IOS_DYNAMIC_FRIDA_PROTECTION_MISSING/recommendation.md b/MOBILE_CLIENT/IOS/_HARDENING/IOS_DYNAMIC_FRIDA_PROTECTION_MISSING/recommendation.md new file mode 100644 index 00000000..608ab988 --- /dev/null +++ b/MOBILE_CLIENT/IOS/_HARDENING/IOS_DYNAMIC_FRIDA_PROTECTION_MISSING/recommendation.md @@ -0,0 +1,244 @@ +Implement Frida detection as a layered runtime resilience control, not as a single startup check. + +On iOS, the practical goal is not to make instrumentation impossible, but to reliably detect common Frida-based runtime tampering attempts and react safely during sensitive flows. A strong baseline is: + +1. Detect suspicious dynamic libraries, images, threads, ports, or runtime state associated with Frida or Frida Gadget. +2. Re-run checks during sensitive workflows instead of only once at launch. +3. Keep the detection logic in the native iOS layer, not only in Flutter, React Native, or other cross-platform code. +4. Move high-value trust decisions to the backend and combine local signals with Apple App Attest where feasible. + +Local Frida detection is a resilience signal, not a complete security boundary. A determined attacker may still patch or bypass client-side checks, so account actions, entitlements, payment approval, fraud decisions, and other high-value operations should still be verified server-side. + +## Native iOS (Swift / Objective-C) + +For native iOS applications, prefer multiple independent checks instead of one signature match. A single string like `frida` is easy to patch around. + +### Swift example: inspect loaded images for Frida-related artifacts + +This is useful for detecting Frida Gadget or other obviously named injected components loaded into the current process: + +```swift +import Foundation +import MachO + +enum FridaDetection { + private static let suspiciousImageMarkers = [ + "frida", + "gadget", + "gum-js-loop", + "frida-agent", + "frida-gadget", + ] + + static func hasSuspiciousLoadedImage() -> Bool { + let imageCount = _dyld_image_count() + + for index in 0.. Bool { + let socketFd = socket(AF_INET, SOCK_STREAM, 0) + if socketFd < 0 { + return false + } + defer { close(socketFd) } + + var address = sockaddr_in() + address.sin_len = UInt8(MemoryLayout.size) + address.sin_family = sa_family_t(AF_INET) + address.sin_port = port.bigEndian + address.sin_addr = in_addr(s_addr: inet_addr("127.0.0.1")) + + let result = withUnsafePointer(to: &address) { + $0.withMemoryRebound(to: sockaddr.self, capacity: 1) { + connect(socketFd, $0, socklen_t(MemoryLayout.size)) + } + } + + return result == 0 +} +``` + +Use this as one signal among several. Port-based detection alone is fragile because ports can be changed, blocked, or proxied. + +### Swift example: centralize the decision + +Combine multiple signals and run the check again before sensitive operations: + +```swift +import Foundation + +enum RuntimeProtection { + static func isInstrumentationDetected() -> Bool { + if FridaDetection.hasSuspiciousLoadedImage() is true { + return true + } + + if isLocalPortOpen(27042) is true { + return true + } + + if isLocalPortOpen(27043) is true { + return true + } + + return false + } +} +``` + +### Native iOS implementation advice + +- Run checks from native iOS code. Cross-platform code can call into native logic, but the actual detection should stay in Swift, Objective-C, or native libraries. +- Re-run detection before sensitive actions such as authentication completion, wallet access, payment approval, key export, or privileged API calls. +- Avoid keeping all detection strings or decision logic in one obvious place. +- Treat detection as a signal to fail closed for high-value flows, clear sensitive in-memory state, and report telemetry when appropriate. +- Test on real release builds, not only debug or simulator builds. + +## Apple App Attest for server-backed trust + +Use local Frida detection together with backend trust validation when possible. Apple App Attest gives the server stronger evidence about the app instance than a local-only runtime check. + +```swift +import CryptoKit +import DeviceCheck +import Foundation + +@available(iOS 14.0, *) +enum AppAttestClient { + static func generateKey() async throws -> String { + let service = DCAppAttestService.shared + guard service.isSupported else { + throw NSError(domain: "AppAttest", code: 1) + } + + return try await service.generateKey() + } + + static func attestKey( + keyIdentifier: String, + challenge: Data, + ) async throws -> Data { + let clientDataHash = Data(SHA256.hash(data: challenge)) + return try await DCAppAttestService.shared.attestKey( + keyIdentifier, + clientDataHash: clientDataHash, + ) + } +} +``` + +Use App Attest results on the server to gate high-value operations. Local anti-instrumentation checks should complement this, not replace it. + +## Flutter on iOS + +For Flutter, keep Frida detection in the native iOS host app and expose only a thin bridge to Dart. + +```dart +import 'package:flutter/services.dart'; + +class RuntimeProtection { + static const MethodChannel _channel = MethodChannel('app.runtime_protection'); + + static Future isInstrumentationDetected() async { + final bool? detected = await _channel.invokeMethod( + 'isInstrumentationDetected', + ); + return detected == true; + } +} +``` + +Swift side: + +```swift +import Flutter +import UIKit + +@main +@objc final class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + let controller = window?.rootViewController as? FlutterViewController + let channel = FlutterMethodChannel( + name: "app.runtime_protection", + binaryMessenger: controller!.binaryMessenger + ) + + channel.setMethodCallHandler { call, result in + guard call.method == "isInstrumentationDetected" else { + result(false) + return + } + + result(RuntimeProtection.isInstrumentationDetected()) + } + + return super.application( + application, + didFinishLaunchingWithOptions: launchOptions + ) + } +} +``` + +Flutter-specific advice: + +- Do not rely on Dart-only anti-instrumentation logic. +- Re-test the final signed `.ipa`. +- Keep the response to detection in native code for sensitive flows when possible. + +## React Native on iOS + +For React Native, place the actual detection logic in the native iOS host layer or a native module, and expose only a minimal JavaScript-facing API. + +```javascript +import { NativeModules } from 'react-native'; + +const { RuntimeProtection } = NativeModules; + +export async function isInstrumentationDetected() { + const detected = await RuntimeProtection.isInstrumentationDetected(); + return detected === true; +} +``` + +React Native-specific advice: + +- Keep the important checks outside JavaScript. +- Re-run the detection around sensitive workflows, not only during app boot. +- Avoid leaving verbose debug behavior in production builds that helps an attacker inspect the app state. + +## Capacitor and other hybrid iOS stacks + +For Capacitor or similar hybrid runtimes, implement Frida detection in the iOS host app or a native plugin and use the web layer only as a consumer of the result. + +## Additional hardening guidance + +- Use more than one detection path. Loaded-image checks, runtime heuristics, and backend integrity signals are stronger together than separately. +- Validate how the app behaves after detection. For high-risk actions, prefer blocking the action instead of only showing a warning. +- Keep analytics around detection events so repeated instrumented sessions can be correlated server-side. +- Periodically re-evaluate the implementation against current Frida and Frida Gadget workflows. diff --git a/MOBILE_CLIENT/IOS/_SECURE/IOS_DYNAMIC_FRIDA_PROTECTION_PRESENT/description.md b/MOBILE_CLIENT/IOS/_SECURE/IOS_DYNAMIC_FRIDA_PROTECTION_PRESENT/description.md new file mode 100644 index 00000000..40dc63b2 --- /dev/null +++ b/MOBILE_CLIENT/IOS/_SECURE/IOS_DYNAMIC_FRIDA_PROTECTION_PRESENT/description.md @@ -0,0 +1,5 @@ +The application detected and responded to Frida-based dynamic instrumentation on iOS. + +This indicates that the application includes runtime resilience controls intended to identify instrumentation through Frida or Frida Gadget and to react when those conditions are observed. In practice, this can raise attacker cost by making runtime observation, hook-based bypasses, and live tampering more difficult. + +This result is informative rather than absolute. Frida detection can improve resilience, but it does not guarantee resistance to all runtime tampering techniques, custom instrumentation builds, or bypasses. High-value trust decisions should still be enforced server-side. diff --git a/MOBILE_CLIENT/IOS/_SECURE/IOS_DYNAMIC_FRIDA_PROTECTION_PRESENT/meta.json b/MOBILE_CLIENT/IOS/_SECURE/IOS_DYNAMIC_FRIDA_PROTECTION_PRESENT/meta.json new file mode 100644 index 00000000..5ddd21f8 --- /dev/null +++ b/MOBILE_CLIENT/IOS/_SECURE/IOS_DYNAMIC_FRIDA_PROTECTION_PRESENT/meta.json @@ -0,0 +1,37 @@ +{ + "risk_rating": "secure", + "short_description": "The application detects and responds to Frida-based dynamic instrumentation on iOS.", + "title": "iOS Frida Instrumentation Detection Implemented", + "privacy_issue": false, + "security_issue": true, + "references": { + "OWASP MASVS - MASVS-RESILIENCE-4": "https://mas.owasp.org/MASVS/controls/MASVS-RESILIENCE-4/", + "OWASP MASTG - Hardening Against Runtime Hooking": "https://mas.owasp.org/MASTG/best-practices/MASTG-BEST-0041/", + "OWASP MASTG - Hardening Against Reverse Engineering Tools": "https://mas.owasp.org/MASTG/best-practices/MASTG-BEST-0048/", + "Frida - Gadget": "https://frida.re/docs/gadget/", + "Apple Developer - Establishing your app's integrity": "https://developer.apple.com/documentation/devicecheck/establishing-your-app-s-integrity" + }, + "categories": { + "OWASP_MASVS_RESILIENCE": [ + "MSTG_RESILIENCE_4" + ], + "OWASP_MASVS_v2_1": [ + "MASVS_RESILIENCE_4" + ], + "PCI_STANDARDS": [ + "REQ_6_2", + "REQ_6_3" + ], + "SOC2_CONTROLS": [ + "CC_7_1", + "CC_7_2" + ], + "HIPAA_CONTROLS": [ + "SECURITY212", + "SECURITY213" + ], + "OWASP_MOBILE_TOP_10": [ + "M7_2024" + ] + } +} diff --git a/MOBILE_CLIENT/IOS/_SECURE/IOS_DYNAMIC_FRIDA_PROTECTION_PRESENT/recommendation.md b/MOBILE_CLIENT/IOS/_SECURE/IOS_DYNAMIC_FRIDA_PROTECTION_PRESENT/recommendation.md new file mode 100644 index 00000000..adacc748 --- /dev/null +++ b/MOBILE_CLIENT/IOS/_SECURE/IOS_DYNAMIC_FRIDA_PROTECTION_PRESENT/recommendation.md @@ -0,0 +1 @@ +This entry is informative, no recommendations applicable.