# Root Detection en Android moderno: Magisk, KernelSU y el problema de confiar en userspaceAnalizamos la evolución del root en Android, desde las detecciones tradicionales hasta KernelSU, y cómo diseñar una estrategia moderna basada en múltiples señales y riesgo.

<br>

<figure>
  <img src="/panda/images/root-detection-kernelsu-cover.png"
       alt="Root Detection en Android moderno - Magisk, KernelSU y userspace">
  <figcaption>
    Root Detection en Android moderno: la frontera de confianza entre userspace y kernel.
  </figcaption>
</figure>

# Root Detection en Android moderno: Magisk, KernelSU y el problema de confiar en userspace

Durante años, detectar si un dispositivo Android tenía privilegios de
root parecía un problema relativamente sencillo.

Buscar el binario `su`, comprobar determinadas rutas del sistema,
identificar paquetes conocidos o inspeccionar propiedades sospechosas
podía proporcionar señales suficientes para detectar muchos dispositivos
modificados.

El ecosistema Android, sin embargo, ha cambiado.

La aparición de técnicas *systemless*, herramientas como Magisk y
soluciones como KernelSU obligan a replantear una pregunta fundamental:

> **¿Hasta qué punto puede una aplicación confiar en las señales que
> obtiene del mismo dispositivo que intenta evaluar?**

La respuesta es especialmente relevante para aplicaciones de alto valor
o con requisitos elevados de seguridad.

------------------------------------------------------------------------

## Root detection ya no consiste simplemente en buscar `su`

Una implementación básica puede intentar determinar si existen elementos
conocidos:

``` text
¿Existe su?
¿Existen paquetes asociados a root?
¿Hay propiedades sospechosas?
¿Existen mounts anómalos?
¿El estado de arranque presenta señales inesperadas?
¿Existen procesos o artefactos conocidos?
¿Hay indicios de hooking o manipulación del runtime?
```

Todas estas comprobaciones pueden aportar información útil.

El problema aparece cuando las convertimos directamente en una decisión
binaria:

``` text
          Android App
               │
               ▼
      ┌───────────────────┐
      │  Root Detection   │
      └─────────┬─────────┘
                │
        ┌───────┴───────┐
        ▼               ▼
      CLEAN           ROOTED
        │               │
     permitir         bloquear
```

Root no debería entenderse únicamente como la existencia de un archivo
concreto.

Desde una perspectiva defensiva, debe entenderse como una modificación
del **modelo de confianza del dispositivo**.

------------------------------------------------------------------------

## El lugar desde donde observa una aplicación

Para comprender el problema resulta útil simplificar la arquitectura:

``` text
┌────────────────────────────────────┐
│          Android Application       │
├────────────────────────────────────┤
│     Android Framework / Runtime    │
├────────────────────────────────────┤
│     Native Libraries / Userspace   │
├────────────────────────────────────┤
│                                    │
│            Linux Kernel            │
│                                    │
├────────────────────────────────────┤
│              Hardware              │
└────────────────────────────────────┘
```

Una aplicación convencional se ejecuta en **userspace**.

Desde allí puede consultar archivos, paquetes instalados, propiedades,
información expuesta por `/proc`, mounts, APIs del framework y otras
características del entorno.

Estas observaciones tienen valor.

Pero existe un problema conceptual:

> **La aplicación está preguntando al mismo entorno cuya integridad
> intenta determinar.**

Si partes de ese entorno han sido modificadas o si una capa con mayores
privilegios puede alterar lo que las capas superiores observan, la
ausencia de una señal deja de constituir una prueba concluyente de que
el dispositivo sea confiable.

Esto no hace inútiles las comprobaciones locales.

Significa que debemos comprender sus límites.

------------------------------------------------------------------------

## Magisk y el cambio hacia systemless root

Las primeras técnicas de root frecuentemente implicaban modificaciones
relativamente visibles en las particiones del sistema.

Por ello, comprobaciones sobre rutas como:

``` text
/system/bin/su
/system/xbin/su
```

podían resultar útiles.

Magisk popularizó un enfoque diferente: **systemless root**.

De manera simplificada:

``` text
Root tradicional
       │
       ▼
modificaciones visibles
del sistema
       │
       ▼
detecciones relativamente
directas
```

frente a:

``` text
Magisk
       │
       ▼
systemless root
       │
       ▼
menor dependencia de
modificar /system
       │
       ▼
detección más compleja
```

Esto no hizo imposible detectar un entorno modificado.

Lo que hizo fue elevar la complejidad del problema y reducir el valor de
depender de una única evidencia.

Root detection comenzó a evolucionar desde:

``` text
buscar "su"
```

hacia la correlación de diferentes indicadores.

------------------------------------------------------------------------

# KernelSU: mover el problema hacia una capa más profunda

KernelSU resulta especialmente interesante porque cambia el lugar donde
se implementa una parte fundamental del mecanismo de privilegios.

Android utiliza el kernel de Linux como base. Las aplicaciones normales
viven en userspace y están sometidas a las restricciones que impone el
kernel.

KernelSU integra funcionalidad de administración de privilegios
directamente en el **kernel**.

Una representación conceptual sería:

``` text
                    USERSPACE

        ┌──────────────────────────┐
        │       Android App        │
        └──────────────────────────┘

        ┌──────────────────────────┐
        │ Android Framework / ART  │
        └──────────────────────────┘

        ┌──────────────────────────┐
        │ Native APIs / Libraries  │
        └──────────────────────────┘

──────────────── TRUST BOUNDARY ────────────────

                     KERNEL

        ┌──────────────────────────┐
        │       Linux Kernel       │
        │                          │
        │        KernelSU          │
        │                          │
        └──────────────────────────┘
```

Esto es importante porque el kernel se encuentra por debajo de userspace
y controla mecanismos fundamentales del sistema: procesos, permisos,
memoria, acceso a recursos y otras operaciones que las aplicaciones
terminan utilizando directa o indirectamente.

Una aplicación intenta observar el dispositivo **desde arriba**.

KernelSU introduce capacidades privilegiadas **desde una capa
inferior**.

Ese cambio modifica el *trust boundary*.

------------------------------------------------------------------------

## ¿Por qué esto puede complicar la detección?

Imaginemos una aplicación realizando diferentes comprobaciones:

``` text
                     APP
                      │
        ┌─────────────┼─────────────┐
        │             │             │
        ▼             ▼             ▼
   File System      /proc       Native APIs
        │             │             │
        └─────────────┼─────────────┘
                      │
                      ▼
                   Kernel
```

Muchas de las señales que recibe una aplicación dependen, directa o
indirectamente, del comportamiento del sistema operativo y del kernel.

Si el mecanismo que concede privilegios se encuentra precisamente en una
capa inferior a la aplicación, aparece una asimetría:

``` text
Aplicación
    │
    │ intenta observar
    ▼
Userspace
    │
    ▼
──────────────
Trust Boundary
──────────────
    │
    ▼
Kernel
    │
    └── mecanismo privilegiado
```

La aplicación no tiene una visión omnisciente del dispositivo.

Ve aquello que las interfaces disponibles para su nivel de privilegio le
permiten observar.

Por eso, mover una parte relevante del mecanismo de root hacia el kernel
puede reducir la eficacia de algunas suposiciones históricas basadas
exclusivamente en artefactos visibles desde userspace.

------------------------------------------------------------------------

## KernelSU no es simplemente "`su` dentro del kernel"

También conviene evitar una simplificación.

KernelSU no significa que todo lo relacionado con root desaparezca
mágicamente de userspace.

Un ecosistema de root puede involucrar componentes de administración,
configuración, módulos, procesos, estados del sistema u otros artefactos
que potencialmente proporcionen señales.

Por tanto:

> **KernelSU no debe considerarse automáticamente invisible o
> indetectable.**

La cuestión defensiva es otra.

Una detección que dependa únicamente de una firma estática, una ruta
concreta o un paquete conocido puede ser frágil frente a un modelo donde
el mecanismo fundamental de privilegios se encuentra en una capa
diferente.

Esto obliga a pensar en **correlación de señales**, no en una firma
mágica.

------------------------------------------------------------------------

## El problema no es solamente encontrar KernelSU

Desde la perspectiva de una aplicación de alto valor, el objetivo real
tampoco debería ser responder exclusivamente:

``` text
¿KernelSU está instalado?
```

Porque KernelSU es solamente una posible manifestación de un problema
más general:

``` text
¿Puede confiarse en el entorno de ejecución?
```

Una estrategia construida específicamente alrededor del nombre de una
herramienta corre el riesgo de quedar obsoleta cuando aparece otra
implementación.

Un enfoque más robusto intenta detectar **propiedades del entorno** y
cambios en su modelo de confianza.

------------------------------------------------------------------------

# El problema de confiar en userspace

Supongamos que una aplicación ejecuta:

``` kotlin
val rooted = checkRoot()
```

Internamente, `checkRoot()` podría consultar múltiples fuentes:

``` text
File System ─────────────┐
                        │
Package Manager ─────────┤
                        │
System Properties ───────┤
                        │
/proc ───────────────────┤
                        ├────► APP
Native APIs ─────────────┤
                        │
Mount information ───────┤
                        │
Process information ─────┘
```

Cada comprobación puede aportar evidencia.

Pero debe interpretarse bajo un principio:

> **Una señal obtenida desde un entorno potencialmente comprometido no
> debería convertirse por sí sola en una raíz absoluta de confianza.**

Esto tampoco significa que las comprobaciones locales sean inútiles.

Pueden elevar significativamente el coste de manipulación, detectar
configuraciones conocidas y proporcionar telemetría valiosa.

El problema aparece cuando toda la arquitectura depende exclusivamente
de ellas.

------------------------------------------------------------------------

# Root detection no debería ser un Boolean

Una simplificación habitual consiste en reducir la confianza del
dispositivo a:

``` text
isRooted = true
```

o:

``` text
isRooted = false
```

Un modelo defensivo más interesante considera múltiples dimensiones:

``` text
                DEVICE

                  │
       ┌──────────┼───────────┐
       │          │           │
       ▼          ▼           ▼

 Root signals   Boot state   App integrity

       │          │           │
       ├──────────┼───────────┤
       │          │           │
       ▼          ▼           ▼

 Hooking      Debugging    Runtime anomalies

       │          │           │
       └──────────┼───────────┘
                  │
                  ▼

             RISK ENGINE

                  │
        ┌─────────┼─────────┐
        ▼         ▼         ▼

       LOW      MEDIUM      HIGH

        │         │          │
      normal   challenge   restrict
```

La pregunta deja de ser:

> ¿El dispositivo tiene root?

y pasa a ser:

> **¿Cuánto puedo confiar en este dispositivo para realizar esta
> operación?**

El cambio parece pequeño.

Arquitectónicamente es enorme.

------------------------------------------------------------------------

## No todas las operaciones tienen el mismo riesgo

Una aplicación con requisitos elevados de seguridad puede realizar
acciones con sensibilidades muy distintas.

``` text
Operación A
Consulta de información
        │
        ▼
      Riesgo bajo


Operación B
Cambio de configuración sensible
        │
        ▼
      Riesgo medio


Operación C
Acción crítica o irreversible
        │
        ▼
      Riesgo alto
```

Bloquear completamente una aplicación por una única señal puede generar
falsos positivos.

Ignorar todas las señales del dispositivo puede ser todavía peor.

Una alternativa consiste en incorporar el estado del dispositivo dentro
de una evaluación de riesgo más amplia.

------------------------------------------------------------------------

# Integridad y attestation

Aquí aparece otra pieza importante del ecosistema Android moderno: los
mecanismos de **integrity y attestation**.

En lugar de confiar exclusivamente en comprobaciones locales, una
aplicación puede incorporar señales cuya validación forme parte de una
decisión realizada fuera del dispositivo.

Conceptualmente:

``` text
        ANDROID APP
             │
             │
       integrity token
             │
             ▼
          BACKEND
             │
       ┌─────┴─────┐
       │           │
       ▼           ▼
   Validación    Contexto
   integridad    de riesgo
       │           │
       └─────┬─────┘
             │
             ▼
          DECISIÓN
```

La idea importante no es sustituir todas las comprobaciones locales.

Es evitar que una operación crítica dependa exclusivamente de una
decisión tomada dentro del mismo entorno que estamos evaluando.

------------------------------------------------------------------------

# RASP y defensa en profundidad

Las soluciones de Runtime Application Self-Protection (RASP) pueden
aumentar la visibilidad sobre el entorno donde se ejecuta una
aplicación.

Una estrategia puede correlacionar señales relacionadas con:

``` text
Root detection
      +
Hook detection
      +
Debugger detection
      +
Tamper detection
      +
Runtime integrity
      +
Boot state
      +
Environment anomalies
```

Ninguna señal necesita ser perfecta individualmente para aportar valor.

Su utilidad aumenta cuando forma parte de una estrategia de **defensa en
profundidad**:

``` text
              APPLICATION
                   │
                   ▼
            Runtime controls
                   │
                   ▼
          Device integrity
                   │
                   ▼
             Attestation
                   │
                   ▼
              Backend
                   │
                   ▼
             Risk Engine
```

El objetivo no debería ser demostrar matemáticamente que un dispositivo
es seguro.

El objetivo es elevar el coste de manipulación y reducir progresivamente
la confianza cuando aparecen evidencias inconsistentes.

------------------------------------------------------------------------

# KernelSU no significa que root detection haya muerto

La aparición de mecanismos de root integrados más profundamente puede
llevar a conclusiones demasiado fuertes:

``` text
"KernelSU es indetectable"
```

o:

``` text
"Root detection ya no sirve"
```

Ambas afirmaciones simplifican excesivamente el problema.

KernelSU no elimina necesariamente todas las señales observables.

Lo que pone en evidencia es algo más interesante:

> **La seguridad basada únicamente en observaciones locales tiene
> límites inherentes cuando el entorno observado puede estar bajo el
> control de una capa con mayores privilegios.**

Una estrategia moderna puede combinar:

``` text
Root indicators
       │
Boot state
       │
Runtime protection
       │
App integrity
       │
Attestation
       │
Backend telemetry
       │
       ▼
   RISK DECISION
```

------------------------------------------------------------------------

# La confianza debería ser contextual

El dispositivo es solamente una parte del problema.

Una decisión de seguridad puede considerar:

``` text
Device Trust
      +
Application Integrity
      +
User Risk
      +
Session Risk
      +
Operation Risk
      +
Backend Signals
      │
      ▼
   DECISION
```

Una señal sospechosa no tiene por qué producir exactamente la misma
respuesta para todas las operaciones.

La arquitectura puede reaccionar proporcionalmente:

``` text
RIESGO BAJO
    │
    └── permitir


RIESGO MEDIO
    │
    └── verificación adicional


RIESGO ALTO
    │
    └── restringir operación


RIESGO CRÍTICO
    │
    └── bloquear / investigar
```

Este modelo convierte root detection en lo que realmente debería ser:

**una señal de riesgo, no necesariamente una decisión completa.**

------------------------------------------------------------------------

# Conclusión

La evolución desde las técnicas tradicionales de root hasta Magisk y
KernelSU muestra una característica fundamental de la seguridad Android:

**el modelo de amenazas evoluciona constantemente.**

Buscar `su` tuvo sentido.

Detectar modificaciones del sistema sigue teniendo sentido.

Analizar mounts, procesos, propiedades, hooking y anomalías de runtime
también tiene sentido.

Pero ninguna de estas señales debería interpretarse aisladamente como
una garantía absoluta.

KernelSU vuelve especialmente visible una pregunta que siempre ha
existido:

> **¿Hasta qué punto puede una aplicación confiar en las respuestas
> proporcionadas por el mismo dispositivo cuya integridad está
> intentando comprobar?**

Quizá por eso la pregunta correcta ya no sea:

> **¿Este dispositivo tiene root?**

sino:

> **¿Cuánto puedo confiar en este dispositivo para permitir esta
> operación?**

Ese cambio de perspectiva transforma root detection de una comprobación
binaria en un componente dentro de una arquitectura mucho más amplia de
seguridad.

------------------------------------------------------------------------

## Próxima investigación

En una segunda parte llevaremos este problema al laboratorio:

**KernelSU en laboratorio: ¿qué señales puede observar realmente una
aplicación Android?**

La idea será comparar un entorno Android convencional con diferentes
escenarios de modificación y observar qué información permanece
disponible desde la perspectiva defensiva de una aplicación.

Sin técnicas de evasión.

Solamente observación, instrumentación y evidencia.

**Research. Audit. Protect.**

--- PandaPandemio
