Os estouros de buffer são grandes. Nada em C é verificado no intervalo por padrão, por isso é muito fácil substituir um buffer. Há uma função de biblioteca padrão gets()
, que não pode ser impedida de estourar o buffer e quase nunca deve ser usada.
Existem algumas técnicas no nível de implementação para impedir a exploração, como embaralhar blocos de heap, mas isso não interrompe o estouro de buffer nos buffers locais, o que geralmente pode fazer coisas interessantes, como alterar o endereço para o qual a função retornará.
Não existe uma boa solução geral em C. Muitas funções da biblioteca possuem versões que limitarão a quantidade que serão gravadas. embora calcular isso possa ser desajeitado. Existem softwares que podem detectar estouros de buffer de heap em teste, desde que o teste apropriado seja executado, e o estouro de pilha geralmente aparece como uma falha nos testes. Fora isso, é uma questão de codificação cuidadosa e revisão de código.
Um problema relacionado é o problema de gravar em um buffer muito pequeno por um caractere, esquecendo que uma string C com n caracteres requer n + 1 caracteres na memória, devido ao '\0'
terminador. Se o invasor conseguir armazenar uma string sem o terminador, qualquer função C que espera uma string continuará processando até atingir um byte zero, o que pode resultar em copiar ou emitir mais informações do que o desejado (ou atingir a memória protegida para um ataque do DOS) ) A solução, novamente, é a conscientização, o cuidado e as revisões de código.
Há outro risco com a printf()
família. Se você escreve char * str; ... printf(str);
, está se preparando para problemas se str
contiver um '%' quando impresso. A %n
diretiva de formato permite printf()
gravar na memória. A solução é printf("%s", str);
ou puts(str);
. (Além disso, use o C99 em snprintf()
vez de sprintf()
.)
O uso de números inteiros não assinados, principalmente como índices de loop, pode causar problemas. Se você atribuir um pequeno valor negativo a um não assinado, obterá um grande valor positivo. Isso pode prejudicar coisas como processar apenas N instâncias de algo ou funções limitadas como strncpy()
. Examine todos os números inteiros não assinados. Você pode evitar unsigned short
, pois um grande valor em um deles será convertido em um grande valor positivo em um int
.
Não esqueça que uma constante de caractere, em C, é na verdade uma int
. Escrever algo como char c; while((c = getchar()) != EOF) ...
pode falhar facilmente, pois EOF
não será representável em um arquivo char
.
Há muitos erros característicos de C em que posso pensar, mas esses podem causar problemas de segurança.