Problemas de validação e representação da entrada são causados por metacaracteres, codificações alternativas e representações numéricas. Confiar na entrada resulta em problemas de segurança. Os problemas incluem: “Buffer Overflows”, ataques de “Cross-Site Scripting”, “SQL Injection”, entre outros.
cfgfile
e copia a entrada em inputbuf
usando strcpy()
. Esse código presume erroneamente que inputbuf
sempre conterá um terminador nulo.
#define MAXLEN 1024
...
char *pathbuf[MAXLEN];
...
read(cfgfile,inputbuf,MAXLEN); //does not null-terminate
strcpy(pathbuf,inputbuf); //requires null-terminated input
...
Example 1
se comportará corretamente se os dados lidos de cfgfile
tiverem uma terminação nula no disco, conforme o esperado. Porém, se um invasor puder modificar essa entrada de forma que ela não contenha o caractere null
esperado, a chamada para strcpy()
continuará copiando da memória até encontrar um caractere null
arbitrário. Isso provavelmente estourará o buffer de destino e, se o invasor puder controlar o conteúdo da memória imediatamente depois de inputbuf
, isso poderá deixar o aplicativo suscetível a um ataque de estouro de buffer.readlink()
expande o nome de um link simbólico armazenado no buffer path
, de forma que o buffer buf
contenha o caminho absoluto do arquivo referenciado por esse link simbólico. O comprimento do valor resultante é então calculado com o uso de strlen()
.
...
char buf[MAXPATH];
...
readlink(path, buf, MAXPATH);
int length = strlen(buf);
...
Example 2
não se comportará corretamente, pois o valor lido em buf
por readlink()
não terá terminação nula. Em situações de teste, vulnerabilidades como esta podem não ser capturadas, pois o conteúdo não utilizado de buf
e a memória imediatamente depois dele podem ser null
, fazendo assim com que strlen()
pareça estar se comportando corretamente. No entanto, em condições naturais, strlen()
continuará a atravessar a memória até encontrar um caractere null
arbitrário na pilha, o que resulta em um valor de length
que é muito superior ao tamanho de buf
e pode causar um estouro de buffer em usos subsequentes desse valor.snprintf()
para copiar uma string de entrada do usuário e colocá-la em várias strings de saída. Apesar de fornecer barreiras de proteção adicionais em comparação com sprintf()
, principalmente a especificação de um tamanho máximo de saída, a função snprintf()
ainda é suscetível a um erro de terminação de string quando o tamanho de saída especificado é maior que a entrada potencial. Erros de terminação de string podem levar a problemas posteriores, como vazamento de memória ou estouro de buffer.
...
char no_null_term[5] = getUserInput();
char output_1[20];
snprintf(output_1, 20, "%s", no_null_term);
char output_2[20];
snprintf(output_2, 20, "%s", no_null_term);
printf("%s\n", output_1);
printf("%s\n", output_2);
...
Example 3
demonstra um vazamento de memória. Quando a output_2
for populada com no_null_term
, snprintf()
deverá ler a partir da localização de no_null_term
até que um caractere nulo seja encontrado ou o limite de tamanho especificado seja atingido. Porque não há terminação em no_null_term
, snprintf
continua a ler os dados de output_1
, em que eventualmente atinge um caractere de terminação nulo fornecido pela primeira chamada de snprintf()
. O vazamento de memória é demonstrado pela printf()
daoutput_2
, que contém a sequência de caracteres de no_null_term
duas vezes.null
. Métodos mais antigos de manipulação de cadeias de caracteres dependem frequentemente desse caractere null
para determinar o comprimento da cadeia de caracteres. Se um buffer que não contém um terminador nulo for transmitido para uma dessas funções, a função fará uma leitura além do final do buffer.