Pplware

Isolamento e segurança aplicacional em Android

Por Pedro Veloso para o PPLWARE.COM A razão pela qual decidi fazer este artigo prende-se com uma questão que vi colocada no G+ em que essencialmente perguntam se é possível uma aplicação ler dados e mesmo injectar código para outra aplicação em Android.

Apesar desse post ter sido o pretexto para o artigo, reconheço que esta questão surge com bastante frequência na Internet e que muita coisa é dita erradamente sobre o Sistema Operativo Android portanto espero elucidar algumas dessas questões relativas ao isolamento aplicacional de Android.

O Android quando foi projectado tinha em vista a cooperação de aplicações entre si, uma filosofia que também está presente nos sistemas operativos inspirados em Unix. Outros sistemas como o iOS e o Windows Mobile não se apoiam tanto nesta filosofia (embora também tenham alguns mecanismos para o mesmo fim), e a forma como isso está implementado traz vantagens e desvantagens ao Android que passarei a explicar ao longo do artigo.

Desenho do sistema

Aqui descrevo como o Android está construído e qual o seu comportamento de omissão.

Quando uma aplicação é instalada no Android é-lhe atribuído um utilizador e grupo únicos, isto tira partido da base de Linux que constitui o Android. Derivado a isto, os dados privados da aplicação (tipicamente guardados em /data/data/[nome do pacote da aplicação]/) ficam com o owner igual a esse ID único de utilizador e atributos drwx------, ou seja essa pasta e os ficheiros subordinados podem apenas ser acedidos pela própria aplicação. Existe ainda a possibilidade de serem acedidos pelo utilizador Root (utilizador com ID 0) que é o administrador de sistema, e por vezes pelo utilizador System (utilizador com ID 1000). Ou seja, tal como seria de esperar e por definição o utilizador Root tem acesso ao sistema completo, mas em Android uma aplicação só consegue privilégios Root se o utilizador o permitir.

Uma aplicação pode obter permissões de System se vier instalada na partição de aplicações da ROM (/system/app), ou seja, são aplicações como Gmail e Google Maps e todas as outras que vêm pré-instaladas com a ROM. Não é possível numa instalação a aplicação ser instalada como aplicação de sistema, e nem todas as aplicações que são de sistema têm este privilégio. As aplicações de sistema têm a particularidade de permanecem instaladas mesmo após uma reposição de dados (mais usualmente conhecido como Factory Reset),

Partilha de Informação

Em Desenho do sistema falei do mecanismo que previne que uma aplicação aceda aos dados de outra, essa imposição é feita a nível do sistema de ficheiros e do kernel de Linux.

No entanto, tal como tinha referido no início deste artigo o Android é um sistema construído para que seja possível às aplicações partilharem informações de forma fácil e eficaz entre si.

O primeiro mecanismo que vou falar e um que é muito importante em Android é o conceito de ContentProvider. ContentProvider é um bloco de construção de aplicações que permite oferecer informações a outras aplicações. Um bom exemplo desta funcionalidade é a aplicação de Contactos do telemóvel, esta usa um ContentProvider para oferecer alguns dos detalhes dos contactos a aplicações que queiram ler estes recursos, isto faz com que não se tenha de reinventar a roda para coisas como procura de informações de contactos guardados no telemóvel. Há 2 particularidades importantes sobre ContentProviders:

  1. A aplicação que faz uso do ContentProvider é que escolhe qual e como é que a informação é fornecida às outras aplicações.
  2. Uma aplicação para tirar partido do ContentProvider de outra aplicação irá ser sinalizada com uma permissão relativa a esse propósito, e o utilizador será informado de tal.

Portanto com ContentProvider toda da informação que é passada a outras aplicações está no controlo do programador.

Existem vários outros mecanismos que permitem a troca de informação entre aplicações:

Outras más práticas

Tal como evidenciado no exemplo anterior, também o mau uso de IPC e de ContentProvider podem levar à partilha indesejada de informação. Nesses casos ninguém tem mais culpa que o programador pois este ignorou ou utilizou erradamente os mecanismos de sistema que estavam bem construídos.

Um caso em que isto já não é absolutamente verdade é quando os dados estão guardados no cartão de memória. Uma vez que o sistema de ficheiros do cartão de memória é FAT32 (uma decisão que foi tomada para que os conteúdos do cartão sejam legíveis em sistemas Microsoft Windows), este sistema de ficheiros rudimentar (:P) não permite ter um controlo de permissões suficiente como o de armazenamento interno, então aqui qualquer aplicação pode aceder a qualquer conteúdo do cartão de memória, tendo no entanto que ter definida a permissão de leitura de cartão do mesmo (e que como é claro será apresentada ao utilizador em tempo de instalação), mas após a obter não existe um controlo de que tipo de conteúdo no cartão lhe é inacessível. Aqui a única solução passa pela aplicação implementar algum tipo de encriptação dos dados que guarda se de facto quer que estes não sejam facilmente legíveis por outras aplicações.

Falhas de sistema

Em Android, tal como noutro sistema operativo móvel qualquer, existem falhas de sistema que podem permitir tirar o extravio de informação.

Uma falha habitualmente explorada é a obtenção de Root sem consentimento do utilizador, uma vez que a aplicação tenha permissões Root é-lhe possível ler toda a informação do sistema (a menos que cifrada).

Este tipo de exploit tem algumas complicações de implementação para o programador mal intencionado, aqui a fragmentação da plataforma na verdade é uma forma de protecção, pois cada telemóvel e versão de Android possui uma forma própria para obtenção de tais permissões (estamos a falar de aplicações obterem permissões Root da mesma forma que as aplicações para instalar Root funcionam, ou seja, sem intermédio da aplicação SuperUser pois aqui o utilizador controla o acesso).

O ponto que joga a favor dos exploiters é que a maioria do código para obtenção de root está disponível livremente na Internet, isto faz com que qualquer programador avançado tenha ferramentas fáceis para tirar partido disso para grupos de dispositivos pré-seleccionados. Uma ferramenta deste tipo de ataque genérico em Android é virtualmente impossível sendo que existem outras restrições que variam muito de fabricante para fabricante (NAND Locked, partições diferentes, versões diferentes de Android, diferentes arquitecturas exploráveis (ARMv6, ARMv7, …)).

Na verdade, neste ponto a plataforma iOS é bem mais vulnerável a ataques, falando de um ponto de vista tecnológico e sem contar com a filtragem que é feita nos repositórios de aplicações de cada um, uma vez que têm um leque limitado e uniforme de dispositivos cujas vulnerabilidades sendo conhecidas aplicam-se logo de imediato a uma grande fatia dos dispositivos.

A filtragem da App Store da Apple funciona como uma primeira linha de defesa contra este tipo de aplicações que é algo que também falha em Android, o que exige um cuidado reforçado na escolha de aplicações a instalar.

Por vezes é um conjunto de factores que no seu todo levam a que uma informação que não era suposto esteja disponível de forma que não deveria, como é o caso do Widget de meteorologia que vem pré-instalado em vários HTC e Samsung que dado à sua má programação publicita a localização do utilizador a nível de sistema e deixa essa informação de leitura para todas as aplicações, tal como demonstrei aqui.

Um outro exemplo prende-se com a manipulação errada de permissões em Android, aqui é preciso ter em conta mais uma vez que o erro está na ROM e na marca que a fez, e não no Android em geral.

Por exemplo em vários dispositivos HTC (incluindo o Nexus One), Motorola e Samsung existem falhas de sistema que permitem ler e tirar partido de certas funcionalidades de sistema que não deveriam acontecer dada a especificação do sistema de permissões e que permitem a leitura de SMSs, gravação de chamadas e captura de imagem:

Conclusão (resumida)

Note-se que estes 2 últimos exemplos são de extravio de informação de certas partes do sistema, a integralidade de informação de aplicações não foi comprometida. Estes e outros exemplos demonstram claramente que a não ser que a aplicação tenha alguma má prática de programação, qualquer dispositivo que passe os testes de compatibilidade da Google e sem contar com obtenção de permissões Root não permite a obtenção de dados privados de outra aplicação.

Quando há injecção de código, seria apenas possível com recurso a uma metodologia de rootkit, e para tal isso implicaria a substituição dos ficheiros DEX que constituem o Bytecode do Dalvik VM de uma aplicação. Para começar esta tarefa é bastante complexa, e requereria mais uma vez a obtenção de permissões Root para ser possível substituir ficheiros de outras aplicações.

Tirando esse caso não há registo de qualquer tipo de injecção de código em aplicações, muito menos com recurso a ficheiros JAR, só alguém que não percebe nada do sistema operativo poderia afirmar isso uma vez que o Bytecode de uma máquina virtual de Java convencional nada tem a ver com o Bytecode da DalvikVM, o próprio funcionamento estrutural é diferente, sendo que o Dalvik se assemelha muito mais a um sistema operativo comum. Vejamos pela descrição dos fundamentos aplicacionais de Android:

Android applications are written in the Java programming language. The Android SDK tools compile the code—along with any data and resource files—into an Android package, an archive file with an .apk suffix. All the code in a single .apk file is considered to be one application and is the file that Android-powered devices use to install the application. Once installed on a device, each Android application lives in its own security sandbox:

  • The Android operating system is a multi-user Linux system in which each application is a different user.
  • By default, the system assigns each application a unique Linux user ID (the ID is used only by the system and is unknown to the application). The system sets permissions for all the files in an application so that only the user ID assigned to that application can access them. • Each process has its own virtual machine (VM), so an application’s code runs in isolation from other applications.
  • By default, every application runs in its own Linux process. Android starts the process when any of the application’s components need to be executed, then shuts down the process when it’s no longer needed or when the system must recover memory for other applications. In this way, the Android system implements the principle of least privilege. That is, each application, by default, has access only to the components that it requires to do its work and no more. This creates a very secure environment in which an application cannot access parts of the system for which it is not given permission.

O próprio sistema visual de Android segue a mesma filosofia e que uma aplicação não pode interagir com o espaço de desenho de outra (citando Dianne Hackborn – lead-programmer do sistema visual de Android):

“Android had a number of very different original design goals than iOS did. A key goal of Android was to provide an open application platform, using application sandboxes to create a much more secure environment that doesn’t rely on a central authority to verify that applications do what they claim.

To achieve this, it uses Linux process isolation and user IDs to prevent each application from being able to access the system or other application in ways that are not controlled and secure.

This is very different from iOS’s original design constraints, which remember didn’t allow any third party applications at all.

An important part of achieving this security is having a way for (EDIT: It has been pointed out to me that iOS does in fact use multiple windows and multiple GL contexts. Lesson to me, just don’t talk about anything I haven’t directly verified. 🙂

That still doesn’t change things for Android, though, where as I mention later we simply did not have hardware and drivers that could do multiple GL contexts until fairly recently.) individual UI elements to share the screen in a secure way. This is why there are windows on Android. The status bar and its notification shade are windows owned and drawn by the system. These are separate from the application’s window, so the application can not touch anything about the status bar, such as to scrape the text of SMS messages as they are displayed there. Likewise the soft keyboard is a separate window, owned by a separate application, and it and the application can only interact with each other through a well defined and controlled interface. (This is also why Android can safely support third party input methods.)”

 

 

Pedro Veloso é Licenciado em Ciências da Computação na Universidade do Minho e programador na empresa Emerge IT , uma empresa com actividade na área das Tecnologias da Informação e Comunicação (TIC), especializada na prestação de serviços e comercialização de soluções tecnológicas adaptadas a organizações, no desenvolvimento de soluções em Android, entre outros. É também membro core da equipa do androidPT onde participa activamente.

Exit mobile version