Categoría de OWASP: MASVS-PLATFORM: Interacción con la plataforma
Descripción general
Las apps para Android y el sistema Android pueden usar transmisiones como sistema de mensajería para notificar a otras apps sobre eventos que podrían interesarles. Las transmisiones persistentes son un tipo especial de transmisión para el cual los objetos de intent enviados permanecen en la caché después de que se completa la transmisión. El sistema puede volver a transmitir intents persistentes a los registros posteriores de receptores. Lamentablemente, la API de Sticky Broadcasts presenta una serie de deficiencias relacionadas con la seguridad, por lo que dejó de estar disponible en Android 5.0 (API nivel 21).
Cualquier persona puede acceder a transmisiones persistentes
Las transmisiones persistentes no se pueden restringir a receptores que tengan ciertos permisos. Por lo tanto, no son adecuadas para transmitir información sensible. Puede ser tentador pensar que especificar el nombre del paquete de la aplicación en la transmisión Intent
limita el conjunto de BroadcastReceivers
:
Kotlin
val intent = Intent("com.example.NOTIFY").apply {
setPackage("com.example.myapp")
}
applicationContext.sendBroadcast(intent)
Java
Intent intent = new Intent("com.example.NOTIFY");
intent.setPackage("com.example.myapp");
getApplicationContext().sendBroadcast(intent);
En el ejemplo, solo los receptores en el paquete de com.example.myapp
reciben el intent cuando se envía la transmisión. Sin embargo, el filtro del nombre del paquete no se aplica cuando el intent se vuelve a transmitir desde la caché persistente. Cuando se registra un receptor con el método registerReceiver()
, todos los intents de la caché persistente que coinciden con el filtro especificado se vuelven a transmitir al receptor, independientemente del nombre del paquete en el que resida el receptor.
Cualquier persona puede enviar transmisiones persistentes
Para enviar transmisiones persistentes, una app solo requiere el permiso android.permission.BROADCAST_STICKY
, que se otorga automáticamente cuando se instala la app. Por lo tanto, los atacantes pueden enviar cualquier intent a cualquier destinatario, lo que podría darles acceso no autorizado a otra app. Los receptores de emisión pueden restringir los remitentes a aquellos que tengan un determinado permiso. Sin embargo, al hacerlo, el receptor no puede recibir transmisiones de la caché persistente porque no se envían en el contexto de la identidad de ninguna app y no se transmiten con ningún permiso.
Cualquier persona puede modificar transmisiones persistentes
Cuando un intent forma parte de una transmisión persistente, el intent reemplaza todas las instancias anteriores que tengan la misma acción, datos, tipo, identificador, clase y categorías en la caché persistente. Por lo tanto, un atacante puede reemplazar trivialmente los datos adicionales en un intent persistente de una app legítima, que luego podría volver a transmitirse a otros receptores.
Las transmisiones enviadas con el método sendStickyOrderedBroadcast()
se entregan a un receptor a la vez para que los receptores con mayor prioridad consuman la transmisión antes de que se entregue a los receptores con menos prioridad. A medida que se ejecuta cada receptor, se puede propagar un resultado al siguiente receptor, como cuando se llama a setResultData()
, o se puede anular la transmisión, lo que evita que los receptores posteriores reciban la transmisión. Un atacante que puede recibir transmisiones persistentes ordenadas de una app legítima puede crear un receptor de prioridad alta para manipular los datos de los resultados de la transmisión o descartar las transmisiones por completo.
Impacto
El impacto varía según cómo se usen las transmisiones persistentes y qué datos se pasen a los receptores de emisión. En términos generales, el uso de transmisiones persistentes puede generar la exposición de datos sensibles, la manipulación de datos, el acceso no autorizado a ejecutar un comportamiento en otra app y la denegación del servicio.
Mitigaciones
No se deben usar transmisiones persistentes. El patrón recomendado es usar transmisiones no persistentes con otro mecanismo, como una base de datos local, para recuperar el valor actual cuando lo desees.
Los desarrolladores pueden controlar quién puede recibir transmisiones no persistentes mediante permisos o con la configuración del nombre del paquete de la aplicación en el intent. Además, si no es necesario enviar una transmisión a los componentes fuera de una app, usa LiveData
, que implementa el patrón del observador.
Puedes encontrar más información sobre cómo proteger las transmisiones en la página de descripción general de las transmisiones.