Tenemos nuestro móvil Android y queremos trastear su hardware y sacarle más provecho, ¿por qué Android no nos permite acceder a todo el hardware?
Android utiliza un sistema de permisos basado en el principio de "privilegio mínimo necesario", controlando el acceso a recursos y funciones críticas del sistema. Este sistema está diseñado para garantizar la seguridad y la integridad del sistema operativo. Las versiones principales de Android se pueden distinguir en dos tipos de compilaciones, las compilaciones de desarrollo, destinadas a ingenieros y desarrolladores, que incluyen herramientas de depuración, acceso root y otras configuraciones para facilitar el desarrollo y la depuración. Tienen ninguna o pocas restricciones de seguridad. Y la compilación de dispositivo comercial destinada al usuario final, cuya consulta “getprop ro.build.type” en una consola como “adb shell” devuelve “user”. Cuenta con todas las restricciones de seguridad y no incluye herramientas de depuración. Por esta razón nuestro móvil no nos permite acceder a todo el hardware.
¿Cómo
podemos ganar privilegios? ¿Cómo podemos obtener
acceso root? Obtener
el root en dispositivos que son comerciales es sencillo cuando se
puede desbloquear el bootloader, pero puede ser un desafío en los
otros casos en lo que no se puede desbloquear. En sistemas dónde el
bootloader
es desbloqueable
se puede flashear la partición system
por
una que
cambie el sistema operativo de una versión comercial a una versión
de desarrollo, habilitando el acceso root. Esto se consigue
modificando las
propiedades ro.secure
y
ro.debuggable
en
el
fichero “build.prop”.
ro.secure: Esta propiedad determina si el sistema se inicia en modo seguro. Siro.secureestá configurado como "1", el sistema se inicia en modo seguro, lo que significa que ciertas funcionalidades de depuración y acceso root pueden estar deshabilitadas o restringidas.ro.debuggable: Esta propiedad indica si el sistema está configurado para ser depurable.Alconfigurarlocomo "1", se permite la depuración del sistema. En una compilación de usuario final comercial,esta propiedad estáconfigurada como "0" para mejorar la seguridad.
Hay que tener en cuenta que desbloquear el bootloader provocará que la partición /data se borre, y que algunos bootloaders iniciarán un flag permanente indicando que el bootloader ha sido modificado, además este flag permanecerá incluso si se vuelve a bloquear.
Al arrancar el sistema operativo con esta modificación en la partición System estaremos produciendo un cambio similar a como funciona una compilación de desarrollo y esto nos permite habilitar el acceso root. Al ejecutar “adb root” estaremos consiguiendo una shell root. Además se puede instalar el binario “su”, asignándole el bit SUID y permitiendo el cambio al usuario root directamente.
Puede
ocurrir que la distribución comercial Android de nuestro móvil haya
sido compilada sin definir la macro relativa al demonio adbd
“ALLOW_ADBD_ROOT”
que provoca que se ignoren
las
propiedades
ro.secure
y
ro.debuggable,
no permitiendo el acceso root.
Si
ALLOW_ADBD_ROOT
está definido, el demonio adbd
permitirá el acceso root.
En
esta situación aun nos quedaría el binario “su”,
que habríamos agregado con el bit
SUID, permitiendo
el acceso root no solo desde la shell, sino también desde
aplicaciones de terceros. Sin
embargo las versiones actuales de Android tienen restricciones que
impiden que las aplicaciones ejecuten binarios SUID, lo que limita la
capacidad de las aplicaciones para elevar privilegios. Y
desde hace unos años montan
la partición System
con
la bandera nosetuid,
lo
que deshabilita
el
uso del bit
SUID.
También
tenemos el sistema
de control de acceso obligatorio (MAC) SELinux (Security-Enhanced
Linux) que impone políticas de seguridad en el sistema. Por
lo que incluso
obteniendo acceso root, el proceso seguirá
estando bajo
las
políticas de seguridad definidas por SELinux.
Por otro lado Zygote es un componente que inicia junto al arranque de Android. Realiza tareas de inicialización y carga recursos comunes que son compartidos por varias aplicaciones. Cuando se lanza una nueva aplicación, Zygote crea un nuevo proceso hijo a partir de sí mismo. Este proceso hijo hereda el estado inicializado de Zygote, lo que acelera el tiempo de inicio de la aplicación. Zygote evita tener que cargar e inicializar recursos comunes cada vez que arranca una nueva aplicación, mejorando el tiempo de inicio de las aplicaciones y optimizando el uso de recursos del sistema. Zygote ayuda a acelerar el inicio de aplicaciones, pero cada aplicación se ejecuta en su propio proceso independiente. Además los procesos creados a partir de Zygote inician su ejecución con un conjunto limitado de capacidades, lo que refuerza la seguridad limitando las acciones que pueden realizar.
En las versiones más antiguas de Android existía un método para conseguir el root mediante instalaciones Over-The-Air (OTA). Este método necesita de un recovery personalizado como TWRP ya que el recovery oficial del móvil sólo permite instalar OTA firmadas por el fabricante. Por lo que también necesita tener desbloqueado el bootloader para poder instalar el recovery personalizado. El método para escalar privilegios con una instalación OTA consiste en modificar el sistema de archivos. El paquete suele constar de binarios para la arquitectura ARM y x86, scripts para instalar demonios y el binario “su”, además suele haber una .apk que administra los permisos para el resto de aplicaciones. Básicamente lo que ocurre es que se copia el binario “su” y los demonios correspondientes a la partición system, y se configuran los permisos y las etiquetas de seguridad SELinux para poder ejecutar la elevación de privilegios.
En la actualidad, Android implementa otras medidas de seguridad además de las ya comentadas, para prevenir el acceso root no autorizado. Entre estas medidas están, la verificación de integridad del sistema (Verified Boot) que verifica que solo se cargue el firmware firmado digitalmente en el momento del arranque. Si detecta que una partición ha sido modificada, el sistema puede mostrar un mensaje de advertencia al usuario o simplemente rechazar el arranque, dependiendo de la implementación específica del fabricante. Otra de las características de seguridad que incorpora Android es montar particiones críticas como de solo lectura.
Desde hace unos años también incluye SafetyNet API, una medida de seguridad que permite a las aplicaciones verificar la integridad del dispositivo, verificando el estado del bootloader, la existencia de permisos de root y la detección de indicadores de compromiso que podrían indicar que el dispositivo ha sido rooteado o modificado. Esta API es utilizada por aplicaciones sensibles a la seguridad, como servicios bancarios y de pago, para determinar si el dispositivo permanece en un estado seguro y es confiable.
Con todas estás medidas de
seguridad, las
aplicaciones de rooteo tienen
que conseguir el root sin modificar las particiones del sistema
directamente. Lo consiguen
utilizando técnicas de inyección en el proceso Zygote, de esta
forma producen
modificaciones en tiempo de ejecución sin cambiar permanentemente el
sistema, aplicando
cambios como el remonte
de la
partición del sistema en
modo lectura y escritura
(mount -o remount,exec,dev,suid,rw
/partición)
temporalmente para aplicar modificaciones necesarias. Con
estas propiedades surge
la técnica "Systemless root" con la que las modificaciones
necesarias para obtener acceso root y realizar otras
personalizaciones se aplican en el espacio de usuario en lugar de
modificar directamente las particiones de solo lectura. Estas
modificaciones pueden incluir la instalación de binarios y archivos
necesarios para el acceso root, así como la aplicación de parches
en tiempo de ejecución para eludir restricciones. El
espacio de usuario es donde se ejecutan las aplicaciones y los
procesos del usuario. Este espacio es independiente de las
particiones del sistema y generalmente es de lectura y escritura.
Actualmente las
aplicaciones de rooteo ocultan
el acceso root a las
aplicaciones que hacen uso de
SafetyNet.
Existen otra forma de escalar privilegios aprovechando la explotación de vulnerabilidades, fallos o configuraciones inseguras en aplicaciones que se ejecutan como root en el propio sistema. Se puede hacer uso de vulnerabilidades del kernel Linux para conseguir el root, como hace la aplicación TowelRoot. Otras aplicaciones hacen uso de vulnerabilidades conocidas y no parcheadas en el dispositivo. El uso de zero-days es menos frecuente, pero puede ser usados con fines de infiltración y ganancia de privilegios.
La ganancia de privilegios es algo delicado y debe estar auditada en el proceso de instalación. Los instaladores de fuentes desconocidas pueden contener malware que con el poder del root puede ser catastrófico. Puede contener rootkit que sean indetectable para las medidas de seguridad estándar que hemos citado anteriormente, permaneciendo oculto y parasitando el dispositivo móvil para fines nocivos. Por eso siempre debemos conocer quien es la fuente y saber que es lo que hace en nuestro sistema. Actualmente la aplicación más usada es Magisk y su sitio oficial en github es https://github.com/topjohnwu/Magisk.
Magisk utiliza un enfoque Systemless root, por lo que las modificaciones del sistema las realiza en el espacio de usuario. Desde la versión 22 de Magisk, lanzada en febrero de 2021, el método de instalación consiste sólo en descargarse una única apk que es a su vez un paquete zip flasheable desde un recovery personalizado como TWRP.
Se instala la aplicación Magiskapp y al abrirla comprueba si el móvil tiene el “ramdisk” en la partición de arranque (boot). El "ramdisk" (disco RAM) en la partición de arranque (boot partition) es una parte del sistema de archivos que se carga en la memoria RAM durante el proceso de arranque. Sus funciones son la inicialización del hardware, la carga de módulos de kernel, la configuración de parámetros del sistema, y la ejecución de scripts de inicio. Magisk se instala en la partición de arranque y modifica el ramdisk, específicamente el archivo init, que es el script de inicio del sistema. Magisk utiliza el ramdisk para implementar la ocultación del acceso root, y para realizar un bypass de SafetyNet, engañando a las verificaciones de seguridad para que ciertas aplicaciones no detecten el estado de root.
