Permissões personalizadas

Categoria do OWASP: MASVS-CODE - Qualidade do código

Visão geral

Os riscos associados a permissões personalizadas surgem quando a definição de permissões personalizadas está ausente ou com erros de digitação ou quando o atributo android:protectionLevel correspondente é usado incorretamente no manifesto.

Por exemplo, esses riscos podem ser explorados criando uma permissão personalizada com o mesmo nome, mas definida por um app malicioso e com diferentes níveis de proteção aplicados.

As permissões personalizadas são projetadas para permitir o compartilhamento de recursos e capabilities com outros apps. Confira alguns exemplos de uso legítimo de permissões personalizadas:

  • Controlar a comunicação entre processos (IPC, na sigla em inglês) entre dois ou mais apps
  • Acessar serviços de terceiros
  • Restringir o acesso aos dados pessoais compartilhados de um app

Impacto

O impacto da exploração dessa vulnerabilidade é que um app malicioso pode ter acesso a recursos originalmente destinados à proteção. As implicações da vulnerabilidade dependem do recurso protegido e das permissões associadas ao serviço do aplicativo original.

Risco: erros de digitação em permissões personalizadas

Uma permissão personalizada pode ser declarada no manifesto, mas uma permissão personalizada diferente é usada para proteger componentes exportados do Android devido a um erro de digitação. Um aplicativo malicioso pode aproveitar aplicativos que tenham erros de digitação em uma permissão de uma das seguintes maneiras:

  • Registrando essa permissão primeiro
  • Antecipando a ortografia em aplicativos subsequentes

Isso pode permitir que um aplicativo tenha acesso não autorizado a recursos ou controle sobre o aplicativo da vítima.

Por exemplo, um app vulnerável quer proteger um componente usando uma permissão READ_CONTACTS, mas acidentalmente digita a permissão como READ_CONACTS. Um app malicioso pode reivindicar READ_CONACTS, já que ela não pertence a nenhum aplicativo (ou ao sistema) e ter acesso ao componente protegido. Outra variante comum dessa vulnerabilidade é android:permission=True. Valores como true e false, independentemente da capitalização, são entradas inválidas para a declaração de permissão e são tratados de maneira semelhante a outros erros de digitação na declaração de permissão personalizada. Para corrigir isso, o valor do atributo android:permission precisa ser alterado para uma string de permissão válida. Por exemplo, se o app precisar acessar os contatos do usuário, o valor do atributo android:permission deverá ser android.permission.READ_CONTACTS.

Mitigações

Verificações de lint do Android

Ao declarar permissões personalizadas, use as verificações de lint do Android para encontrar erros de digitação e outros erros em potencial no código.

Convenção de nomenclatura

Use uma convenção de nomenclatura consistente para tornar os erros de digitação mais perceptíveis. Verifique cuidadosamente as declarações de permissão personalizada no manifesto do app para encontrar erros de digitação.


Risco: permissões órfãs

As permissões são usadas para proteger recursos de apps. Há dois locais diferentes em que um app pode declarar as permissões necessárias para acessar recursos:

No entanto, às vezes essas permissões não são definidas por uma tag correspondente <permission> em um manifesto de um APK no dispositivo. Nesse caso, elas são chamadas de permissões órfãs. Essa situação pode ocorrer por vários motivos, como:

  • Pode haver uma dessincronização entre as atualizações no manifesto e o código com a verificação de permissão
  • O APK com as permissões pode não estar incluído no build ou a versão errada pode ser incluída
  • O nome da permissão na verificação ou no manifesto pode estar escrito incorretamente

Um app malicioso pode definir uma permissão órfã e adquiri-la. Se isso acontecer, os aplicativos privilegiados que confiam na permissão órfã para proteger um componente poderão ser comprometidos.

Nos casos em que o app privilegiado usa a permissão para proteger ou restringir qualquer componente, isso pode conceder ao app mal-intencionado acesso a esse componente. Os exemplos incluem o lançamento de atividades protegidas por uma permissão, o acesso a um provedor de conteúdo ou a transmissão para um broadcast receiver protegido pela permissão órfã.

Também pode criar uma situação em que o aplicativo privilegiado é enganado para acreditar que o app malicioso é legítimo e, portanto, carregar arquivos ou conteúdo.

Mitigações

Verifique se todas as permissões personalizadas que o app usa para proteger componentes também estão definidas no manifesto.

O app usa as permissões personalizadas my.app.provider.READ e my.app.provider.WRITE para proteger o acesso a um provedor de conteúdo:

XML

<provider android:name="my.app.database.CommonContentProvider" android:readPermission="my.app.provider.READ" android:writePermission="my.app.provider.WRITE" android:exported="true" android:process=":myappservice" android:authorities="my.app.database.contentprovider"/>

O app também define e usa essas permissões personalizadas, impedindo que outros apps maliciosos façam isso:

XML

<permission android:name="my.app.provider.READ"/>
<permission android:name="my.app.provider.WRITE"/>
<uses-permission android:name="my.app.provider.READ" />
<uses-permission android:name="my.app.provider.WRITE" />

Risco: android:protectionLevel usado incorretamente

Esse atributo descreve o nível de risco potencial na permissão e indica quais procedimentos o sistema precisa seguir ao decidir se concede ou não a permissão.

Mitigações

Evitar o nível de proteção normal ou perigoso

Usar um protectionLevel normal ou perigoso nas permissões significa que a maioria dos apps pode solicitar e receber a permissão:

  • "normal" exige apenas a declaração
  • "perigoso" será aprovado por muitos usuários

Portanto, esses protectionLevels oferecem pouca segurança.

Usar permissões de assinatura (Android 10 e versões mais recentes)

Use níveis de proteção de assinatura sempre que possível. O uso dessa capacidade garante que apenas outros apps assinados com o mesmo certificado do app que criou a permissão possam acessar esses recursos protegidos. Verifique se você está usando um certificado de assinatura dedicado (não reutilizado) e armazene-o com segurança em um keystore.

Defina uma permissão personalizada da seguinte maneira no manifesto:

XML

<permission
    android:name="my.custom.permission.MY_PERMISSION"
    android:protectionLevel="signature"/>

Restrinja o acesso a, por exemplo, uma atividade, apenas aos apps que têm essa permissão personalizada concedida, da seguinte maneira:

XML

<activity android:name=".MyActivity" android:permission="my.custom.permission.MY_PERMISSION"/>

Qualquer outro app assinado com o mesmo certificado do app que declarou essa permissão personalizada receberá acesso à atividade .MyActivity e precisará declará-la da seguinte maneira no manifesto:

XML

<uses-permission android:name="my.custom.permission.MY_PERMISSION" />

Cuidado com permissões personalizadas de assinatura (Android 9 e versões anteriores)

Se o app for destinado ao Android 9 e versões anteriores, sempre que as permissões personalizadas do app forem removidas devido a desinstalações ou atualizações, poderá haver apps maliciosos capazes de usar essas permissões personalizadas e, assim, ignorar as verificações. Isso ocorre devido a uma vulnerabilidade de escalonamento de privilégios (CVE-2019-2200) que foi corrigida no Android 10.

Esse é um dos motivos (junto com o risco de condições de corrida) pelo qual as verificações de assinatura são recomendadas em vez de permissões personalizadas.


Risco: condição de corrida

Se um app legítimo A definir uma permissão personalizada de assinatura que é usada por outros apps X, mas for desinstalado posteriormente, um app malicioso B poderá definir essa mesma permissão personalizada com um protectionLevel diferente, por exemplo, normal. Dessa forma, B ganha acesso a todos os componentes protegidos por essa permissão personalizada nos apps X sem precisar ser assinado com o mesmo certificado do app A.

O mesmo acontece se B for instalado antes de A.

Mitigações

Se você quiser disponibilizar um componente apenas para apps assinados com a mesma assinatura do app de fornecimento, talvez seja possível evitar a definição de permissões personalizadas para restringir o acesso a esse componente. Nessa situação, você pode usar verificações de assinatura. Quando um dos seus apps fizer uma solicitação de outro app, o segundo app poderá verificar se os dois apps estão assinados com o mesmo certificado antes de obedecer à solicitação.


Recursos