Malwarelytics for Apple

Malwarelytics for Apple protects your iOS, tvOS or macOS app from a broad range of cyber threats. Integrate mobile threat protection SDK and connect to our cloud service to get the best benefit.

Supported Features

Malwarelytics for Apple currently supports the following features:

  • Jailbreak Detection
  • Debugger Protection
  • Reverse Engineering Tools Detection
  • HTTP Proxy detection
  • Repackaging Detection
  • Screen Capture Detection
  • VPN Detection
  • Active Call Detection
  • App Presence Detection
  • User Screenshot Detection
  • System Passcode Status
  • System Biometry Status
  • Predefined and Custom Events

Installation

Configuration

Recommended Responses to Security Issues

Malwarelytics for Apple provides detection of many security issues. Moreover, it provides a huge variability in both configuring these protections and reactions to security violations. Some reactions, such as app termination, are provided by the SDK. Other reactions, such as displaying a warning screen or limiting functionality, are the responsibility of the application integrating Malwarelytics for Apple.

The page provides a summary of recommended responses to various security issues that the SDK can help you with.

Before diving into details we summarize the recommendations here. In general, we recommend:

  • Terminate the app on app repackaging, when a debugger is attached, or when reverse engineering tools are detected.
  • Show active warning when a jailbroken device is detected.
  • Block debuggers, and hide screen contents when screen capturing is detected.
  • Inform about other potential issues in some security advisor built into the app.

Responses to Security Issues

Some general approaches to handling a security violation might be:

  1. Display a Warning Message: The app can display a warning message informing the user that the app doesn’t support when a certain security feature is violated. This message should explain the security risks associated with using the app on such devices in such conditions and recommend fixing the issue for banking and financial operations.
  2. Limited Functionality: The app can limit its functionality when a security violation is detected. For example, it might disable some sensitive features like money transfers, or access to sensitive financial data to reduce the potential for unauthorized access and fraudulent activities.
  3. Terminate the App: If the app detects that it is running on a device with a security violation, it can immediately terminate itself to prevent any further access. This will help minimize the exposure of sensitive financial information and protect the user from potential security risks. As a general UX improvement, it is recommended to also open a website (in a browser outside the app) with an explanation while the app is being terminated.
  4. Silent Monitoring on Server: The app can silently monitor what’s happening on the device by sending data to the remote server. This approach is especially powerful when connected to a complex anti-fraud system analyzing inputs from various sources. The backend system can then decide the appropriate handling of the security issue. This approach should be used for all features in parallel to other approaches.

Responses to RASP Security Issues

Malwarelytics for Apple protects from a wide range of runtime issues. Some of them are more serious than others. Here we provide a list of recommended responses to these issues by a banking or a financial app.

Summary of Responses to RASP Issues

The summary here mentions RASP protection features that have a RaspObserver callback method. These features can notify the integrating app about an issue and the app can react to it. Some of the protection behaviors are automatically provided by the SDK.

Security feature Recommended response to security issue
Jailbroken device Terminate the app.
Repackaged app Terminate the app.
Attached debugger Block debuggers or terminate the app when a debugger attaches.
Reverse engineering tools Terminate the app.
Screenshots Display a warning.
Screen capturing Hide content and monitor silently.
System passcode status Display a warning. Optionally limit sensitive functionality.
System biometry status Monitor silently. Optionally display a recommendation.
HTTP proxy Display a warning.
VPN Display a warning.
Active calls Limit sensitive functionality during a call.
App presence Limit sensitive functionality when an unwanted app is installed.

Jailbroken Devices

It is generally recommended to avoid using jailbroken devices for banking or financial apps. The integrity of jailbroken devices is compromised and security is reduced. It is far easier for attackers to bypass security measures designed to protect financial data and the integrity of financial operations within the app.

For these reasons, we generally recommend terminating the app and not allowing users to use it on a jailbroken device.

Repackaged Application

A repackaged application is a changed app and can’t be considered secure. It poses a danger to both clients and the financial institution issuing the app. Any code inside a repackaged app can be inserted, changed, or removed. Therefore security features of such apps have to be considered as compromised.

For this reason, the app should unconditionally terminate itself when it detects that it has been repackaged.

Attached Debuggers

An attached debugger poses a huge danger to the app. There’s a huge number of potential issues such as data leakage, security breaches, transaction tampering, and injection of malicious code.

For these reasons, we generally recommend either blocking debuggers from attaching or terminating the app when an attached debugger is detected.

Reverse Engineering Tools

Reverse engineering tools substantially affect the security and integrity of iOS applications. These tools can be used to jailbreak the device, hook into live processes, and modify code execution in real-time. It can be used to bypass security checks, authentication mechanisms, and other protective measures.

For these reasons, the app should unconditionally terminate itself when it detects any reverse engineering tool.

Screenshots

Screenshots taken by users can contain sensitive personal and financial information. Once a screenshot is captured, the users should take care to handle it with caution to avoid accidental leakage and exposure of the data it may contain. Unfortunately, this is often not the case.

For this reason, the app should warn users about the dangers of leaking sensitive information when it detects that a screenshot has been taken.

Screen Capturing

A financial or banking app handles a lot of sensitive data. Screen capturing can record everything happening on the screen over a period of time, not just a static image. This means all displayed sensitive information, including account numbers, balances, transaction history, and personal data, can be captured in detail. The captured recording can be accidentally or maliciously shared, leading to a significant breach of confidentiality.

The recommended approach is to hide screen contents. This way the obtained recording will not contain sensitive data. Screen capturing should be monitored silently, with no action unless additional suspicious signals appear.

System Passcode Status

Usage of system passcode is an essential security feature of all iOS devices. Not having a system passcode poses significant security risks, especially if sensitive applications like banking apps are installed. The stored personal and financial information is vulnerable to unauthorized access. Moreover, when a malicious individual gets physical access to the device, the possession authentication factor is effectively eliminated on such devices, and the risk of financial fraud greatly increases. Lastly, a lack of system passcode conflicts with several security standards and regulations, which can lead to compliance issues.

The recommended response is to display a warning and optionally limit the app’s sensitive functionality.

System Biometry Status

Usage of biometrics reduces the risk of unauthorized access to the user’s device and a banking app. PINs and passwords are frequently reused by the users. Also, there is a range of attacks for obtaining the user’s password or PIN such as phishing attacks, social engineering, and shoulder surfing.

The recommended response is to monitor the issue silently. Optionally the app can attempt to display a recommendation to the user.

Active HTTP Proxy

Active HTTP proxy can exploit issues in client-server communication when not done correctly and can lead to data interception.

The recommended response to the detection of an active HTTP proxy is to display a warning to the user.

Active VPN

Active VPN can indicate a possible fraud attempt and might be a problem from the point of regulatory compliance. While VPNs are generally used to secure internet traffic, not all VPN services are trustworthy. Some might intercept, monitor, or manipulate traffic routed through them.

The recommended response to the detection of an active VPN is to display a warning to the user.

Active Calls

An active call during the active usage of a banking app poses a risk of social engineering attacks. These attacks are very frequent and create huge financial losses.

For this reason, it’s recommended to block any sensitive functionality during the period of the call. Or even automatically reject all operations and transactions initiated during an active call.

App Presence

Remote desktop apps are a concern for all banking apps due to the potential risk they pose in financial fraud. These apps enable remote access to the device, allowing unauthorized individuals to view the screen remotely. Furthermore, some remote desktop apps may include audio sharing, which could potentially allow eavesdropping through the device’s microphone. Although it is not possible to remotely control an iOS device, attackers frequently use these apps to commit financial fraud.

The recommended response is to limit functionality while an unwanted app is present on the device. All functionality involving sensitive operations and transactions should be blocked to prevent any fraudsters from seeing any sensitive data.

RASP Features Overview

Jailbreak Detection

– | - | | .noAction | indicates that jailbreak will not be automatically detected. A manual check is still possible. | | .notify | indicates that jailbreak will be automatically detected and the delegates will be notified via the jailbreakDetected() method. | | .exit(
exitUrl: String?) | indicates that the jailbreak will be automatically detected and the app will be terminated when the jailbreak is automatically detected. |

Jailbreak detection defaults to .notify.

List of available parameters for some config values:

Parameter Description
exitUrl: String? defines the URL to be opened when the app is terminated because of the automatic detection. Defaults to nil.

Usage

After service creation, the jailbreak detection feature can be accessed via AppProtectionRasp. This can be used to add a delegate or to trigger a manual jailbreak detection check.

Observing Detection

Jailbreak detection can trigger a certain action. To achieve that, a delegate needs to be added.

Delegate configuration:

class RaspDelegate: AppProtectionRaspDelegate {

    // other delegate code

    func jailbreakDetected() {
        // handle jailbreak detection
    }
}

The delegate can be added in AppProtectionRasp. When it is no longer needed, it can be removed again.

let raspDelegate = RaspDelegate()
appProtection.rasp.addDelegate(raspDelegate)
appProtection.rasp.removeDelegate(raspDelegate)

Triggering a Manual Check

Jailbreak detection check can be triggered manually in AppProtectionRasp by getting the isJailbroken property value. A simple Bool answer is given.

let isJailbroken = appProtection.rasp.isJailbroken

More information on general RASP feature configuration and usage can be found in this overview.

Debugger Detection

– | | | .noAction | indicates that debuggers will not be automatically detected. A manual check is still possible. | | .notify | indicates that debuggers will be automatically detected and the delegates will be notified via the debuggerDetected() method. | | .block | indicates that debuggers will be blocked from attaching to the application process. | | .exit(
exitUrl: String?) | indicates that debuggers will be automatically detected and the app will be terminated when a debugger is automatically detected. |

Debugger detection defaults to .notify.

List of available parameters for some config values:

Parameter Description
exitUrl: String? defines the URL to be opened when the app is terminated because of the automatic detection. Defaults to nil.

Usage

After service creation, the debugger detection feature can be accessed via AppProtectionRasp. This can be used to add a delegate or to trigger a manual debugger detection check.

Observing Detection

Debugger detection can trigger a certain action. To achieve that, a delegate needs to be added.

Delegate configuration:

class RaspDelegate: AppProtectionRaspDelegate {

    // other delegate code

    func debuggerDetected() {
        // handle debugger detection
    }
}

The delegate can be added in AppProtectionRasp. When it is no longer needed, it can be removed again.

let raspDelegate = RaspDelegate()
appProtection.rasp.addDelegate(raspDelegate)
appProtection.rasp.removeDelegate(raspDelegate)

Triggering a Manual Check

Debugger detection check can be triggered manually in AppProtectionRasp by getting the isDebuggerConnected property value. A simple Bool answer is given.

let isDebuggerConnected = appProtection.rasp.isDebuggerConnected

More information on general RASP feature configuration and usage can be found in this overview.

Reverse Engineering Tools Detection

– | - | | .noAction | indicates that reverse engineering tools will not be automatically detected. A manual check is still possible. | | .notify | indicates that reverse engineering tools will be automatically detected and the delegates will be notified via the reverseEngineeringToolsDetected() method. | | .exit(
exitUrl: String?) | indicates that the reverse engineering tools will be automatically detected and the app will be terminated when the reverse engineering tools are automatically detected. |

Reverse engineering tools detection defaults to .notify.

List of available parameters for some config values:

Parameter Description
exitUrl: String? defines the URL to be opened when the app is terminated because of the automatic detection. Defaults to nil.

Usage

After service creation, the reverse engineering tools detection feature can be accessed via AppProtectionRasp. This can be used to add a delegate or to trigger a manual reverse engineering tools detection check.

Observing Detection

Reverse engineering tools detection can trigger a certain action. To achieve that, a delegate needs to be added.

Delegate configuration:

class RaspDelegate: AppProtectionRaspDelegate {

    // other delegate code

    func reverseEngineeringToolsDetected() {
        // handle reverse engineering tools detection
    }
}

The delegate can be added in AppProtectionRasp. When it is no longer needed, it can be removed again.

let raspDelegate = RaspDelegate()
appProtection.rasp.addDelegate(raspDelegate)
appProtection.rasp.removeDelegate(raspDelegate)

Triggering a Manual Check

Reverse engineering tools detection check can be triggered manually in AppProtectionRasp by getting the isReverseEngineeringToolsPresent property value. A simple Bool answer is given.

let isReverseEngineeringToolsPresent = appProtection.rasp.isReverseEngineeringToolsPresent

More information on general RASP feature configuration and usage can be found in this overview.

HTTP Proxy Detection

– | | | .noAction | indicates that the HTTP proxy will not be automatically detected. A manual check is still possible. | | .notify | indicates that the HTTP proxy will be automatically detected and the delegates will be notified via the httpProxyEnabled() method. | | .exit(
exitUrl: String?) | indicates that the HTTP proxy will be automatically detected and the app will be terminated when the HTTP proxy is automatically detected. |

HTTP proxy detection defaults to .notify.

List of available parameters for some config values:

Parameter Description
exitUrl: String? defines the URL to be opened when the app is terminated because of the automatic detection. Defaults to nil.

Usage

After service creation, the HTTP proxy detection feature can be accessed via AppProtectionRasp. This can be used to add a delegate or to trigger a manual HTTP proxy detection check.

Observing Detection

HTTP proxy detection can trigger a certain action. To achieve that, a delegate needs to be added.

Delegate configuration:

class RaspDelegate: AppProtectionRaspDelegate {

    // other delegate code

    func httpProxyEnabled() {
        // handle HTTP proxy detection
    }
}

The delegate can be added in AppProtectionRasp. When it is no longer needed, it can be removed again.

let raspDelegate = RaspDelegate()
appProtection.rasp.addDelegate(raspDelegate)
appProtection.rasp.removeDelegate(raspDelegate)

Triggering a Manual Check

HTTP proxy detection check can be triggered manually in AppProtectionRasp by getting the isHttpProxyEnabled property value. A simple Bool answer is given.

let isHttpProxyEnabled = appProtection.rasp.isHttpProxyEnabled

More information on general RASP feature configuration and usage can be found in this overview.

Repackaging Detection

– | – | | .noAction(
trustedCerts: [TrustedCertificate]) | indicates that repackaging will not be automatically detected. A manual check is still possible. | | .notify(
trustedCerts: [TrustedCertificate]) | indicates that repackaging will be automatically detected and the delegates will be notified via the repackageDetected() method. | | .exit(
trustedCerts: [TrustedCertificate],
exitUrl: String?) | indicates that the repackaging will be automatically detected and the app will be terminated when the repackaging is automatically detected. |

Repackaging detection defaults to .noAction([]).

List of available parameters for some config values:

Parameter Description
trustedCerts: [TrustedCertificate] defines trusted certificates for ad-hoc or enterprise distribution. AppStore signing certificates are trusted by default.
exitUrl: String? defines the URL to be opened when the app is terminated because of the automatic detection. Defaults to nil.

Certificate Configuration Details

To properly configure the repackaging detection, you need to get the Base64 encoded string of your signing certificate:

  1. Open the Keychain Access application.
  2. Find a certificate that will be used to sign your application, for example, “Apple Development: Jan Tester (c)”.
  3. Right-click on the item and click “Export…”.
  4. Export the certificate in the .cer format.
  5. Open up the terminal and cd into the folder with your exported certificate.
  6. Encode the certificate in Base64 with cat your_exported.cer | base64.
  7. Copy the output of the command and use it as a parameter for the repackage detection configuration:
// Prepare the RASP feature configuration
let raspConfig = AppProtectionRaspConfig(
    // ...
    repackage: .exit([AppProtectionTrustedCert(withBase64EncodedString: "BASE_64_ENCODED_CERT")!], "https://myurl.com/repackage-explained")
    // ...
)

Tip: To hide the string in your binary, use the init constructor for AppProtectionTrustedCert with Data or [UInt8] arguments.

Usage

After service creation, the repackaging detection feature can be accessed via AppProtectionRasp. This can be used to add a delegate or to trigger a manual repackaging detection check.

Observing Detection

Repackaging detection can trigger a certain action. To achieve that, a delegate needs to be added.

Delegate configuration:

class RaspDelegate: AppProtectionRaspDelegate {

    // other delegate code

    func repackageDetected() {
        // handle repackaging detection
    }
}

The delegate can be added in AppProtectionRasp. When it is no longer needed, it can be removed again.

let raspDelegate = RaspDelegate()
appProtection.rasp.addDelegate(raspDelegate)
appProtection.rasp.removeDelegate(raspDelegate)

Triggering a Manual Check

The repackaging detection check can be triggered manually in AppProtectionRasp by getting the isRepackaged property value. A simple Bool answer is given.

let isRepackaged = appProtection.rasp.isRepackaged

More information on general RASP feature configuration and usage can be found in this overview.

Screen Capture Detection

– | – | | .noAction | indicates that screen capture will not be automatically detected. A manual check is still possible. | | .notify | indicates that screen capture will be automatically detected and the delegates will be notified via the screenCapturedChanged(Bool) method. | | .hide(
overlay: Overlay) | indicates that the app will hide its content when the screen capture is detected. The delegates will be notified via the screenCapturedChanged(Bool) method. | | .exit(
exitUrl: String?) | indicates that the screen capture will be automatically detected and the app will be terminated when the screen capture is automatically detected. |

Screen capture detection defaults to .notify.

List of available parameters for some config values:

Parameter Description
overlay: Overlay defines the overlay that will be used to hide the contents of the app. Defaults to .default.
exitUrl: String? defines the URL to be opened when the app is terminated because of the automatic detection. Defaults to nil.

Overlay Configuration

Available value of Overlay:

Value Description
.default defines the default behavior that covers the screen with a solid color and application icon.
.color(
color: UIColor)
defines that the screen will be covered with a solid color.
.image(
image: UIImage)
defines that the screen will be covered with an image.

Usage

After service creation, the screen capture detection feature can be accessed via AppProtectionRasp. This can be used to add a delegate or to trigger a manual screen capture detection check.

Observing Detection

The screen capture detection can trigger a certain action. To achieve that, a delegate needs to be added.

Delegate configuration:

class RaspDelegate: AppProtectionRaspDelegate {

    // other delegate code

    func screenCapturedChanged(isCaptured: Bool) {
        // handle screen capture detection (casting to a different device)
    }
}

The delegate can be added in AppProtectionRasp. When it is no longer needed, it can be removed again.

let raspDelegate = RaspDelegate()
appProtection.rasp.addDelegate(raspDelegate)
appProtection.rasp.removeDelegate(raspDelegate)

Triggering a Manual Check

The screen capture detection check can be triggered manually in AppProtectionRasp by getting the isScreenCaptured property value. A simple Bool answer is given.

let isScreenCaptured = appProtection.rasp.isScreenCaptured

More information on general RASP feature configuration and usage can be found in this overview.

VPN Detection

– | - | | .noAction | indicates that the VPN will not be automatically detected. A manual check is still possible. | | .notify | indicates that the VPN will be automatically detected and the delegates will be notified via the vpnChanged(Bool) method. | | .exit(
exitUrl: String?) | indicates that the VPN will be automatically detected and the app will be terminated when the VPN is automatically detected. |

VPN detection defaults to .notify.

List of available parameters for some config values:

Parameter Description
exitUrl: String? defines the URL to be opened when the app is terminated because of the automatic detection. Defaults to nil.

Usage

After service creation, the VPN detection feature can be accessed via AppProtectionRasp. This can be used to add a delegate or to trigger a manual VPN detection check.

Observing Detection

VPN detection can trigger a certain action. To achieve that, a delegate needs to be added.

Delegate configuration:

class RaspDelegate: AppProtectionRaspDelegate {

    // other delegate code

    func vpnChanged(active: Bool) {
        // handle VPN detection
    }
}

The delegate can be added in AppProtectionRasp. When it is no longer needed, it can be removed again.

let raspDelegate = RaspDelegate()
appProtection.rasp.addDelegate(raspDelegate)
appProtection.rasp.removeDelegate(raspDelegate)

Triggering a Manual Check

VPN detection check can be triggered manually in AppProtectionRasp by getting the isVpnActive property value. A simple Bool answer is given.

let isVpnActive = appProtection.rasp.isVpnActive

More information on general RASP feature configuration and usage can be found in this overview.

Active Call Detection

– | - | | .noAction | indicates that an active call will not be automatically detected. A manual check is still possible. | | .notify | indicates that an active call will be automatically detected and the delegates will be notified via the onCallChanged(Bool) method. |

Active call detection defaults to .notify.

Usage

After service creation, the active call detection feature can be accessed via AppProtectionRasp. This can be used to add a delegate or to trigger a manual active call detection check.

Observing Detection

Active call detection can trigger a certain action. To achieve that, a delegate needs to be added.

Delegate configuration:

class RaspDelegate: AppProtectionRaspDelegate {

    // other delegate code

    func onCallChanged(isOnCall: Bool) {
        // handle active call detection
    }
}

The delegate can be added in AppProtectionRasp. When it is no longer needed, it can be removed again.

let raspDelegate = RaspDelegate()
appProtection.rasp.addDelegate(raspDelegate)
appProtection.rasp.removeDelegate(raspDelegate)

Triggering a Manual Check

Active call detection check can be triggered manually in AppProtectionRasp by getting the isOnCall property value. A simple Bool answer is given.

let isOnCall = appProtection.rasp.isOnCall

More information on general RASP feature configuration and usage can be found in this overview.

App Presence Detection

| – | | .manual(
apps: [DetectableApp]) | indicates that app presence will not be automatically detected. A manual check is still possible. | | .notify(
apps: [DetectableApp]) | indicates that app presence will be automatically detected and the delegates will be notified via the installedAppsChanged([DetectableApp]) method. |

The app presence detection defaults to .manual([]).

List of available parameters for some config values:

Parameter Description
apps: [DetectableApp] defines the list of detectable apps.

Detectable App Configuration

A detectable app is defined by several properties:

Property Description
deeplinkProtocols: [String] specifies deep links defined for the app.
name: String specifies name of the application. The name can be chosen at will and does not need to reflect the name in the AppStore or of an installed app.
category: Category specifies category of the application. Currently only .remoteDesktop is available.
tag: String? specifies any additional information that should be passed to the remote server.

Usage

After service creation, the app presence detection feature can be accessed via AppProtectionRasp. This can be used to add a delegate or to trigger a manual app presence detection check.

Observing Detection

The app presence detection can trigger a certain action. To achieve that, a delegate needs to be added.

Delegate configuration:

class RaspDelegate: AppProtectionRaspDelegate {

    // other delegate code

    func installedAppsChanged(installedApps: [DetectableApp]) {
        // handle app presence detection
    }
}

The delegate can be added in AppProtectionRasp. When it is no longer needed, it can be removed again.

let raspDelegate = RaspDelegate()
appProtection.rasp.addDelegate(raspDelegate)
appProtection.rasp.removeDelegate(raspDelegate)

Triggering a Manual Check

The app presence detection check can be triggered manually in AppProtectionRasp by getting the installedApps property value. The method returns [DetectableApp].

let installedApps = appProtection.rasp.installedApps

More information on general RASP feature configuration and usage can be found in this overview.

User Screenshot Detection

System Passcode Detection

System Biometry Detection

Release Notes

Current Release

Release 3.0.1-dev

  • Improve VPN detection (#135)
  • Improve jailbreak detection with detection of rootless palera1n (#136)
  • Fix .exit(String?) with invalid exitUrl string (#134)

Previous Releases

Release 3.0.0

  • Renamed the swift module to WultraAppProtection from AppProtection

Release 2.1.2

  • Change debugger detection default to .notify (#113)
  • Updated TestFlight certificate

Release 2.1.1

  • Add unwanted apps detection (#104)

Release 2.0.0

  • Add detection of active call
  • Add option to run in RASP-only (offline) mode

Release 1.2.2

  • Add support for TestFlight builds (#90)

Release 1.2.1

  • Remove X-Signature-Origin-App header from signature verification (#85)
  • Expose avUid (internal device id) (#87)

Release 1.2.0

  • Add overlay when screen is captured (#77)
  • Add VPN detection (#72)

Release 1.1.2

  • Add test environment (#73)
  • Improve CPU usage (#74)

Release 1.1.1

  • Add clientAppDeviceId (#68)
  • Add config items for customer application package names and grouping (#67)

Release 1.1.0

  • Add Swift Package Manager support
  • Add other fixes and improvements

Release 1.0.3

  • Fix issue when device id could be automaticaly renewed
  • Add other fixes and improvements

Release 1.0.2

  • Fix potential crash when the app was running for a long time
  • Add other fixes and improvements

Release 1.0.1

  • Add fixes and improvements

Release 1.0.0

  • Remove singleton pattern. Use a public initializer to create an instance note that only one instance can be created.
  • Remove configuration builders. Configuration is now struct with initializer.
  • Add other fixes and improvements

Release 0.9.9

  • Add fixes related to Core Data crashes

Release 0.9.8

  • Initial beta release
Generated on Jul 22, 2024 (16:51)