Categoría de OWASP: MASVS-PLATFORM: Interacción con la plataforma
Descripción general
Un permiso de Android es un identificador de cadena declarado en el manifiesto de la app para solicitar acceso a datos o acciones restringidos, que el framework de Android aplica en el tiempo de ejecución.
Los niveles de permisos de Android indican el posible riesgo asociado con el permiso:
- Normal: Son permisos de bajo riesgo que se otorgan automáticamente en el momento de la instalación.
- Peligrosos: Son permisos de alto riesgo que podrían permitir el acceso a datos sensibles del usuario y que requieren la aprobación explícita del usuario durante el tiempo de ejecución.
- Firma: Se otorga solo a las apps firmadas con el mismo certificado que la app que declara el permiso, por lo general, se usa para apps del sistema o interacciones entre apps del mismo desarrollador.
Las vulnerabilidades relacionadas con los controles de acceso basados en permisos ocurren cuando el componente de una app (como la actividad, el receptor, el proveedor de contenido o el servicio) cumple con todos los siguientes criterios:
- El componente no está asociado con ningún
android:permission
en elManifest
. - El componente realiza una tarea sensible para la que existe un permiso que el usuario ya aprobó.
- Se exporta el componente.
- El componente no realiza ninguna verificación de permisos manual (a nivel del manifiesto o del código).
Cuando esto sucede, una app maliciosa puede realizar acciones sensibles abusando de los privilegios del componente vulnerable y usando un proxy para los privilegios de la app vulnerable en la app maliciosa.
Impacto
La exportación de componentes vulnerables se puede usar para obtener acceso a recursos sensibles o realizar acciones sensibles. El impacto de este comportamiento no deseado depende del contexto del componente vulnerable y sus privilegios.
Mitigaciones
Exige permisos para tareas sensibles
Cuando exportes un componente con permisos sensibles, requiere esos mismos permisos para cualquier solicitud entrante. El IDE de Android Studio tiene verificaciones de lint para receptores y servicios para detectar esta vulnerabilidad y recomendar que se requieran los permisos adecuados.
Los desarrolladores pueden requerir permisos para las solicitudes entrantes declarándolos en el archivo Manifest
o a nivel de código cuando implementan el servicio, como en los siguientes ejemplos.
XML
<manifest ...>
<uses-permission android:name="android.permission.READ_CONTACTS" />
<application ...>
<service android:name=".MyExportService"
android:exported="true"
android:permission="android.permission.READ_CONTACTS" />
</application>
</manifest>
Kotlin
class MyExportService : Service() {
private val binder = MyExportBinder()
override fun onBind(intent: Intent): IBinder? {
// Enforce calling app has the required permission
enforceCallingPermission(Manifest.permission.READ_CONTACTS, "Calling app doesn't have READ_CONTACTS permission.")
// Permission is enforced, proceed with export logic
return binder
}
// Inner class for your Binder implementation
private inner class MyExportBinder : Binder() {
// Permission is enforced, proceed with export logic
}
}
Java
public class MyExportService extends Service {
@Override
public IBinder onBind(Intent intent) {
// Enforce calling app has the required permission
enforceCallingPermission(Manifest.permission.READ_CONTACTS, "Calling app doesn't have READ_CONTACTS permission.");
return binder;
}
// Inner class for your Binder implementation
private class MyExportBinder extends Binder {
// Permission is enforced, proceed with export logic
}
}
No exportes el componente.
Evita exportar componentes con acceso a recursos sensibles, a menos que sea absolutamente necesario. Para lograrlo, configura el android:exported
del archivo Manifest
como false
para tu componente. A partir del nivel de API 31, este atributo se establece en false
de forma predeterminada.
XML
<activity
android:name=".MyActivity"
android:exported="false"/>
Aplica permisos basados en firmas
Cuando compartes datos entre dos apps que controlas o posees, usa permisos basados en firmas. Estos permisos no requieren la confirmación del usuario y, en cambio, comprueban que la app que accede a los datos esté firmada con la misma clave. Esta configuración ofrece una experiencia del usuario más segura y simplificada. Si declaras permisos personalizados, ten en cuenta los lineamientos de seguridad correspondientes.
XML
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapp">
<permission android:name="my_custom_permission_name"
android:protectionLevel="signature" />
Extremos de una sola tarea
Implementa tu app siguiendo el principio de diseño de separación de preocupaciones. Cada extremo solo debe realizar un pequeño conjunto de tareas específicas con privilegios específicos. Esta práctica de diseño también permite al desarrollador aplicar permisos detallados para cada extremo. Por ejemplo, evita crear un extremo único que entregue el calendario y los contactos.
Recursos
- Acceso de Android a componentes protegidos de apps del blog Oversecured
- Prácticas recomendadas para proveedores de contenido
- Permisos de tiempo de ejecución (peligrosos)
- Principio de diseño de separación de problemas
- Documentación de permisos de Android
- Sugerencias de seguridad para receptores de emisión de Android
- Sugerencias de seguridad para los servicios de Android
- Android 12 (nivel de API 31) exportó el valor predeterminado establecido en "false"
- Comprobación de lint: No se debe exportar PreferenceActivity exportada
- Comprobación de lint: El receptor exportado no requiere permiso
- Comprobación de lint: El servicio exportado no requiere permiso