Application code not obfuscated
Code de l'application non obfusqué
Description
L'obfuscation fait référence aux méthodes permettant de masquer le code et de le rendre difficile à comprendre. Les classes Java compilées peuvent être décompilées s'il n'y a pas d'obfuscation pendant l'étape de compilation. Elle fonctionne en modifiant le code et les métadonnées de l'application de manière à ce qu'il soit difficile pour les attaquants de comprendre le code et de le modifier pour introduire des vulnérabilités ou ajouter des fonctionnalités malveillantes. Les obfuscateurs y parviennent généralement en renommant les classes, les méthodes et les variables avec des noms sans signification, en supprimant les informations de débogage et en ajoutant du code factice pour tromper les décompilateurs.
Les adversaires peuvent voler du code et des informations sensibles, introduire des vulnérabilités susceptibles de compromettre la sécurité de l'application, ou réutiliser et vendre le code dans une nouvelle application ou créer une fausse application malveillante basée sur l'initiale. Si ce code n'est pas obfusqué, il peut être facilement décompilé à l'aide d'outils comme Apktool ou JADX.
L'obfuscation du code ne fait que ralentir l'attaquant dans sa rétro-ingénierie, mais ne la rend pas impossible.
Recommandation
Voici les étapes que vous pouvez envisager pour rendre votre application moins vulnérable à la rétro-ingénierie :
Obfusquer le code source Java avec Proguard.
Pour ajouter Proguard à votre application, ajoutez ce qui suit au fichier build.gradle :
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
Cela indique à Gradle d'utiliser ProGuard pour l'obfuscation du code dans la build de release. Vous pouvez ensuite créer un fichier "proguard-rules.pro" dans le répertoire "app" de l'application pour configurer les règles d'obfuscation.
Exemple proguard-rules.pro:
# Conserver les noms des classes dans ce paquet
-keep class com.example.myapplication.** { *; }
# Conserver toutes les méthodes publiques et protégées dans ces classes
-keepclassmembers class com.example.myapplication.** {
public protected *;
}
# Conserver tous les noms de méthodes natives
-keepclassmembers class * {
native <methods>;
}
# Conserver tous les champs avec le nom spécifié
-keepclassmembers class * {
private int myField;
}
# Conserver toutes les classes qui implémentent Parcelable
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
# Conserver toutes les classes Enum
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
# Conserver toutes les annotations
-keepattributes *Annotation*
# Préserver tous les points d'entrée (comme les méthodes main)
-keep public class * {
public static void main(java.lang.String[]);
}
# Conserver toutes les classes Serializable
-keep class * implements java.io.Serializable {
*;
}
Obfusquer le code source Java avec Dexguard.
Pour activer Dexguard dans votre application, vous pouvez ajouter ce qui suit au fichier build.gradle :
buildTypes {
release {
minifyEnabled true
useProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
dexguard {
config 'dexguard-release.cfg'
}
}
}
Cela indique à Gradle d'utiliser DexGuard pour l'obfuscation du code dans la build de release. Vous pouvez créer un fichier "dexguard-project.txt" dans le répertoire "app" de l'application pour configurer le projet DexGuard, et un fichier "dexguard-release.cfg" pour configurer l'obfuscation pour la build de release.
Par défaut, lorsque vous activez l'obfuscation du code à l'aide de DexGuard, il utilisera ses propres règles d'obfuscation en plus des règles spécifiées dans le fichier de configuration ProGuard. Cependant, vous pouvez désactiver l'utilisation des règles de ProGuard en définissant l'option useProguard sur false.
- Vérification du certificat de signature de l'application lors de l'exécution en vérifiant
context.getPackageManager().signature - Vérifier le programme d'installation de l'application pour s'assurer qu'il correspond à l'Android Market en appelant
context.getPackageManager().getInstallerPackageName - Vérifier l'environnement d'exécution lors de l'exécution
Vérifier si l'application s'exécute sur un émulateur
Vous pouvez ajouter la vérification suivante à votre application pour détecter si elle s'exécute sur un émulateur.
private static String getSystemProperty(String name) throws Exception {
Class systemPropertyClazz = Class.forName("android.os.SystemProperties");
return (String) systemPropertyClazz.getMethod("get", new Class[] { String.class }).invoke(systemPropertyClazz, new Object[] { name });
}
public static boolean checkEmulator() {
try {
boolean goldfish = getSystemProperty("ro.hardware").contains("goldfish");
boolean qemu = getSystemProperty("ro.kernel.qemu").length() > 0;
boolean sdk = getSystemProperty("ro.product.model").equals("sdk");
if (qemu || goldfish || sdk) {
return true;
}
} catch (Exception e) {}
return false;
}
Vérifier l'indicateur de débogage à l'exécution
De même, vous pouvez vérifier si l'application est en mode débogage pendant l'exécution
context.getApplicationInfo().applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE;
Liens
Normes
- OWASP_MASVS_RESILIENCE:
- MSTG_RESILIENCE_9
- MSTG_RESILIENCE_12
- PCI_STANDARDS:
- REQ_2_2
- OWASP_MASVS_v2_1:
- MASVS_RESILIENCE_3
- HIPAA_CONTROLS:
- SECURITY212
- SECURITY213
- SECURITY255