1. O documento discute a vulnerabilidade CWE-787 Out-of-bounds Write, que ocorre quando dados são gravados para além dos limites do buffer de memória.
2. A vulnerabilidade é comum em linguagens como C e C++ e pode resultar em dados corrompidos, falhas de execução ou execução de código não autorizado.
3. O documento fornece exemplos de código, métodos de prevenção, detecção e casos reais de vulnerabilidades, destacando a importância de se tomar cuidado ao se desenvolver software em C para evitar essa vulnerabilidade
Out-of-bounds Write: Vulnerabilidade comum e perigosa
1. CWE-787
Out-of-bounds Write
Guilherme de Oliveira Dutra
go.dutra@unesp.br - godutra@gmail.com
Disciplina de Segurança Cibernética
Pós-graduação PPGCC/UNESP
Prof. Dr. Adriano Mauro Cansian
2. O que é Out-of-bounds Write
➢ É a gravação de dados após o final
ou antes do início do buffer de memória.
➢ Ocorre devido a falhas na concepção e no desenvolvimento do
software.
➢ É prevalente em softwares implementados em C, C++ e, também
encontrado, em Assembly.
➢ Pertence à categoria de Erros de Buffer de Memória.
2
3. Consequências
➢ Dados corrompidos
➢ Falha na execução
➢ Execução de código não-autorizado
➢ Indisponibilidade do serviço (DoS)
➢ Encerramento na execução da aplicação
➢ Reinício da aplicação
3
4. Common Weakness Enumeration (CWE)
➢ Código: CWE-787.
➢ É um catálogo de tipos prevalentes de fragilidades (imperfeições,
falhas, bugs e erros) de software e hardware com consequências em
segurança (vulnerabilidades) [1].
4
5. CWE TOP 25
➢ Top 25 - Ranking dos mais perigosos conforme dados da CVE (Common
Vulnerabilities and Exposures), NVD (National Vulnerability Database) e
CVSS (Common Vulnerability Scoring System) [2].
➢ Segunda colocada na CWE Top 25 de 2020.
➢ Primeira colocada na CWE Top 25 de 2020 com score de 65,93.
5
6. Exemplo (1) - Linguagem C
➢ O código a seguir tenta salvar quatro números de identificação diferentes em um vetor.
int id_sequence[3];
/* Populate the id array. */
id_sequence[0] = 123;
id_sequence[1] = 234;
id_sequence[2] = 345;
id_sequence[3] = 456;
➢ Como o vetor é definido apenas para conter três elementos, os índices válidos são de 0
a 2. Portanto, a atribuição a id_sequence[3] está fora dos limites.
6
7. Exemplo (2) - Tratamento de Hostname
➢ Este exemplo pega um endereço IP de um usuário, verifica se
ele está bem formado e, em seguida, procura o nome do host
e o copia em um buffer.
➢ Esta função aloca um buffer de 64 bytes para armazenar o
nome do host, porém não há garantia de que o nome do host
não seja maior que 64 bytes. Se um invasor especificar um
endereço que resolva para um nome de host maior, a função
poderá substituir dados confidenciais ou até mesmo liberar o
fluxo de controle para o invasor.
7
void host_lookup(char *user_supplied_addr){
struct hostent *hp;
in_addr_t *addr;
char hostname[64];
in_addr_t inet_addr(const char *cp);
/*routine that ensures
user_supplied_addr is in
the right format for
conversion */
validate_addr_form(user_supplied_addr);
addr = inet_addr(user_supplied_addr);
hp = gethostbyaddr( addr, sizeof(struct
in_addr), AF_INET);
strcpy(hostname, hp->h_name);
}
8. Exemplo (3)- Trim em String
➢ Função de utilitário usada para remover espaços em branco à
direita de uma cadeia de caracteres. A função copia a string
de entrada para uma string de caracteres local e usa uma
instrução while para remover o espaço em branco à direita.
➢ No entanto, esta função pode causar uma subscrição de
buffer se a cadeia de caracteres de entrada contiver todos os
espaços em branco. Em alguns sistemas, a instrução while
se moverá para trás além do início de uma cadeia de
caracteres e chamará a função isspace() em um endereço
fora dos limites do buffer.
8
char* trimTrailingWhitespace(char *strMessage, int
length) {
char *retMessage;
char *message =
malloc(sizeof(char)*(length+1));
// copy input string to a temporary string
char message[length+1];
int index;
for (index = 0; index < length; index++) {
message[index] = strMessage[index];
}
message[index] = '0';
// trim trailing whitespace
int len = index-1;
while (isspace(message[len])) {
message[len] = '0';
len--;
}
// return string without trailing whitespace
retMessage = message;
return retMessage;
}
10. ➢ Use uma linguagem que não permita que essa vulnerabilidade ocorra ou
forneça construções que tornem essa vulnerabilidade mais fácil de evitar.
➢ Há muitas linguagens que executam seu próprio gerenciamento de memória,
como Java e Go, não estão sujeitas a estouros de buffer. Outras linguagens,
como Ada e C# oferecem mas pode ser desligada.
Métodos de Prevenção. Fase: Requisitos.
Escolha da Linguagem
10
11. ➢ Não devem permitir que essa vulnerabilidade ocorra ou forneça padrões que tornem
essa vulnerabilidade fácil de se evitar.
➢ Exemplos incluem as bibliotecas SafeStr e Strsafe.h. Que fornecem versões mais
seguras de funções de manipulação de strings.
➢ Contudo, muitos estouros de buffer não estão relacionados a strings.
Métodos de Prevenção. Fase: Arquitetura e Design.
Utilização de Bibliotecas ou Frameworks
11
12. ➢ Execute ou compile o software usando extensões que fornecem automaticamente
mecanismos de proteção contra estouros de buffer.
➢ Certos compiladores fornecem mecanismos automáticos de detecção de estouro
de buffer que são incorporados ao código compilado, como o Microsoft Visual Studio
/GS, Fedora/Red Hat FORTIFY_SOURCE GCC, StackGuard e ProPolice.
➢ Contudo, esses mecanismos só podem detectar certos tipos de estouros.
Métodos de Prevenção. Fase: Compilação.
Build Hardening
12
13. ➢ Regras ao alocar e gerenciar a memória de um aplicativo:
■ Verifique novamente (double check) se o buffer é do tamanho especificado.
■ Ao usar funções que requerem a identificação de um número de bytes, como strncpy(), esteja ciente
de que, se o tamanho do buffer de destino for igual ao tamanho do buffer de origem, a string não pode
ser terminada por nulo (NULL).
■ Verifique os limites do buffer se estiver acessando o buffer em um loop e certifique-se de que não
haja perigo de escrever além do espaço alocado.
■ Se necessário, reduza todas as strings de entrada ao comprimento definido antes de passá-las para
funções de cópia e concatenação.
Métodos de Prevenção. Fase: Implementação.
Regras de Conformidade.
13
14. ➢ Execute ou compile o software usando extensões que distribuam aleatoriamente
as posições do executável e das bibliotecas de um programa na memória.
➢ Pode impedir que um invasor chegue de forma confiável no código explorável.
➢ Contudo, ainda pode causar uma indisponibilidade do serviço (DoS), já que a
resposta típica é sair do aplicativo.
Métodos de Prevenção. Fase: Operação.
Dificultação de Leitura do Ambiente.
14
15. ➢ Substitua as funções de cópia por funções análogas que suportam argumentos de
limitação de comprimento, como strcpy por strncpy. Crie-os se não estiverem
disponíveis.
➢ Observação: essa abordagem ainda é suscetível a erros de cálculo, incluindo
problemas de cálculo incorreto de comprimentos de buffer (CWE-131).
Métodos de Prevenção. Fase: Implementação.
Funções com Argumentos de Limites.
15
16. ➢ Método de debug de programação que examina o código sem executar o programa
[3].
➢ Muitas ferramentas automatizadas de análise estática modernas usam análise de
fluxo de dados comparando com regras de padrões de boas práticas de
desenvolvimento seguro.
➢ Não leva em consideração possíveis inputs maliciosos em tempo de execução.
Métodos de Detecção
Análise Estática Automatizada
16
17. ➢ Pode ser detectada usando ferramentas e técnicas dinâmicas que interagem com o
software usando grandes conjuntos de testes com muitas entradas diversas, como
testes de fuzz (fuzzing) [4], testes de robustez e injeção de falhas.
➢ A operação do software pode ficar lenta, mas não deve
ficar instável, travar ou gerar resultados incorretos.
Métodos de Detecção
Análise Dinâmica Automatizada
17
18. ➢ Implementação de Bluetooth para celular que não define corretamente o limite (offset) ao
calcular o comprimento do pacote (CWE-682), conduzindo a um “out-of-bounds write”.
➢ Na função “reassemble_and_dispatch” de “packet_fragmenter.cc”, é possível escrever fora
dos limites devido a um cálculo incorreto dos limites. Isso pode levar à execução remota de
código por Bluetooth sem a necessidade de privilégios de execução adicionais.
➢ Produto: Android Versões: Android-8.0 Android-8.1 Android-9 Android-10.
Casos Conhecidos
CVE-2020-0022
18
19. ➢ São Inputs escritos deliberadamente para causarem acessos a objetos não inicializados ou
excluídos anteriormente, levando ao estouro de memória.
➢ Ocorre no Microsoft Internet Explorer 8 para Windows XP SP2 e SP3; 8 para o Server 2003 SP2; 8
para Vista Gold, SP1 e SP2; e 8 para Server 2008 SP2.
➢ Não manipulam corretamente objetos na memória, o que permite a invasores remotos executarem
código malicioso, levando ao estouro de memória conhecido como "Vulnerabilidade de Estouro de
memória de objetos HTML".
Casos Conhecidos
CVE-2009-1532
19
20. ➢ O valor de retorno “ -1” em uma chamada de função foi pensado para indicar um erro, mas em um
kernel do Linux foi usado como índice de um vetor.
➢ O subsistema eCryptfs no kernel Linux antes de 2.6.28.1 permite que usuários locais causem uma
interrupção de serviço (DOS), ou possivelmente tenham outro impacto não especificado, por meio de
uma chamada readlink que resulta em um erro, levando ao uso do valor “-1” como índice de um vetor.
Casos Conhecidos
CVE-2009-0269
20
21. ➢ A não verificação do comprimento do conteúdo do desafio (challenge) usando no SSLv2 leva a buffer
underflow, no qual o software escreve no início do buffer.
➢ O buffer underflow no ssldump 0.9b2 e anteriores permite que invasores remotos causem um DOS
por meio de um valor de desafio SSLv2 manipulado.
Casos Conhecidos
CVE-2002-2227
21
22. ➢ Buffer underflow [5] de um valor de tamanho pequeno com um buffer grande causa uma
inconsistência no comprimento do parâmetro (CWE-130).
➢ O estouro de buffer no redlight.sys do BufferZone 2.1 e 2.5 permite que os usuários locais causem
travamento por DOS e, possivelmente, executem código informando um valor tamanho de buffer
menor para o código do manipulador contendo um buffer maior.
➢ Justamente no BufferZone (bufferzonesecurity.com), um sistema de segurança criado para proteger
sessões de browsers e endpoints de APIs.
Casos Conhecidos
CVE-2007-4580
22
23. ➢ Um erro de conversão de inteiro com sinal para um sem sinal (CWE-195) com comparação de sinais,
conduzindo a um estouro de buffer (heap overflow) (CWE-122).
➢ Presente no componente de rede no Apple Mac OS X 10.4 a 10.4.10, permite que usuários executem
código por meio de uma mensagem AppleTalk contendo um valor negativo, que satisfaz uma
comparação de sinais durante a alocação de mbuf, o que é posteriormente interpretado como um
valor sem sinal, que aciona um estouro de buffer.
Casos Conhecidos
CVE-2007-4268
23
24. ➢ Estou de buffer de memória na pilha (Heap-based buffer overflow) no media player SCMPX 1.5.1
usando uma entrada extensa na playlist.
➢ O estouro de buffer no SCMPX 1.5.1 permite que invasores remotos causem um DOS por travamento
do aplicativo ou executem código por meio de uma longa string em um arquivo de lista de reprodução
.m3u.
Casos Conhecidos
CVE-2009-2403
24
25. ➢ Uma otimização realizada por compilador, a CWE-733, modificou o código criado pelo desenvolvedor
para detectar falhas de “integer overflow” (CWE-190), o que permitiu “out-of-bounds write”.
➢ O Evince 3.26.0, um visualizador de documentos em formato PDF
, é afetado pelo estouro de buffer. O
impacto é um Deny Of Service e uma possível execução de código. O componente é o
backend/tiff/tiff-document.c.
➢ O gatilho ocorre quando se abre um PDF infectado. O mecanismo é acionado na renderização de
imagens TIFF
.
Casos Conhecidos
CVE-2019-1010006
25
27. A linguagem C é utilizada por entregar um excelente desempenho, possuir compiladores para todos
os Sistemas Operacionais e ser de fácil aprendizado e implementação. Contudo, é importante ter
cuidados redobrados para evitar o ataque mais visado dos últimos anos, o CWE-787 Out-of-Bounds
Write.
Evidentemente, essa vulnerabilidade é muito explorada pois a imensa maioria dos principais
softwares disponíveis atualmente são desenvolvidos em C/C++.
Mas, conforme apresentado, há diversos métodos preventivos, de detecção e correção que ajudam a
mitigar ameaças causadas por esta vulnerabilidade.
Conclusão
27
28. 1. “CWE - About - CWE Overview.” Common Weakness Enumeration, 13 March 2021,
https://cwe.mitre.org/about/index.html. Accessed 23 May 2022.
2. “CWE - 2021 CWE Top 25 Most Dangerous Software Weaknesses.” Common Weakness Enumeration, 26 July
2021, https://cwe.mitre.org/top25/archive/2021/2021_cwe_top25.html. Accessed 23 May 2022.
3. Gillis, Alexander S. “What is Static Analysis (Static Code Analysis)?” TechTarget,
https://www.techtarget.com/whatis/definition/static-analysis-static-code-analysis. Accessed 24 May 2022.
4. “What Is Fuzz Testing and How Does It Work?” Synopsys,
https://www.synopsys.com/glossary/what-is-fuzz-testing.html. Accessed 25 May 2022.
5. “Buffer underrun – Wikipédia, a enciclopédia livre.” Wikipédia, https://pt.wikipedia.org/wiki/Buffer_underrun.
Accessed 25 May 2022
6. “CWE - CWE-787: Out-of-bounds Write (4.7).” Common Weakness Enumeration,
https://cwe.mitre.org/data/definitions/787.html. Accessed 23 May 2022.
7. Aleph One. “stack based buffer overflow vulnerability.” Phrack Magazine, 8 November 1996,
http://phrack.org/issues/49/14.html. Accessed 26 May 2022.
Referências
28