Controle de acesso baseado em permissões para componentes exportados

Categoria do OWASP: MASVS-PLATFORM - Interação com plataformas

Visão geral

Uma permissão do Android é um identificador de string declarado no manifesto do app para solicitar acesso a dados ou ações restritos, aplicados no ambiente de execução pelo framework do Android.

Os níveis de permissão do Android indicam o possível risco associado à permissão:

  • Normal: permissões de baixo risco, concedidas automaticamente no momento da instalação.
  • Perigosas: permissões de alto risco que podem permitir o acesso a dados sensíveis do usuário, exigindo a aprovação explícita do usuário no momento da execução.
  • Assinatura: concedida apenas a apps assinados com o mesmo certificado do app que declara a permissão, normalmente usada para apps do sistema ou interações entre apps do mesmo desenvolvedor.

Vulnerabilidades relacionadas a controles de acesso baseados em permissões ocorrem quando um componente de app (como atividade, broadcast receiver, provedor de conteúdo ou serviço) atende a todos os seguintes critérios:

  • O componente não está associado a nenhuma android:permission no Manifest.
  • O componente executa uma tarefa sensível para a qual existe uma permissão que o usuário já aprovou;
  • O componente é exportado.
  • O componente não realiza verificações manuais de permissão (no nível do manifesto ou do código).

Quando isso acontece, um app malicioso pode realizar ações sensíveis abusando dos privilégios do componente vulnerável, fazendo proxy dos privilégios do app vulnerável para o app malicioso.

Impacto

A exportação de componentes vulneráveis pode ser usada para acessar recursos sensíveis ou realizar ações sensíveis. O impacto desse comportamento indesejado depende do contexto do componente vulnerável e dos privilégios dele.

Mitigações

Exigir permissões para tarefas sensíveis

Ao exportar um componente com permissões sensíveis, exija essas mesmas permissões para qualquer solicitação recebida. O ambiente de desenvolvimento integrado do Android Studio tem verificações de lint para recebedores e serviços para detectar essa vulnerabilidade e recomendar a exigência das permissões adequadas.

Os desenvolvedores podem exigir permissões para solicitações recebidas declarando-as no arquivo Manifest ou no nível do código ao implementar o serviço, como nos exemplos a seguir.

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

    }
}

Não exportar o componente

Evite exportar componentes com acesso a recursos sensíveis, a menos que seja absolutamente necessário. Para fazer isso, defina android:exported no arquivo Manifest como false para o componente. A partir do nível 31 da API e mais recentes, esse atributo é definido como false por padrão.

XML

<activity
    android:name=".MyActivity"
    android:exported="false"/>

Aplicar permissões baseadas em assinatura

Ao compartilhar dados entre dois apps que você controla ou possui, use permissões baseadas em assinatura. Essas permissões não exigem a confirmação do usuário. Em vez disso, elas verificam se os apps que acessam os dados são assinados com a mesma chave de assinatura. Essa configuração oferece uma experiência do usuário mais simples e segura. Se você declarar permissões personalizadas, considere as diretrizes de segurança correspondentes.

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" />

Endpoints de tarefa única

Implemente seu app seguindo o princípio de design Separação de preocupações. Cada endpoint precisa executar apenas um pequeno conjunto de tarefas específicas com privilégios específicos. Essa boa prática de design também permite que o desenvolvedor aplique permissões detalhadas para cada endpoint. Por exemplo, evite criar um endpoint único que atenda a agenda e aos contatos.

Recursos