Skip to content

Threat detection

Tomas Psota edited this page Jun 3, 2024 · 32 revisions

FreeRASP performs several security checks to detect potential threats to the application during its runtime. Each covers a particular attack vector, and the developers (business owners) can choose how to respond to the incidents on their own. Developers can implement an application to kill itself, send a warning to the user, fetch the incident's details, or ignore it entirely.

To help choose an appropriate response, we briefly explain the available checks. Please note that proper response depends heavily on application security requirements and use cases.

Detecting rooted or jailbroken devices

// Root detection on Android
override fun onRootDetected() {
    TODO("Not yet implemented")
}

// iOS jailbreaking detection
case jailbreak

// Flutter root and jailbreak detection
onPrivilegedAccess: () => print("Privileged access")

// Cordova root and jailbreak detection
privilegedAccess: () => {
    // Place your reaction here
}

// React Native root and jailbreak detection
privilegedAccess: () => {
    // Place your reaction here
}

// Capacitor root and jailbreak detection
privilegedAccess: () => {
    // Place your reaction here
}

Rooting/jailbreaking is a technique of acquiring privileged control over the operating system of an Android/iOS device. While most users root their devices to overcome the limitations put on the devices by the manufacturers, it also enables those with malicious intent to abuse privileged access and steal sensitive information. Many different attack vectors require privileged access to be performed. Tools such as Magisk or Shadow can hide the privileged access and are often used by attackers.

FreeRASP uses various checks to detect whether the device is rooted or jailbroken. It detects not only rooted/jailbroken devices but also looks for the presence of their hiders (e.g., Magisk, Shad0w).

From our data, around 0.5% - 1% of devices have traces of rooting and jailbreaking. Keep that in mind when choosing the appropriate reaction type.

Recommended action: Notify users that their device is insecure and log the event on your BE. Some of the applications (mostly banking) are even killed upon this incident.

Emulator detection

// Android emulator check
override fun onEmulatorDetected() {
    TODO("Not yet implemented")
}

// iOS simulator detection
case simulator

// Flutter emulator and simulator detection
onSimulator: () => print("Simulator")

// Cordova emulator and simulator detection
simulator: () => {
    // Place your reaction here
}

// React Native emulator and simulator detection
simulator: () => {
    // Place your reaction here
}

// Capacitor emulator and simulator detection
simulator: () => {
    // Place your reaction here
}

Running an application inside an emulator/simulator allows an attacker to hook or trace program execution. For applications running inside an emulator, it is easy to inspect the system's state, reset it to a saved image, or monitor how the app operates. Keep in mind that not every emulator/simulator usage means an ongoing potential threat for the application.

Recommended action: Notify users that their device is insecure and log the event on your BE. Some of the applications (mostly banking) are even killed upon this incident.

Hook detection

// Android hook check
override fun onHookDetected() {
    TODO("Not yet implemented")
}

// iOS hook detection
case runtimeManipulation

// Flutter hook and runtime manipulation detection
onHooks: () => print("Hooks")

// Cordova hook and runtime manipulation detection
hooks: () => {
    // Place your reaction here
}

// React Native hook and runtime manipulation detection
hooks: () => {
    // Place your reaction here
}

// Capacitor hook and runtime manipulation detection
hooks: () => {
    // Place your reaction here
}

The application can be analysed or modified even though its source code has not been changed, applying a technique known as hooking. This technique can be used to intercept system or application calls and then modify them. An attacker can exploit this by inserting new (often malicious) code or by altering existing one to obtain personal client data. The most well-known hooking frameworks are Frida, Xposed, or Cydia Substrate.

Recommended action: Notify users that their device or app is insecure. In some cases, it is recommended to even kill the application.

App tampering detection

// Android tampering
override fun onTamperDetected() {
    TODO("Not yet implemented")
}

// iOS signature
case signature

// Flutter tampering and signature detection
onAppIntegrity: () => print("App integrity")

// Cordova tampering and signature detection
appIntegrity: () => {
    // Place your reaction here
}

// React Native tampering and signature detection
appIntegrity: () => {
    // Place your reaction here
}

// Capacitor tampering and signature detection
appIntegrity: () => {
    // Place your reaction here
}

Every application can be easily modified and then resigned by an attacker. This process is known as application repackaging. There may be many reasons for application repackaging, whether it's adding new code, removing app protections, or bypassing app licensing. A modified/tampered application is often distributed using third-party stores or other side channels.

FreeRASP uses various checks to detect whether the application was tampered (e.g., changed package name, signing hash).

Make sure, that you have integrated freeRASP correctly (e.g., signing certificate hash), otherwise this check might be triggered very often.

Recommended action: Kill the application.

Debugger detection

// Android debugger detection
override fun onDebuggerDetected() {
    TODO("Not yet implemented")
}

// iOS debugger detection
case debugger

// Flutter
onDebug: () => print("Debugging")

// Cordova
debug: () => {
    // Place your reaction here 
}

// React Native
debug: () => {
    // Place your reaction here 
}

// Capacitor
debug: () => {
    // Place your reaction here 
}

While most developers use debuggers to trace the flow of their program during its execution same tool can be attached to an application in an attempt to reverse engineer, check memory values, and steal confidential information. This method looks for specific flags to determine whether the debugger is active and offers the option to disable it.

Recommended action: Kill the application.

Detecting unofficial installation

// Android
override fun onUntrustedInstallationSourceDetected() {...}

// iOS
case unofficialStore

// Flutter
onUnofficialStore: () => print("Unofficial store")

// Cordova 
unofficialStore: () => {
    // Place your reaction here 
}

// React Native
unofficialStore: () => {
    // Place your reaction here 
}

// Capacitor
unofficialStore: () => {
    // Place your reaction here 
}

Users can share a copy of the application on unofficial stores or various pirate forums. While some users download these copies to avoid paying for the product, they can include unknown and possibly dangerous modifications. Verifying an official installation consequently protects both the users and the owner. This reaction is also triggered, if you install the application through alternative ways like unofficial store or Xcode build.

Recommended action: Notify users that the application is installed from unofficial store. In some cases, it is recommended to even kill the application.

Define alternative supported stores

If you want to define which applications can install the application, insert its package name in the supportedAlternativeStores (or supportedStores on Flutter) parameter. If you publish on Google Play, Huawei AppGallery, App Store (iOS), and TestFlight (iOS), you don't need to assign anything, as they are already supported out of the box.

Store / Distribution method Package name Notes
App Store (iOS) Included by default, no action needed
TestFlight (iOS) Included by default, no action needed
Google Play Included by default, no action needed
Huawei AppGallery Included by default, no action needed
Firebase App Distribution dev.firebase.appdistribution
Samsung Galaxy Store com.sec.android.app.samsungapps Common on Samsung devices
Vivo App Store com.vivo.appstore Common on Vivo devices
HeyTap com.heytap.market Common on Realme and Oppo devices
Oppo App Market com.oppo.market Common on Oppo devices
GetApps com.xiaomi.mipicks Common on Xiaomi, Redmi and POCO devices

The application can also be installed by "cloning" apps, which users employ to transfer apps between devices. The following list comprises popular examples of such apps. By default, freeRASP categorizes them as installations from unofficial store .

Mover / Cloner app Package name
Mi Mover (Xiaomi) com.miui.huanji
Phone Clone (Huawei) com.hicloud.android.clone
Samsung Smart Switch com.sec.android.easyMover
Samsung Cloud for Wear OS com.samsung.android.scloud
OPPO Clone Phone com.coloros.backuprestore
EasyShare (Vivo) com.vivo.easyshare
Clone Phone (OnePlus) com.oneplus.backuprestore
SHAREit (Lenovo) com.lenovo.anyshare.gps
SHAREit Lite shareit.lite
ShareMe (Xiaomi) com.xiaomi.midrop
MIUI Backup (Xiaomi) com.miui.backup
Phone Clone (Honor) com.hihonor.android.clone

Finally, it's very common application gets installed through browser, file manager, cloud storage or various messaging apps. By default, freeRASP categorizes them as installations from unofficial store.

Device binding detection

// Android device binding check
override fun onDeviceBindingDetected() {
    TODO("Not yet implemented")
}

// iOS device binding methods
case deviceChange
case deviceID

// Flutter 
// device binding and device change detection
onDeviceBinding: () => print("Device binding")

// device ID 
onDeviceID: () => print("Device ID")  // iOS only

// Cordova 
// device binding and device change detection
deviceBinding: () => {
    // Place your reaction here
}

// device ID 
deviceID: () => {  // iOS only
    // Place your reaction here 
}

// React Native 
// device binding and device change detection
deviceBinding: () => {
    // Place your reaction here
}

// deviceID
deviceID: () => {  // iOS only
    // Place your reaction here 
}

// Capacitor 
// device binding and device change detection
deviceBinding: () => {
    // Place your reaction here
}

// deviceID
deviceID: () => {  // iOS only
    // Place your reaction here 
}

Device binding is attaching an application instance to a particular mobile device. This method detects a transfer of an application instance to another device. A new install of the application (e.g. in case of buying a new device and transfer the apps) is not detected.

The deviceID detects, whether the device identifier has been changed. It is triggered after reinstallation of the application if there are none other applications from the same vendor installed. The value can also change when installing test builds using Xcode or when installing an app on a device using ad-hoc distribution.

Recommended action: Log the event on your BE and react to it if you need to have an instance attached to a particular mobile device (e.g., activation scenarios), otherwise ignore it.

Missing obfuscation detection (Android devices only)

// Android
override fun onObfuscationIssuesDetected() {
    TODO("Not yet implemented")
}

// Flutter
onObfuscationIssues: () => print("Obfuscation issues")

// Cordova
obfuscationIssues: () => {
    // Place your reaction here
},

// React Native
obfuscationIssues: () => {
    // Place your reaction here
},

// Capacitor
obfuscationIssues: () => {
    // Place your reaction here
},

The freeRASP SDK contains public API, so the integration process is as simple as possible. Unfortunately, this public API also creates opportunities for the attacker to interrupt freeRASP SDK operations or modify the custom code in threat callbacks. All internal freeRASP classes are already obfuscated, so it is simple to distinguish freeRASP sources from the rest of the application code during the static analysis. In order for freeRASP to be as effective as possible, it is highly recommended to apply obfuscation to the final package/application, making the public API more difficult to find and also to make it partially randomized for each application so it cannot be automatically abused by generic hooking scripts.

Please follow the integration guide of your platform for more information about how to obfuscate the app.

Recommended action: Use this callback during the development process to ensure that the app is obfuscated.

Secure Hardware detection (Keystore/Keychain secure storage check)

// Android Keystore
override fun onHardwareBackedKeystoreNotAvailableDetected() {
    TODO("Not yet implemented")
}

// iOS Secure Enclave
case missingSecureEnclave

// Flutter HW backed keystore not available and missing secure enclave detection
onSecureHardwareNotAvailable: () => print("Secure hardware not available")

// Cordova HW backed keystore not available and missing secure enclave detection
secureHardwareNotAvailable: () => {
    // Place your reaction here
}

// React Native HW backed keystore not available and missing secure enclave detection
secureHardwareNotAvailable: () => {
    // Place your reaction here
}

// Capacitor HW backed keystore not available and missing secure enclave detection
secureHardwareNotAvailable: () => {
    // Place your reaction here
}

The Secure Enclave and the Android Keystore system make it very difficult to decrypt sensitive data without physical access to the device. In that order, these keys need to be stored securely. FreeRASP checks if the keys reside inside secure hardware.

Recommended action: Ignore the callback or log the event to your BE.

Passcode

// Android lock check
override fun onUnlockedDeviceDetected() {
    TODO("Not yet implemented")
}

// iOS lock check
case passcode

// Flutter unlocked device and passcode detection
onPasscode: () => print("Passcode not set")

// Cordova unlocked device and passcode detection
passcode: () => {
    // Place your reaction here
}

// React Native unlocked device and passcode detection
passcode: () => {
    // Place your reaction here
}

// Capacitor unlocked device and passcode detection
passcode: () => {
    // Place your reaction here
}

Saving any sensitive data on a device without a lock / passcode makes them more prone to theft. With no user authentification device can be accessed and modified with minimal effort. FreeRASP checks if the device is secured with any type of lock.

Recommended action: Log the event on your BE or react to it if you need users to have a screen lock set up, otherwise ignore it.

System VPN

// Android system VPN detection
override fun onSystemVPNDetected() {
    TODO("Not yet implemented")
}

// iOS system VPN detection
case systemVPN

// Flutter system VPN detection
onSystemVPN: () => print("System VPN detected")

// Cordova system VPN detection
systemVPN: () => {
    // Place your reaction here
}

// React Native system VPN detection
systemVPN: () => {
    // Place your reaction here
}

// Capacitor system VPN detection
systemVPN: () => {
    // Place your reaction here
}

Detecting a running VPN service on mobile devices is critical for security-sensitive applications, as it can indicate potential privacy and security risks. VPNs can obscure the user’s actual IP address and route data through servers potentially under external control, which might interfere with geographical restrictions and bypass network security settings intended to protect data integrity and confidentiality. Such anonymising features could be exploited to mask illicit activities, evade compliance controls, or access services from unauthorised regions. FreeRASP checks whether the system VPN is enabled.

Recommended action: Log the event on your BE

Developer Mode (Android devices only)

// Android Developer mode detection
override fun onDeveloperModeDetected() {
    TODO("Not yet implemented")
}

// Flutter Developer mode detection
onDevMode: () => print("Developer mode detected")

// Cordova Developer mode detection
devMode: () => {
    // Place your reaction here
}

// React Native Developer mode detection
devMode: () => {
    // Place your reaction here
}

// Capacitor Developer mode detection
devMode: () => {
    // Place your reaction here
}

Android developer mode allows deeper system access and debugging capabilities that can bypass app security measures. Developer mode can enable settings that facilitate the installation of uncertified applications and the execution of potentially harmful code, posing significant risks to data integrity and app functionality. FreeRASP detects whether the developer mode is enabled.

Recommended action: Log the event on your BE