Root Detection en aplicaciones móviles — métodos de detección y principio de funcionamiento

Autor: IT Sectr Publicado: 2026-04-03 Tiempo de lectura: 9 min

Root Detection es un mecanismo de seguridad que protege las aplicaciones Android de ejecutarse en dispositivos con privilegios de superusuario. Las aplicaciones bancarias, de pago y empresariales bloquean o restringen la funcionalidad en dispositivos rooteados, ya que el acceso root elimina las restricciones del sandbox de Android y abre la posibilidad de interceptar tráfico, leer la memoria de procesos y manipular datos. Según OWASP Mobile Top 10 (2024), la ausencia de Root Detection pertenece a la categoría M8 (Security Decisions via Untrusted Inputs). Root Detection se basa en una combinación de verificaciones estáticas del sistema de archivos y análisis dinámico del comportamiento en tiempo de ejecución.

Puntos clave

  • Root Detection — verificación de un dispositivo Android para detectar acceso root y proteger la aplicación de ejecutarse en un entorno comprometido
  • Métodos estáticos revisan el sistema de archivos en busca de binarios su, aplicaciones Superuser y cambios en las particiones del sistema
  • Métodos dinámicos analizan el runtime: verificación de Build.TAGS, intento de abrir /proc/self/maps con procesos privilegiados
  • Implementación nativa en C/C++ mediante JNI proporciona resistencia a la evasión a través de Xposed y Frida a nivel de Java
  • Seguridad Root Detection requiere ofuscación continua y verificación del lado del servidor para evitar la manipulación de los resultados

¿Qué es Root Detection?

Root Detection es un mecanismo de software que detecta la presencia de acceso root en un dispositivo Android. El acceso root proporciona control total sobre el sistema operativo, permitiendo que aplicaciones y scripts ejecuten comandos con UID 0. En un dispositivo rooteado, se pierde el aislamiento de aplicaciones (Android Sandbox), lo que hace posible interceptar la entrada del teclado, leer bases de datos SQLite de otras aplicaciones, inyectar código en procesos y sustituir certificados SSL en el almacén de confianza.

Para las aplicaciones financieras y empresariales, operar en un dispositivo rooteado presenta un riesgo inaceptable: un atacante obtiene acceso a tokens, claves de sesión y datos personales. Los reguladores, incluido el PCI Security Standards Council, exigen que las aplicaciones de pago detecten y respondan al acceso root. En respuesta, los desarrolladores de Android integran Root Detection como parte de una estrategia de protección proactiva.

Existen dos enfoques para la detección: estático, que analiza el sistema de archivos y los paquetes instalados, y dinámico, que realiza verificaciones en tiempo de ejecución. El enfoque combinado se considera el más confiable, ya que cubre diferentes vectores de evasión. Según un estudio de NowSecure (2025), el 76% de las aplicaciones bancarias en el top 100 de Google Play contienen alguna forma de Root Detection.

Métodos estáticos de detección de root

Los métodos estáticos se ejecutan al iniciar la aplicación y verifican signos de acceso root dejados por las herramientas de rooteo en el sistema de archivos. Estos métodos no requieren ejecutar comandos privilegiados y funcionan dentro del contexto de una aplicación normal.

Verificación de la existencia del binario su

El principal indicador de acceso root es la presencia del archivo ejecutable su en rutas estándar: /system/bin/su, /system/xbin/su, /sbin/su, /su/bin/su. La aplicación verifica la existencia del archivo mediante File.exists() o una implementación nativa de access() de libc. Adicionalmente, se puede intentar ejecutar su --version o su -c id y verificar el código de salida.

Búsqueda de gestores de root

Aplicaciones típicas para gestionar el acceso root: Superuser, SuperSU, Magisk Manager, KingRoot. Su presencia se verifica mediante PackageManager.getPackageInfo() o leyendo el directorio /data/app/. Paquetes a verificar: com.topjohnwu.magisk, eu.chainfire.supersu, com.noshufou.android.su, com.thirdparty.superuser, com.koushikdutta.superuser, com.zacharee1.systemuituner.

Verificación de propiedades del sistema

Android almacena información sobre el estado del sistema en propiedades del sistema, accesibles mediante System.getProperty y Build.TAGS. Si Build.TAGS contiene test-keys en lugar de release-keys, esto indica un firmware personalizado, a menudo con acceso root. Adicionalmente, se verifican ro.build.tags, ro.debuggable y ro.secure leyendo /system/build.prop.

java
public class RootDetectionChecker {
    private static final String[] SU_PATHS = {
        "/system/bin/su",
        "/system/xbin/su",
        "/sbin/su",
        "/su/bin/su",
        "/system/sd/xbin/su"
    };

    public boolean checkRootByFiles() {
        for (String path : SU_PATHS) {
            if (new File(path).exists()) {
                return true;
            }
        }
        return false;
    }

    public boolean checkRootByPackages(Context ctx) {
        String[] packages = {
            "com.topjohnwu.magisk",
            "eu.chainfire.supersu",
            "com.noshufou.android.su",
            "com.koushikdutta.superuser"
        };
        for (String pkg : packages) {
            try {
                ctx.getPackageManager().getPackageInfo(pkg, 0);
                return true;
            } catch (PackageManager.NameNotFoundException e) {
                // package not found
            }
        }
        return false;
    }
}

Métodos dinámicos de verificación

Los métodos dinámicos se ejecutan durante el funcionamiento de la aplicación y analizan el entorno de ejecución. A diferencia de los estáticos, pueden detectar el rooteo oculto mediante Magisk Hide o Zygisk, ya que verifican el comportamiento del sistema y no solo la estructura de archivos.

Verificación de puntos de montaje

Con acceso root, algunas particiones del sistema se montan con el flag rw (read-write) en lugar de ro (read-only). La aplicación lee /proc/mounts y verifica que /system esté montado como ro. Si /system está montado como rw, esto indica un sistema modificado. Adicionalmente, se verifica la presencia del montaje de /su mediante Magisk.

Prueba de modo seguro

El modo seguro de Android desactiva las aplicaciones de terceros, incluidos los gestores de root. Una implementación correcta de Root Detection puede verificar si el dispositivo está funcionando en modo seguro. Si la aplicación detecta que los gestores de root no son visibles pero el binario su existe, esto es un indicador de Magisk Hide.

Verificación de ejecución de comandos

Intentar ejecutar su -c id mediante ProcessBuilder o Runtime.exec es una prueba directa de acceso root. Sin embargo, Magisk puede interceptar esta llamada. Un enfoque más confiable es la verificación mediante código nativo: abrir /proc/1/limits o /proc/self/maps y analizar el UID de los procesos en ejecución. Si la aplicación puede obtener UID 0 o leer archivos accesibles solo para root, el dispositivo está comprometido.

java
public boolean checkRootDynamically() {
    // Build flags check
    String buildTags = Build.TAGS;
    if (buildTags != null && buildTags.contains("test-keys")) {
        return true;
    }

    // Checking /system mount
    try {
        BufferedReader reader = new BufferedReader(
            new InputStreamReader(new FileInputStream("/proc/mounts"))
        );
        String line;
        while ((line = reader.readLine()) != null) {
            if (line.contains("/system")
                && line.contains("rw")) {
                reader.close();
                return true;
            }
        }
        reader.close();
    } catch (IOException e) {
        // error reading mounts
    }

    return false;
}

Implementación nativa de Root Detection en C++

Root Detection implementado en Java se evade fácilmente mediante módulos de Xposed o Frida, que interceptan métodos Java y sustituyen los valores de retorno. La implementación nativa en C++ mediante JNI es significativamente más resistente: las herramientas de análisis dinámico que operan a nivel de Java no ven las llamadas nativas de libc como stat, access, popen y dlopen.

cpp
#include <unistd.h>
#include <sys/stat.h>
#include <cstring>
#include <vector>

extern "C"
JNIEXPORT jboolean JNICALL
Java_com_example_checker_RootCheck_nativeCheck(
    JNIEnv* env, jobject instance) {

    std::vector<const char*> paths = {
        "/system/bin/su",
        "/system/xbin/su",
        "/sbin/su",
        "/data/local/su"
    };

    struct stat st;
    for (const char* path : paths) {
        if (stat(path, &st) == 0) {
            return JNI_TRUE;
        }
    }
    return JNI_FALSE;
}

La verificación nativa no utiliza la API de Java, lo que la hace invisible para las herramientas de evasión que operan a nivel de Dalvik/ART. Para protección adicional, se recomienda almacenar las constantes (lista de rutas) no en una sección de solo lectura, sino calcularlas mediante funciones reversibles simples. La llamada stat de libc accede directamente al kernel de Linux, omitiendo las envolturas de Java, y no puede ser interceptada mediante Xposed.

Métodos de evasión de Root Detection

Los desarrolladores de protección deben comprender los métodos de evasión existentes para construir un sistema de detección robusto. Cada método de evasión requiere una contramedida en el nivel correspondiente.

Evasión mediante Magisk Hide y Zygisk

Magisk es la herramienta de rooteo más popular en Android 9–14. Magisk Hide oculta la presencia de su de /proc y suplanta los resultados de verificación de rutas. Magisk opera a nivel de kernel e intercepta stat() y access() antes de que la aplicación los vea. Contramedida: verificar la presencia de Magisk mediante la existencia de /sbin/.magisk o verificando mediante la lectura de los propios maps de la aplicación — Magisk inyecta su biblioteca en cada proceso.

Evasión mediante Frida

Frida es una herramienta de instrumentación dinámica que puede interceptar funciones nativas mediante Ptrace o Dobby. Frida reemplaza el valor de retorno de cualquier verificación, suplantando el resultado de stat a ENOENT. Contramedida: verificar la integridad de las funciones nativas mediante el cálculo de la suma de verificación de las instrucciones en memoria y detectar Frida mediante el análisis de /proc/self/maps para detectar la presencia de frida-agent.so o frida-helper.

Evasión mediante parcheo del APK

Root Detection implementado en Java se elimina en 2–3 minutos: el APK se descompila con apktool, en el código smali se cambia el valor de retorno del método a false, el APK se recompila y se firma. Contramedida: trasladar la lógica crítica al código nativo y verificar la firma digital de la aplicación en tiempo de ejecución mediante la API de Signature o comparando el hash del APK con una referencia en el servidor.

Recomendaciones para una protección confiable

Root Detection efectivo se construye sobre una arquitectura multicapa. Ningún método por sí solo proporciona suficiente protección. La combinación de verificaciones estáticas y dinámicas, código nativo y verificación del lado del servidor proporciona la máxima resistencia.

Verificación del lado del servidor

No confíe únicamente en la verificación del lado del cliente. Envíe los resultados de Root Detection al servidor junto con un token de sesión de un solo uso. El servidor decide si bloquear o restringir la funcionalidad. Esto previene ataques a nivel de API, donde la aplicación cliente puede ser modificada mientras el servidor sigue siendo una parte confiable.

Ofuscación del código

El código de Root Detection debe estar ofuscado. Si un atacante ve una secuencia clara de verificaciones de rutas su en jadx, la evasión tomará minutos. Use ProGuard o DexGuard para ofuscar el flujo de control y cifrar las cadenas. La ofuscación aumenta el tiempo de análisis del código de protección de minutos a horas.

Actualización regular de firmas

La lista de rutas, paquetes e indicadores verificados debe actualizarse con cada versión de la aplicación. Nuevas herramientas de rooteo y evasión aparecen mensualmente. Una lista estática que no ha cambiado en un año no detectará métodos modernos. Se recomienda cargar firmas actualizadas desde el servidor al iniciar la aplicación antes de realizar las verificaciones.

Preguntas frecuentes

¿Por qué las aplicaciones necesitan Root Detection?

Root Detection protege contra la ejecución de una aplicación en un dispositivo donde el sandbox de Android está desactivado. En un dispositivo rooteado, cualquier aplicación puede leer datos de otras aplicaciones. Las aplicaciones bancarias y de pago están obligadas a bloquear el funcionamiento en dispositivos rooteados según los requisitos de PCI DSS y las recomendaciones de OWASP Mobile Security.

¿Cómo funciona Magisk Hide?

Magisk Hide utiliza un mecanismo de montaje de espacios de nombres (mount namespace). Para cada proceso en la lista de exclusión, Magisk crea un namespace aislado donde el binario su es invisible. Las llamadas al sistema stat, access y open en este namespace no ven los archivos de Magisk. Magisk se puede detectar verificando la presencia de /proc/self/maps y buscando volcados de magisk.

¿Se puede evadir Root Detection sin root?

Sí, si la aplicación no verifica la integridad de su código. Mediante Frida, se puede interceptar el método Java de verificación y forzarlo a devolver false. La contramedida es una implementación nativa de la lógica crítica en C++ y la verificación de integridad mediante el hash del archivo DEX. Sin ofuscación, cualquier Root Detection en Java se evita en 5–10 minutos.

¿Qué es SafetyNet y la atestación?

SafetyNet (obsoleto) y Play Integrity API son verificaciones del lado del servidor de Google que confirman la integridad del dispositivo. Incluyen la verificación del bootloader, la firma del sistema y el estado de root. Play Integrity API es el reemplazo recomendado de SafetyNet, que proporciona tres niveles: BASIC, DEVICE y STRONG. Root Detection en el cliente complementa la atestación del servidor.

¿Cómo probar Root Detection en tu aplicación?

Instale la aplicación en un dispositivo rooteado real (por ejemplo, un Pixel con Magisk). Verifique si se activa el bloqueo. Luego intente ocultar el root mediante Magisk Hide para su aplicación y reinicie la prueba. Para una verificación exhaustiva, use Frida para interceptar los métodos objetivo y asegúrese de que la protección nativa no pueda ser evadida.

Resumen

  • Root Detection es un componente de seguridad obligatorio para aplicaciones Android bancarias, de pago y empresariales, que funciona mediante una combinación de verificaciones estáticas y dinámicas
  • Métodos estáticos incluyen la búsqueda del binario su en rutas estándar, la verificación de gestores de root instalados y el análisis de las propiedades del sistema Build.TAGS
  • Métodos dinámicos analizan el montaje de /system en modo rw, verifican la integridad de /proc/mounts y realizan pruebas de ejecución de comandos privilegiados
  • Implementación nativa en C++ mediante JNI hace que las verificaciones sean invisibles para Xposed y Frida que operan a nivel de Java, requiriendo evasión mediante Dobby o Ptrace
  • Magisk Hide es la herramienta principal para evadir Root Detection mediante mount namespaces, detectable mediante el análisis de /proc/self/maps en busca de bibliotecas de magisk
  • Arquitectura recomendada: verificaciones nativas + ofuscación de código + verificación de resultados del lado del servidor + actualización regular de firmas
  • Play Integrity API de Google complementa Root Detection del lado del cliente con atestación del dispositivo del lado del servidor, proporcionando una protección integral

Desarrollaremos una aplicación móvil llave en mano

IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.

Discutir el proyecto

Lea también