Concrete Logo
Hamburger button

Dicas de segurança em aplicações Android

  • Blog
  • 10 de Junho de 2015

Muitas vezes somos roubados e nem percebemos (diga lá, meu Brasil…). Há fatos que nunca achamos que vai acontecer com a gente, mas aí… xablau. Isso pode acontecer porque fomos muito ingênuos com as coisas deste mundão. Em mobile não é nada diferente.

Às vezes algo simples como:

Parece inofensivo, correto? No entanto, quando se trata de segurança temos um mundo de contradições sobre o que é “inofensivo”. Há especialistas no assunto que recomendam “evitar lógicas simples”. Vejamos algumas dicas que, já aviso, não vão lhe garantir segurança completa e total, mas vão ajudar a diminuir nossa inerente ingenuidade.

1. Conheça sua plataforma!

Pense que você é um #feladuma**** de um hacker sacana. Se você está querendo atacar uma aplicação Android, qual é o primeiro lugar para procurar? No top 3 estará o Java. Portanto, estude vulnerabilidades e boas práticas de desenvolvimento seguro do Java. Quase tudo que se aplica ao Java se aplica também ao Android. Exemplo: é muito comum código Android não usar os modificadores de acesso do Java corretamente. Assim, acabamos com vários atributos públicos ou não encapsulados (e essa é outra discussão homérica…).

2. Eu disse: CONHEÇA SUA PLATAFORMA!!!

Já ouvi desenvolvedores Android dizendo que usam o SQLite no lugar de SharedPreferences para guardar credenciais do usuário porque é “mais seguro”. Aaaah essa geração criada no biscoito com leite…

  • O que é o SQLite?
  • Um banco de dados.
  • Onde ele persiste esse banco?
  • Num arquivo.
  • O que é o SharedPreferences?
  • Um arquivo.
  • Mas, mas, mas, mas… mundo injusto!

Não guarde senha ou dados críticos abertos e sem proteção em nenhum destes locais. Talvez a API que seu aplicativo acessa implemente autenticação HTTP Basic ou Digest (pelo amor do bom e velho Tim Maia me diga que não é o caso). O que eu faço? Grita. Esses esquemas de autenticação não são seguros para dados críticos. Mas o que é crítico? Dados pessoais dos seus usuários, informações que identifiquem unicamente alguém e etc, etc, etc. Fale com seu time de API e procure práticas mais avançadas para autenticação e autorização, como JWT, autenticação delegada em um padrão seguro e etc.

De qualquer maneira, há formas de dificultar para um atacante. Bibliotecas como secure-preferences ajudam a criar uma camada a mais em SharedPreferences.

Além disso, é claro, ofusque seu código com ProGuard. Sempre. Além de ganhar em performance (diminui o tamanho do APK final limpando código não utilizado e alterando nomes de classes e métodos, entre outras mandingas) também ganha em mais uma camada de segurança (para dificultar mais um pouquinho).

O ProGuard faz algumas mágicas também. Um exemplo de limpar logs em produção (tirado da documentação do ProGuard):

Há uma versão mais robusta do ProGuard chamada DexGuard. Essa faz mais mandingas ainda. Segue comparativo:

image00

Um ponto nesta lista é chamado de Application Integrity (integridade da aplicação). Isso é: o código sendo executado é o código que enviamos para a loja? Isso é chamado de tampering. Há algumas técnicas para evitarmos o tampering, ou seja, que alguém modifique o binário do nosso usuário sem ele saber. Em geral, compara-se checksums dos arquivos, integridade da chave que assinou o binário e etc. Neste gist há uma sugestão de uma versão light de anti-tampering.

3. Cuide bem do seu código de acesso a serviços

Quando devemos usar HTTPS? Sempre. É sério. Sempre mesmo. E mesmo usando sempre ainda há diversos canais de ataque possíveis.

Pense o seguinte: você vai até o Starbucks e conecta no WIFI que está descrito na loja. Há diversos geeks no local criando a próxima startup de sucesso #SQN. Se aquele #feladuma**** que mencionamos anteriormente criar um hotspot no seu notebook com o mesmo nome da rede da loja e se AMBOS estiverem sem senha, há uma chance de você acabar conectando na rede errada! Daí em diante ele pode colocar um proxy na conexão e ver tudo que trafega.

Talvez pareça exagero, mas hoje em dia há diversas técnicas para fazer spoofing do sinal de uma rede. Existem aparelhos vendidos na famosa Santa Ifigênia (São Paulo) que fazem isso com antenas de celular. Eles acabam emitindo um sinal válido de célula mais forte do que o da antena mais próxima e seu celular acaba tentando sincronizar com o aparelho ao invés da antena. E o que eu posso fazer? Well, well, well, Manuel…

O essencial é não cometer um erro na validação do SSL. Já vi muita gente criar código que aceita qualquer certificado SSL sem verificar corretamente. As pessoas acabam sobre-escrevendo a verificação de certificado porque muitas vezes, em ambiente de desenvolvimento, o certificado é gerado localmente e, portanto, não passa na validação do device.

Mas ó raios! Com o Gradle não é tão fácil termos uma classe para debug e outra para release? Estude os Build Types! Não deixe código que só deveria existir em debug chegar em produção. Separe tudo que é específico de ambientes em seu próprio buildtype.

Além de garantir que não está usando códigos obscuros para burlar a verficação do SSL, há mais uma técnica recomendada: Certificate Pinning. O próprio Google recomenda essa técnica aqui. Basicamente isso diz que não é qualquer entidade certificadora que poderá validar o certificado, mas apenas um conjunto específico. Uma das bibliotecas mais utilizadas para HTTP no Android é a OkHttp e ela facilita aplicar essa técnica com esta classe.

Fora estes pontos, é importante não misturar chamadas HTTPS com HTTP. Lembre que em HTTP você não está usando SSL e, portanto, tudo trafega sem criptografia. Caso você se autentique em HTTPS, porém por um descuido faz uma chamada na sequência em HTTP na qual passa seu token de acesso… bom… pode ser que tenha ido tudo para o brejo.

4. Cuidado com seus Logs!

Já citei que o ProGuard pode limpar nossos logs. Isto é muito importante! Veja, você toma todo o cuidado do mundo para não deixar detalhes de segurança passarem despercebidos. Anti-tampering, SSL Certificate pinning, ofuscação e criptografia em SharedPrefrences. Daí, “sem querer”, você vai lá e imprime no log o usuário e senha da sua chamada HTTP.

Existem vários hackers preguiçosos. Por mais que você tenha dificultado bem o trabalho dele, certamente o primeiro lugar que ele vai analisar é o Logcat. Portanto, CUIDADO com seus logs.

Aliás, melhor dizendo, cuidado com TODOS os logs. Veja as configurações das bibliotecas das quais você depende para não mostrar os logs em produção. Exemplo abaixo com Retrofit:

Veja que, seguindo o exemplo da documentação, todos os headers, paths e corpos de requisições serão impressos no Logcat . Não deixe isso acontecer!

Uma maneira de facilitar que os SEUS logs não apareçam no Logcat é usar uma biblioteca que já cuida disso. Existem várias! Veja essa pesquisa no Android Arsenal. Particularmente tenho usado a Timber.

5. Não inclua no repositório do seu código os usuários e senhas para assinar seu pacote!

Existem diversos crawlers que buscam dados como estes no Github… Tem muita gente com TEMPO nesse mundo. Mas como faço para gerar um build.gradle que não contenha a assinatura de release?

Bom, alguém tem que ser o responsável por esses dados. Então, verifique no build.gradle se estes dados estão disponíveis, procurando em variáveis de ambiente ou fazendo algo como:

E colocando dentro do gradle.properties uma propriedade signing.properties. Por último, LEMBRE DE COLOCAR ESTE ARQUIVO NO GITIGNORE!!!!

6. Cuidado com as bibliotecas que você depende no seu projeto.

Ok. Talvez você não se sinta à vontade para fazer um widget de calendário para usar na sua aplicação. No entanto, não saia usando a primeira que encontrar no Github! Lembre-se que ao incluir uma dependência no seu projeto, você DEPENDE daquilo.

Faça algumas observações: o projeto está com atividade recente (commit, isuues sendo respondidos, wiki sendo atualizada e etc)? O projeto segue convenções recentes do Android (Gradle, testes, usa dependências atualizadas também)? O projeto depende de código nativo (em geral pode ser um risco a mais)? Caso tudo isso esteja okay, você terá que acompanhar o projeto e se manter informado dele.

Há algumas formas de fazer isso, sendo que a melhor é: olhe com frequência o repositório. Aperte “watch” para receber notificações (caso seja um projeto aberto no Github ou Bitbucket) e acompanhe no jcenter ou maven central informações sobre novos releases.

Bom, seguindo tudo isso você irá dificultar o trabalho de quem vive de quebrar o trabalho dos outros. Dificultar não é impedir. Fique atento aos seus usuários!

Para concluir deixo algumas referências. Se tiver sugestões sobre outras dicas de segurança faça o favor de nos enviar 😀

Referências: