I am working on a FinTech Android app, and I recently discovered that the APK can be tampered with using tools like APKTool. Specifically, the strings.xml file can be modified, and the APK can be recompiled without any issues. This poses a significant security risk, as the app handles sensitive financial data.
I want to implement APK tamper detection to ensure that any modifications to the app’s resources or code are detected before the app is allowed to run.
1.What are the best practices for implementing tamper detection in Android apps, especially in the context of a FinTech application?
2.Are there any recommended libraries or techniques that can help in detecting tampering of the APK, including modifications to resource files like strings.xml?
3.How can I ensure that the app will not run if it has been tampered with?
1
1. APK Signature Verification
Android apps are signed with a private key before being distributed. When the app is installed, the Android system verifies the signature. Ensure that your app’s signature is checked at runtime to confirm it hasn’t been modified after signing.
Use the BuildConfig or PackageInfo to compare the apps and expected certificates.
Sample code
fun isAppSignatureValid(context : Context): Boolean {
val packageInfo = context.packageManager.getPackageInfo(
context.packageName,
PackageManager.GET_SIGNATURES
)
// Iterate through the signatures
val signatures = packageInfo.signatures
for (signature in signatures) {
val signatureBytes = signature.toByteArray()
// Generate the SHA-1 hash of the signature
val md = MessageDigest.getInstance("SHA")
val digest = md.digest(signatureBytes)
// Convert the hash to a hex string
val hex = digest.joinToString("") { String.format("%02X", it) }
// Compare the generated hash with the expected signature hash
if (hex == EXPECTED_SIGNATURE_HASH) {
return true // Signature is valid
}
}
return false // Signature is invalid
}
2. Root/Jailbreak Detection
Detect if the device is rooted, as root access allows more significant tampering.
fun isDeviceRooted(): Boolean {
val rootPaths = arrayOf(
"/system/app/Superuser.apk",
"/sbin/su",
"/system/bin/su",
"/system/xbin/su"
)
return rootPaths.any { File(it).exists() }
}
3. Secure Communication (Certificate Pinning)
Ensure that all network communications are secure and encrypted using HTTPS.
4. ProGuard/R8 Obfuscation
Use ProGuard or R8 to obfuscate your code, making it harder for attackers to reverse engineer and modify your app.
The method above helps prevent tampering by checking the app’s signature at runtime. To detect APK tampering, simply verify the app’s signature as described in the first solution.
1