Skip to main content

Root detection control bypass

Description

It is possible to reverse engineer the application and disable detection of rooted devices.

Impact

Avoid the applications detection of rooted devices.

Recommendation

Implement an integrity check on the application so that it cannot be used if it has been modified.

Threat

Attacker with access to APK.

Expected Remediation Time

⌚ 450 minutes.

Score

Default score using CVSS 3.1. It may change depending on the context of the vulnerability.

Base

  • Attack vector: N
  • Attack complexity: H
  • Privileges required: N
  • User interaction: N
  • Scope: U
  • Confidentiality: N
  • Integrity: L
  • Availability: N

Temporal

  • Exploit code madurity: X
  • Remediation level: X
  • Report confidence: X

Result

  • Vector string: CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N/E:X/RL:X/RC:X
  • Score:
    • Base: 3.7
    • Temporal: 3.7
  • Severity:
    • Base: Low
    • Temporal: Low

Code Examples

Compliant code

A function implemented to check if the source code has been altered before running the app. A possible option is to include a MD5 hash within the code, generated at each build, and adding a check to the code to ensure that this hash is the same as the one stored before running the app

public static boolean checkApkSha(){
String apkPath = appExample.getInstance().getPackageCodePath();
MessageDigest msgDigest = null;
try {
msgDigest = MessageDigest.getInstance("SHA-1");
byte[] bytes = new byte[1024];
int byteCount;
FileInputStream fis = new FileInputStream(new File(apkPath));
while ((byteCount = fis.read(bytes)) > 0){
msgDigest.update(bytes, 0, byteCount);
}
BigInteger bi = new BigInteger(1, msgDigest.digest());
String sha = bi.toString(16);
fis.close();
if(BaseApplication.getInstance().getString(R.string.apk_sha).equals(sha)){
return true;
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
}

Non compliant code

Source code could be executed after vulnerable adjustments because of an incorrectly implemented integrity check

public static boolean checkDexCrcValue() {
String apkPath = BaseApplication.getInstance().getPackageCodePath();
Long dexCrc = Long.parseLong(QianJinSuoApplication.getInstance().getString(R.string.classesdex_crc));
try {
ZipFile zipfile = new ZipFile(apkPath);
ZipEntry dexentry = zipfile.getEntry("classes.dex");
# The CRC32 check could be bypassed anyway because of debugging code included in the function
Log.i("checkDexCrcValue", "classes.dexcrc=" + dexentry.getCrc());
if (dexentry.getCrc() == dexCrc) {
return true;
}
} catch (IOException e) {
e.printStackTrace();
}
return false;
}

Requirements