Los problemas de validación y representación de entradas están causados por metacaracteres, codificaciones alternativas y representaciones numéricas. Los problemas de seguridad surgen de entradas en las que se confía. Estos problemas incluyen: «desbordamientos de búfer», ataques de «scripts de sitios», "SQL injection" y muchas otras acciones.
cfgfile
y copia la entrada en inputbuf
mediante strcpy()
. El código presupone incorrectamente que inputbuf
siempre contendrá un terminador null.
#define MAXLEN 1024
...
char *pathbuf[MAXLEN];
...
read(cfgfile,inputbuf,MAXLEN); //does not null-terminate
strcpy(pathbuf,inputbuf); //requires null-terminated input
...
Example 1
presentará un comportamiento correcto si los datos leídos desde cfgfile
se finalizan con null en el disco, tal y como se espera. Sin embargo, si el usuario malintencionado puede modificar esta entrada para que no contenga el carácter null
esperado, la llamada a strcpy()
continuará con el proceso de copia desde la memoria hasta que encuentre un carácter null
arbitrario. Es probable que esto desborde el búfer de destino y, si el atacante puede controlar el contenido de la memoria que aparece justo después de inputbuf
, este puede conseguir que la aplicación sea susceptible a un ataque de desbordamiento del búfer.readlink()
amplía el nombre de un vínculo simbólico almacenado en el búfer path
para que el búfer buf
contenga la ruta absoluta del archivo al que hace referencia este vínculo. A continuación, la longitud del valor resultante se calcula mediante strlen()
.
...
char buf[MAXPATH];
...
readlink(path, buf, MAXPATH);
int length = strlen(buf);
...
Example 2
no presentará un comportamiento correcto debido a que el valor leído en buf
por readlink()
no se finalizará con null. En las pruebas, es posible que no se detecten vulnerabilidades como esta debido a que el contenido de buf
no utilizado y la memoria que aparece justo después pueden ser null
, lo que provocaría que strlen()
mostrase aparentemente un comportamiento correcto. Sin embargo, en un entorno real, strlen()
seguirá recorriendo la memoria hasta que detecte un carácter null
arbitrario en la pila, lo que genera un valor de length
mucho más grande que el tamaño de buf
y podría provocar un desbordamiento del búfer en los usos posteriores de este valor.snprintf()
para copiar una cadena de entrada de usuario y colocarla en múltiples cadenas de salida. A pesar de proporcionar protecciones adicionales en comparación con sprintf()
, en particular la especificación de un tamaño máximo de salida, la función snprintf()
aún es susceptible a un error de terminación de cadena cuando el tamaño de salida especificado es mayor que la entrada prospectiva. Los errores de terminación de cadena pueden provocar problemas posteriores, como una pérdida de memoria o un buffer overflow.
...
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
demuestra una pérdida de memoria. Cuando la output_2
incluye no_null_term
, snprintf()
debe leerse desde la ubicación de no_null_term
hasta que se encuentre un carácter nulo o se alcance el límite de tamaño especificado. Como no hay terminación en no_null_term
, snprintf
continúa leyendo los datos de output_1
, donde finalmente alcanza un carácter de terminación nulo proporcionado por la primera llamada de snprintf()
. La pérdida de memoria se demuestra mediante printf()
de output_2
, que contiene la secuencia de caracteres de no_null_term
dos veces.null
. Los métodos de administración de cadenas anteriores utilizaban frecuentemente este carácter null
para determinar la longitud de la cadena. Si un búfer que no contiene un terminador null se transfiere a una de estas funciones, la función leerá más allá del final del búfer.