Skip to content

MASTG-TEST-0229: Stack Canaries não habilitado

Visão Geral

Este caso de teste verifica se o binário principal ou qualquer biblioteca do aplicativo é compilado sem canários de pilha e, portanto, carece de proteção contra estouro de pilha)), uma técnica comum de mitigação contra ataques de buffer overflow.

Este teste aplica-se a todos os binários e bibliotecas:

  • É especialmente importante para linguagens não memory safe como Objective-C ou C/C++.
  • Para aplicativos puramente em Swift, a verificação de canários de pilha geralmente pode ser ignorada, pois o Swift é considerado memory safe por design e técnicas convencionais de análise não conseguem detectar canários de pilha em binários Swift (consulte a seção "canary – exceptions" desta publicação de blog).

Para diferenciar entre binários Objective-C e Swift, você pode inspecionar as importações e bibliotecas vinculadas. Detectar binários Objective-C é simples, mas detectar binários puramente em Swift é mais desafiador porque, dependendo da versão do Swift e das configurações do compilador, o binário ainda pode conter símbolos ou bibliotecas Objective-C. Consulte a seção "identifying objc vs swift" desta publicação de blog para mais detalhes.

Etapas

  1. Extraia o aplicativo e identifique o binário principal ( Obtenção e Extração de Apps).
  2. Identifique todas as bibliotecas compartilhadas ( Obter Bibliotecas Compartilhadas).
  3. Execute Obtenção de Recursos de Segurança Fornecidos pelo Compilador no binário principal e em cada biblioteca compartilhada.
  4. Se a saída contiver o símbolo __stack_chk_fail, isso indica que os canários de pilha estão habilitados.

Observação

A saída deve conter uma lista de símbolos do binário principal e de cada biblioteca compartilhada.

Avaliação

O caso de teste falha se qualquer binário ou biblioteca não for puramente Swift e não contiver métodos que indiquem canários de pilha, como objc_autorelease ou objc_retainAutorelease.

Nota: Verificar o símbolo __stack_chk_fail apenas indica que a proteção contra estouro de pilha está habilitada em algum lugar do aplicativo. Embora os canários de pilha geralmente sejam habilitados ou desabilitados para todo o binário, pode haver casos específicos em que apenas partes do aplicativo estejam protegidas. Por exemplo, se o desenvolvedor do aplicativo vincular estaticamente uma biblioteca com proteção contra estouro de pilha habilitada, mas desabilitá-la para todo o aplicativo.

Se você quiser ter certeza de que métodos específicos críticos para segurança estão suficientemente protegidos, será necessário fazer a engenharia reversa de cada um deles e verificar manualmente a presença de proteção contra estouro de pilha.

Ao avaliar isso, observe que existem potenciais falsos positivos esperados para os quais o caso de teste deve ser considerado como aprovado. Para ter certeza nesses casos, é necessária uma revisão manual do código-fonte original e dos flags de compilação utilizados.

Os exemplos a seguir abrangem alguns dos casos de falsos positivos que podem ser encontrados:

Uso de Linguagens Memory Safe

O framework Flutter não usa canários de pilha devido à forma como o Dart mitiga estouros de buffer.

Otimizações do Compilador

Às vezes, devido ao tamanho da biblioteca e às otimizações aplicadas pelo compilador, é possível que a biblioteca tenha sido originalmente compilada com canários de pilha, mas eles tenham sido otimizados e removidos. Por exemplo, este é o caso de alguns aplicativos React Native. Eles são construídos com -fstack-protector-strong, mas ao tentar buscar por stack_chk_fail dentro dos arquivos binários, ele não é encontrado. Os desenvolvedores do React Native, neste caso, declaram que não adicionarão -fstack-protector-all, pois, em sua visão, consideram que isso adicionaria uma penalidade de desempenho sem ganho efetivo de segurança.