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¶
- Extraia o aplicativo e identifique o binário principal ( Obtenção e Extração de Apps).
- Identifique todas as bibliotecas compartilhadas ( Obter Bibliotecas Compartilhadas).
- Execute Obtenção de Recursos de Segurança Fornecidos pelo Compilador no binário principal e em cada biblioteca compartilhada.
- 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.