From 6050e870a4d2ecb7968e1d664c92d55f4d593040 Mon Sep 17 00:00:00 2001 From: burogurama Date: Sat, 20 Jun 2026 12:10:54 +0100 Subject: [PATCH] feature: add ANTI_SIDELOADING present/missing KB entries for Android --- .../ANTI_SIDELOADING_MISSING/description.md | 10 +++ .../ANTI_SIDELOADING_MISSING/meta.json | 36 ++++++++++ .../recommendation.md | 72 +++++++++++++++++++ .../ANTI_SIDELOADING_PRESENT/description.md | 3 + .../ANTI_SIDELOADING_PRESENT/meta.json | 38 ++++++++++ .../recommendation.md | 1 + 6 files changed, 160 insertions(+) create mode 100644 MOBILE_CLIENT/ANDROID/_HARDENING/ANTI_SIDELOADING_MISSING/description.md create mode 100644 MOBILE_CLIENT/ANDROID/_HARDENING/ANTI_SIDELOADING_MISSING/meta.json create mode 100644 MOBILE_CLIENT/ANDROID/_HARDENING/ANTI_SIDELOADING_MISSING/recommendation.md create mode 100644 MOBILE_CLIENT/ANDROID/_SECURE/ANTI_SIDELOADING_PRESENT/description.md create mode 100644 MOBILE_CLIENT/ANDROID/_SECURE/ANTI_SIDELOADING_PRESENT/meta.json create mode 100644 MOBILE_CLIENT/ANDROID/_SECURE/ANTI_SIDELOADING_PRESENT/recommendation.md diff --git a/MOBILE_CLIENT/ANDROID/_HARDENING/ANTI_SIDELOADING_MISSING/description.md b/MOBILE_CLIENT/ANDROID/_HARDENING/ANTI_SIDELOADING_MISSING/description.md new file mode 100644 index 00000000..8ff69899 --- /dev/null +++ b/MOBILE_CLIENT/ANDROID/_HARDENING/ANTI_SIDELOADING_MISSING/description.md @@ -0,0 +1,10 @@ +The application ran normally after being installed from an unofficial source instead of the store it was published through, without detecting or responding to the sideloaded installation. + +A sideloaded build is the typical delivery vector for a repackaged app: an attacker decompiles the original APK, injects malicious code or strips out security controls, re-signs it with their own key, and distributes it through third-party stores, file-sharing sites, or social engineering. Because the app never checks where it was installed from, the tampered copy runs with full functionality. + +**Common attack scenarios:** + +- **Repackaged malware distribution:** A trojanized clone of the app is published on a third-party store; users who sideload it expose their credentials and data to the attacker. +- **Ad/SDK swapping:** The original APK is rebuilt with the attacker's analytics or ad SDK to hijack revenue and exfiltrate user data. +- **Control stripping:** Root detection, certificate pinning, or license checks are removed from the repackaged build before redistribution. +- **Bypassing store-side protections:** Sideloading skips the publishing channel's malware scanning and integrity guarantees entirely. diff --git a/MOBILE_CLIENT/ANDROID/_HARDENING/ANTI_SIDELOADING_MISSING/meta.json b/MOBILE_CLIENT/ANDROID/_HARDENING/ANTI_SIDELOADING_MISSING/meta.json new file mode 100644 index 00000000..d9fd247c --- /dev/null +++ b/MOBILE_CLIENT/ANDROID/_HARDENING/ANTI_SIDELOADING_MISSING/meta.json @@ -0,0 +1,36 @@ +{ + "risk_rating": "hardening", + "short_description": "The application does not verify its installation source and runs normally when sideloaded from an unofficial channel.", + "title": "Missing Sideloading Detection", + "privacy_issue": false, + "security_issue": true, + "references": { + "OWASP MASVS - MASVS-RESILIENCE-2": "https://mas.owasp.org/MASVS/controls/MASVS-RESILIENCE-2/", + "Android Developers - PackageManager.getInstallSourceInfo": "https://developer.android.com/reference/android/content/pm/PackageManager", + "Android Developers - Play Integrity API overview": "https://developer.android.com/google/play/integrity/overview", + "Android Developers - Play Install Referrer Library": "https://developer.android.com/google/play/installreferrer" + }, + "categories": { + "OWASP_MASVS_RESILIENCE": [ + "MSTG_RESILIENCE_3" + ], + "OWASP_MASVS_v2_1": [ + "MASVS_RESILIENCE_2" + ], + "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/ANDROID/_HARDENING/ANTI_SIDELOADING_MISSING/recommendation.md b/MOBILE_CLIENT/ANDROID/_HARDENING/ANTI_SIDELOADING_MISSING/recommendation.md new file mode 100644 index 00000000..59862020 --- /dev/null +++ b/MOBILE_CLIENT/ANDROID/_HARDENING/ANTI_SIDELOADING_MISSING/recommendation.md @@ -0,0 +1,72 @@ +Verify at runtime that the app was installed by an authorized source and respond when it was not. Combine a local installer-package check (cheap, but spoofable) with a server-verified Play Integrity attestation (authoritative). + +**Detection approaches:** + +1. **Installer package verification:** Query which package installed the app and confirm it matches an allow-list of trusted installers (e.g. the Google Play Store, `com.android.vending`). On API 30+ use `getInstallSourceInfo`; fall back to `getInstallerPackageName` on older releases. A `null` installer indicates a sideloaded `adb install` or a direct APK install. + +=== "Kotlin" + ```kotlin + private val TRUSTED_INSTALLERS = setOf( + "com.android.vending", // Google Play Store + "com.google.android.feedback" + ) + + fun isFromTrustedInstaller(context: Context): Boolean { + val pm = context.packageManager + val installer = try { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + pm.getInstallSourceInfo(context.packageName).installingPackageName + } else { + @Suppress("DEPRECATION") + pm.getInstallerPackageName(context.packageName) + } + } catch (_: PackageManager.NameNotFoundException) { + null + } + return installer in TRUSTED_INSTALLERS + } + ``` + +=== "Java" + ```java + private static final Set TRUSTED_INSTALLERS = new HashSet<>(Arrays.asList( + "com.android.vending", "com.google.android.feedback" + )); + + public static boolean isFromTrustedInstaller(Context context) { + PackageManager pm = context.getPackageManager(); + String installer = null; + try { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + installer = pm.getInstallSourceInfo(context.getPackageName()) + .getInstallingPackageName(); + } else { + installer = pm.getInstallerPackageName(context.getPackageName()); + } + } catch (PackageManager.NameNotFoundException ignored) { + } + return installer != null && TRUSTED_INSTALLERS.contains(installer); + } + ``` + +2. **Play Integrity attestation (authoritative):** The local installer string can be spoofed on a rooted device, so back it with a server-side check. Request an integrity token from the Play Integrity API, send it to your backend, and verify on the server that `appRecognitionVerdict` is `PLAY_RECOGNIZED` and the device meets `MEETS_DEVICE_INTEGRITY`. A repackaged or sideloaded build will not be recognized by Play. + +=== "Kotlin" + ```kotlin + val manager = IntegrityManagerFactory.create(context) + manager.requestIntegrityToken( + IntegrityTokenRequest.builder() + .setNonce(serverProvidedNonce) + .build() + ).addOnSuccessListener { response -> + // Send response.token() to your backend; never trust the verdict on-device. + sendTokenToServer(response.token()) + } + ``` + +**Additional hardening:** + +- Treat the installer check as a hint and the server-verified Play Integrity verdict as the decision — never gate access on the on-device result alone. +- Implement the installer/source checks in native code (JNI) so the comparison and the allow-list cannot be trivially patched at the Java layer. +- Pair with APK signature verification so a re-signed repackaged build is rejected even if it spoofs the installer string. +- On a failed verdict, fail server-side: refuse to issue session tokens or unlock sensitive features rather than only showing a client-side warning. diff --git a/MOBILE_CLIENT/ANDROID/_SECURE/ANTI_SIDELOADING_PRESENT/description.md b/MOBILE_CLIENT/ANDROID/_SECURE/ANTI_SIDELOADING_PRESENT/description.md new file mode 100644 index 00000000..406bf1dd --- /dev/null +++ b/MOBILE_CLIENT/ANDROID/_SECURE/ANTI_SIDELOADING_PRESENT/description.md @@ -0,0 +1,3 @@ +The application verified its installation source and detected that it had been sideloaded from an unofficial channel rather than the store it was published through, responding by terminating or displaying a security warning. + +This indicates the app performs installer-source verification, raising the bar against repackaged builds distributed through third-party stores or direct APK installs that strip out security controls or inject malicious code. diff --git a/MOBILE_CLIENT/ANDROID/_SECURE/ANTI_SIDELOADING_PRESENT/meta.json b/MOBILE_CLIENT/ANDROID/_SECURE/ANTI_SIDELOADING_PRESENT/meta.json new file mode 100644 index 00000000..e7e7fb8e --- /dev/null +++ b/MOBILE_CLIENT/ANDROID/_SECURE/ANTI_SIDELOADING_PRESENT/meta.json @@ -0,0 +1,38 @@ +{ + "risk_rating": "secure", + "short_description": "The application verifies its installation source and detects when it has been sideloaded from an unofficial channel.", + "title": "Sideloading Detection Implemented", + "privacy_issue": false, + "security_issue": true, + "targeted_by_malware": false, + "targeted_by_ransomware": false, + "targeted_by_nation_state": false, + "has_public_exploit": false, + "references": { + "OWASP MASVS - MASVS-RESILIENCE-2": "https://mas.owasp.org/MASVS/controls/MASVS-RESILIENCE-2/", + "Android Developers - Play Integrity API overview": "https://developer.android.com/google/play/integrity/overview" + }, + "categories": { + "OWASP_MASVS_RESILIENCE": [ + "MSTG_RESILIENCE_3" + ], + "OWASP_MASVS_v2_1": [ + "MASVS_RESILIENCE_2" + ], + "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/ANDROID/_SECURE/ANTI_SIDELOADING_PRESENT/recommendation.md b/MOBILE_CLIENT/ANDROID/_SECURE/ANTI_SIDELOADING_PRESENT/recommendation.md new file mode 100644 index 00000000..5911adf4 --- /dev/null +++ b/MOBILE_CLIENT/ANDROID/_SECURE/ANTI_SIDELOADING_PRESENT/recommendation.md @@ -0,0 +1 @@ +The implementation is secure, no recommendation applies.