Application code not obfuscated
Código de la aplicación no ofuscado
Descripción
La ofuscación se refiere a los métodos para ocultar el código y dificultar su comprensión. Las clases de Java compiladas pueden descompilarse si no hay ofuscación durante el paso de compilación. Funciona modificando el código y los metadatos de la aplicación de tal manera que a los atacantes les resulte difícil comprender el código y modificarlo para introducir vulnerabilidades o agregar funcionalidades maliciosas. Los ofuscadores normalmente logran esto renombrando clases, métodos y variables con nombres sin significado, eliminando información de depuración y agregando código falso para confundir a los descompiladores.
Los adversarios pueden robar código e información sensible, introducir vulnerabilidades que puedan comprometer la seguridad de la aplicación, o reutilizar y vender el código en una nueva aplicación, o crear una aplicación falsa y maliciosa basada en la inicial. Si este código no está ofuscado, puede descompilarse fácilmente utilizando herramientas como Apktool o JADX.
La ofuscación de código solo retrasa al atacante en la ingeniería inversa, pero no la hace imposible.
Recomendación
A continuación se indican los pasos que puede considerar para que su aplicación sea menos propensa a la ingeniería inversa:
Ofuscar el código fuente de Java con Proguard.
Para agregar Proguard a su aplicación, agregue lo siguiente al archivo build.gradle:
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
Esto le indica a Gradle que use ProGuard para la ofuscación de código en la build de release. Luego puede crear un archivo "proguard-rules.pro" en el directorio "app" de la aplicación para configurar las reglas de ofuscación.
Ejemplo proguard-rules.pro:
# Mantener los nombres de las clases en este paquete
-keep class com.example.myapplication.** { *; }
# Mantener todos los métodos públicos y protegidos en estas clases
-keepclassmembers class com.example.myapplication.** {
public protected *;
}
# Mantener todos los nombres de métodos nativos
-keepclassmembers class * {
native <methods>;
}
# Mantener todos los campos con el nombre especificado
-keepclassmembers class * {
private int myField;
}
# Mantener todas las clases que implementan Parcelable
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
# Mantener todas las clases Enum
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
# Mantener todas las anotaciones
-keepattributes *Annotation*
# Preservar todos los puntos de entrada (como métodos main)
-keep public class * {
public static void main(java.lang.String[]);
}
# Mantener todas las clases Serializable
-keep class * implements java.io.Serializable {
*;
}
Ofuscar el código fuente de Java con Dexguard.
Para habilitar Dexguard en su aplicación, puede agregar lo siguiente al archivo build.gradle:
buildTypes {
release {
minifyEnabled true
useProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
dexguard {
config 'dexguard-release.cfg'
}
}
}
Esto le indica a Gradle que use DexGuard para la ofuscación de código en la build de release. Puede crear un archivo "dexguard-project.txt" en el directorio "app" de la aplicación para configurar el proyecto DexGuard, y un archivo "dexguard-release.cfg" para configurar la ofuscación para la build de release.
De forma predeterminada, cuando habilita la ofuscación de código utilizando DexGuard, este utilizará sus propias reglas de ofuscación además de cualquier regla especificada en el archivo de configuración de ProGuard. Sin embargo, puede deshabilitar el uso de las reglas de ProGuard estableciendo la opción useProguard en false.
- Verificación del certificado de firma de la aplicación durante el tiempo de ejecución verificando
context.getPackageManager().signature - Verificar el instalador de la aplicación para asegurarse de que coincida con el Android Market llamando a
context.getPackageManager().getInstallerPackageName - Verificar el entorno de ejecución en tiempo de ejecución
Verificar si la aplicación se está ejecutando en un emulador
Puede agregar la siguiente verificación a su aplicación para detectar si se está ejecutando en un emulador.
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;
}
Verificar el indicador de depuración en tiempo de ejecución
De manera similar, puede verificar si la aplicación está en modo de depuración durante el tiempo de ejecución
context.getApplicationInfo().applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE;
Enlaces
Estándares
- 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