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 riesgo potencial asociado con el permiso:
- Normal: Permisos de bajo riesgo que se otorgan automáticamente en el momento de la instalación
- Riesgosos: 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 las apps del sistema o las interacciones entre apps del mismo desarrollador.
Las vulnerabilidades relacionadas con los controles de acceso basados en permisos se producen cuando un componente de la app (como una actividad, un receptor, un proveedor de contenido o un servicio) cumple con todos los siguientes criterios:
- El componente no está asociado a ningún
android:permissionen elManifest. - El componente realiza una tarea sensible para la que existe un permiso que el usuario ya aprobó.
- El componente se exporta.
- El componente no realiza ninguna verificación manual de permisos (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 transfiriendo los privilegios de la app vulnerable a 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
Cómo solicitar permisos para tareas sensibles
Cuando exportes un componente con permisos sensibles, exige 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 soliciten los permisos adecuados.
Los desarrolladores pueden exigir permisos para las solicitudes entrantes declarándolos en el archivo Manifest o a nivel del 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 exportar el componente
Evita exportar componentes con acceso a recursos sensibles, a menos que sea absolutamente necesario. Para lograr esto, configura android:exported en el archivo Manifest como false para tu componente. A partir del nivel de API 31, este atributo se establece en falsede 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 tareas únicas
Implementa tu app siguiendo el principio de diseño de Separación de responsabilidades. Cada extremo solo debe realizar un pequeño conjunto de tareas específicas con privilegios específicos. Esta práctica de buen diseño también permite que el desarrollador aplique permisos detallados para cada extremo. Por ejemplo, evita crear un solo extremo que proporcione tanto el calendario como los contactos.
Recursos
- Android Access to app protected components from the Oversecured blog (Acceso a componentes protegidos de la app en Android, del blog de 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 sobre permisos de Android
- Sugerencias de seguridad para receptores de transmisiones de Android
- Sugerencias de seguridad para los servicios de Android
- El valor predeterminado de Android 12 (API 31) se estableció en "false"
- Comprobación de lint: No se debe exportar PreferenceActivity exportada
- Comprobación de Lint: El receptor exportado no requiere permiso
- Lint Check: Exported Service doesn't require permission