Skip to content

MASTG-TECH-0012: Contornando o Certificate Pinning

Alguns aplicativos implementam SSL Pinning, o que impede que o aplicativo aceite seu certificado de interceptação como um certificado válido. Isso significa que você não conseguirá monitorar o tráfego entre o aplicativo e o servidor.

Para a maioria dos aplicativos, o certificate pinning pode ser contornado em segundos, mas apenas se o app usar as funções de API cobertas por essas ferramentas. Se o aplicativo implementar SSL Pinning com um framework ou biblioteca personalizados, o SSL Pinning deve ser corrigido e desativado manualmente, o que pode ser demorado.

Esta seção descreve várias maneiras de contornar o SSL Pinning e oferece orientações sobre o que você deve fazer quando as ferramentas existentes não ajudam.

Métodos de Bypass

Existem várias maneiras de contornar o certificate pinning para um teste de caixa preta, dependendo dos frameworks disponíveis no dispositivo:

Se você tiver um dispositivo root com frida-server instalado, pode contornar o SSL pinning executando o seguinte comando do objection (consulte Reempacotamento de Apps se estiver usando um dispositivo não root):

android sslpinning disable

Aqui está um exemplo da saída:

Consulte também a Ajuda do Objection sobre Desabilitar SSL Pinning para Android para obter mais informações e inspecione o arquivo pinning.ts para entender como o bypass funciona.

Observe que o script frida-multiple-unpinning do Frida CodeShare cobre mais cenários que o script do Objection.

Contornar Certificate Pinning Personalizado Estaticamente

Em algum lugar do aplicativo, tanto o endpoint quanto o certificado (ou seu hash) devem ser definidos. Após descompilar o aplicativo, você pode pesquisar por:

  • Hashes de certificado: grep -ri "sha256\|sha1" ./smali. Substitua os hashes identificados pelo hash do CA do seu proxy. Alternativamente, se o hash estiver acompanhado de um nome de domínio, você pode tentar modificar o nome de domínio para um domínio inexistente para que o domínio original não seja fixado. Isso funciona bem em implementações ofuscadas do OkHTTP.
  • Arquivos de certificado: find ./assets -type f \( -iname \*.cer -o -iname \*.crt \). Substitua esses arquivos pelos certificados do seu proxy, certificando-se de que estejam no formato correto.
  • Arquivos de truststore: find ./ -type f \( -iname \*.jks -o -iname \*.bks \). Adicione os certificados do seu proxy ao truststore e certifique-se de que estejam no formato correto.

Lembre-se de que um aplicativo pode conter arquivos sem extensão. Os locais mais comuns de arquivos são os diretórios assets e res, que também devem ser investigados.

Como exemplo, digamos que você encontre um aplicativo que usa um truststore BKS (BouncyCastle) armazenado no arquivo res/raw/truststore.bks. Para contornar o SSL Pinning, você precisa adicionar o certificado do seu proxy ao truststore com a ferramenta de linha de comando keytool. O keytool vem com o SDK Java e os seguintes valores são necessários para executar o comando:

  • password - Senha do keystore. Procure no código descompilado do aplicativo a senha hardcoded.
  • providerpath - Localização do arquivo jar do Provedor BouncyCastle. Você pode baixá-lo em The Legion of the Bouncy Castle.
  • proxy.cer - Certificado do seu proxy.
  • aliascert - Valor único que será usado como alias para o certificado do seu proxy.

Para adicionar o certificado do seu proxy, use o seguinte comando:

keytool -importcert -v -trustcacerts -file proxy.cer -alias aliascert -keystore "res/raw/truststore.bks" -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "providerpath/bcprov-jdk15on-164.jar" -storetype BKS -storepass password

Para listar certificados no truststore BKS, use o seguinte comando:

keytool -list -keystore "res/raw/truststore.bks" -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "providerpath/bcprov-jdk15on-164.jar"  -storetype BKS -storepass password

Após fazer essas modificações, reempacote o aplicativo usando apktool e instale-o em seu dispositivo.

Se o aplicativo usar bibliotecas nativas para implementar a comunicação de rede, será necessário fazer mais engenharia reversa. Um exemplo dessa abordagem pode ser encontrado no blog post Identificando a lógica de SSL Pinning no código smali, corrigindo e remontando o APK

Contornar Certificate Pinning Personalizado Dinamicamente

Contornar a lógica de pinning dinamicamente é mais conveniente, pois não é necessário contornar verificações de integridade e é muito mais rápido realizar tentativas de tentativa e erro.

Encontrar o método correto para hook é normalmente a parte mais difícil e pode levar bastante tempo, dependendo do nível de ofuscação. Como os desenvolvedores normalmente reutilizam bibliotecas existentes, é uma boa abordagem procurar por strings e arquivos de licença que identifiquem a biblioteca usada. Uma vez identificada a biblioteca, examine o código não ofuscado para encontrar métodos adequados para instrumentação dinâmica.

Como exemplo, digamos que você encontre um aplicativo que usa uma biblioteca OkHTTP3 ofuscada. A documentação mostra que a classe CertificatePinner.Builder é responsável por adicionar pins para domínios específicos. Se você puder modificar os argumentos do método Builder.add, você pode alterar os hashes para os hashes corretos pertencentes ao seu certificado. Encontrar o método correto pode ser feito de duas maneiras, conforme explicado neste blog post por Jeroen Beckers:

  • Procure por hashes e nomes de domínio, conforme explicado na seção anterior. O método de pinning real normalmente será usado ou definido nas proximidades dessas strings
  • Procure pela assinatura do método no código SMALI

Para o método Builder.add, você pode encontrar os métodos possíveis executando o seguinte comando grep: grep -ri java/lang/String;\[Ljava/lang/String;)L ./

Este comando pesquisará todos os métodos que recebem uma string e uma lista variável de strings como argumentos e retornam um objeto complexo. Dependendo do tamanho do aplicativo, isso pode ter uma ou várias correspondências no código.

Faça hook de cada método com Frida e imprima os argumentos. Um deles imprimirá um nome de domínio e um hash de certificado, após o qual você poderá modificar os argumentos para contornar o pinning implementado.