StrandHogg – Sequestrando aplicações Android
Introdução
No início de dezembro, uma “nova” vulnerabilidade Android ganhou destaque na mídia especializada em Segurança da Informação. Batizada de StrandHogg pela empresa responsável pela divulgação, essa vulnerabilidade explora usos legítimos da Framework do Android para fins maliciosos. Este artigo tem como objetivo explicar como atacantes usam a Framework para esse ataque, sob quais condições podem ser feitos e possíveis maneiras de preveni-lo.
AMS e Android Multi-tasking
As aplicações Android são compostas de quatro partes essenciais: Activities, Services, Broadcast Receivers e Content Providers. Neste artigo focaremos nas Atividades (ou Activities), elas são cada janela, menu, avisos, notificações que aparecem na tela. O Sistema Android prevê múltiplos aplicativos ativos ao mesmo tempo, para isso foram criadas tarefas (ou tasks), cada aplicação ao ser inicializada cria sua própria tarefa e suas Atividades são todas empilhadas à medida que são ativadas. Ao pressionar o botão de retorno, a Activity que está no topo dessa pilha é removida e a anterior é exibida ao usuário. O comportamento padrão previsto pelo Android é apenas empilhar ou remover Activities dessa pilha, porém, para alguns casos especiais, foram criados parâmetros para customizar Activities à fim de proporcionar novas funcionalidades para aplicações e assim expandir a capacidade de lidar com múltiplas tarefas. Dentre esses parâmetros destacam-se:
Launch Mode: Define o modo que a Activity deve ser iniciada pelo Gerenciador de Atividades, existem quatro opções podendo ser standard, singleTask, singleInstance ou singleTop.
Task Affinity: Define a afinidade da Activity para criação de Tarefas. Para o Gerenciador, apps diferentes com mesma afinidade, para o Gerenciador, pertencem à mesma tarefa. Por padrão, a afinidade é definida pelo nome do pacote do aplicativo root, mas pode ser alterado para qualquer string.
Allow Task Reparenting: Valor booleano que define se a Activity pode trocar de pilha durante sua execução caso uma tarefa de mesma afinidade seja lançada.
Manipulando e sequestrando tarefas
Aproveitando–se da falta de controle por parte do Framework sobre os atributos citados é possível que uma aplicação consiga manipular arbitrariamente a pilha de tarefas de outros aplicativos e realizar ataques sobre eles, basta saber o nome da Afinidade do aplicativo alvo e então manipular os atributos de acordo com o ataque que deseja executar. Existem dois cenários para exploração dessa vulnerabilidade. Cada cenário depende de algumas condições, sejam elas para as aplicações (alvo ou malware) ou condições de ações do usuário, já levando em consideração que seria necessário o usuário ter instalado em seu celular uma aplicação maliciosa. No primeiro cenário o malware controla a pilha, logo possui alguns privilégios sobre as Atividades do aplicativo alvo. Estar na posição 0 (ou root) da pilha permite controlar instanciações dos métodos da classe Activity e até interceptar Intents acionadas ou direcionadas para atividades da pilha. Esse cenário abre a possibilidade para seguintes ataques:
Phishing: ataque de fraude cuja finalidade é extrair informações sensíveis ou credenciais de um usuário fazendo-o acreditar que o malware é uma aplicação legítima
Denial of Service: ataque de negação de serviço ocorre quando o atacante torna o recurso indisponível ou inacessível ao usuário
Spyware: software cuja finalidade é monitorar atividades no dispositivo e roubar informações
O outro cenário, apesar de mais limitado, é tão crítico quanto o primeiro, nesse caso o malware engana o Gerenciador de Atividades de modo que ele interprete suas Atividades como pertencentes à alguma aplicação, então quando esta é iniciada o Gerenciador reorganiza as atividades por afinidade levando o malware até a pilha vítima.
Exemplo 1 – spoofing
State 0: Homescreen do usuário
State 1 & 2: O usuário inicia a aplicação maliciosa se passando por alguma aplicação legítima e então abre uma segunda Activity (M2), ela será a responsável pelo ataque, para isso foram definidos os seguintes atributos:
TaskAffinity = “com.alvo.teste”
AllowTaskReparenting = True
State 3: O usuário inicia a aplicação Alvo que possui launchMode definido como Single Task, portanto o Gerenciador ao inicializar sua Task busca a Activity do malware que possui a mesma afinidade e a coloca sobre a pilha da aplicação então para usuário a Activity que aparecerá seria da aplicação recém inicializada.
Exemplo 2 – phishing
State 0: Usuário está com o malware executando em background
State 1 & 2: O usuário utiliza um aplicativo legítimo que em alguma Activity possui um vídeo, para isso o Gerenciador percebe que existem mais de um player de vídeos, dos quais um será alvo do malware.
State 3: Quando o usuário selecionar o player alvo ele executará por cima do malware, devido aos atributos:
TaskAffinity = “com.player.alvo”
LauchMode = singleTask
Assim, o malware terá controle sobre essa nova Activity e ao finalizar o vídeo quando o usuário pressionar o botão de retorno ele voltará para as Activities do malware.
Prevenção
Nesse cenário, onde funcionalidades legítimas do Framework são utilizadas para ataques, citar boas práticas de desenvolvimento de Aplicativos é irrelevante, visto que alguns cenários independem dos atributos do alvo para funcionarem. O ideal seria que algumas mudanças no modo que essas ferramentas de multi-tasking são disponibilizadas para os desenvolvedores, algo como limitação de afinidades, aprimoramento no Gerenciador, assinatura de afinidades, são alguns exemplos de alterações que tornariam essas funcionalidades mais seguras. Todavia, até o momento não houve alterações, então fica responsável ao desenvolvedor pensar em se prevenir desse tipo de ataques. Um modo, não otimizado, é utilizar algumas funções do próprio Android que permitem monitorar quais Activities estão na pilha da aplicação e checar com uma whitelist, caso seja detectada alguma activity não prevista no código a aplicação pode sobrepô-la com uma activity alertando o usuário sobre um possível ataque e qual aplicativo pode ter sido responsável. Essa solução, ainda que funcional, possui alguns contrapesos: ela exige um consumo maior de memória, porém não o suficiente para impactar a experiência do usuário; e também requer do desenvolvedor uma previsão do maior número de casos possíveis para a whitelist, para que não ocorram casos onde aplicações legítimas sejam identificadas como maliciosas. Desse modo, fica a critério dos desenvolvedores ponderar o custo dessa mitigação.
Referências
https://developer.android.com/guide/components/activities/tasks-and-back-stack
https://www.usenix.org/system/files/conference/usenixsecurity15/sec15-paper-ren-chuangang.pdf
https://promon.co/security-news/strandhogg/