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.
send
y sus variantes permiten a los programadores evitar los especificadores de acceso de Ruby en las funciones. En concreto, permite a los programadores acceder a funciones y a campos privados y protegidos, un comportamiento normalmente no permitido.paramName
.
...
<bookmark>
<method>#{paramHandler.handleParams}</method>
<url-parameter>
<name>paramName</name>
<value>#{requestScope.paramName}</value>
</url-parameter>
</bookmark>
...
userClassPath
modificable por el usuario para determinar el directorio donde buscar las clases para cargar.
...
productCategory = this.getIntent().getExtras().getString("userClassPath");
DexClassLoader dexClassLoader = new DexClassLoader(productCategory, optimizedDexOutputPath.getAbsolutePath(), null, getClassLoader());
...
userClassPath
para que señale a una ruta diferente que controla este. Como el programa no valida el valor leído del entorno, si un usuario malintencionado puede controlar el valor de userClassPath
, podría engañar a la aplicación para que señalara un directorio controlado por él y, por lo tanto, cargar las clases que hubiera definido, utilizando los mismos privilegios que la aplicación original.userOutput
modificable por el usuario para determinar el directorio donde deberían escribirse los archivos DEX optimizados.
...
productCategory = this.getIntent().getExtras().getString("userOutput");
DexClassLoader dexClassLoader = new DexClassLoader(sanitizedPath, productCategory, null, getClassLoader());
...
userOutput
por un directorio que controle, como por ejemplo almacenamiento externo. Una vez logrado esto, basta con reemplazar el archivo ODEX producido con un archivo ODEX malintencionado para ejecutar este con los mismos privilegios que la aplicación original.ModelState.IsValid
para comprobar si la validación del modelo es correcta.class.classLoader
, que le permitirá sobrescribir propiedades del sistema y ejecutar potencialmente código arbitrario.
String prop = request.getParameter('prop');
String value = request.getParameter('value');
HashMap properties = new HashMap();
properties.put(prop, value);
BeanUtils.populate(user, properties);
strncpy()
, pueden provocar vulnerabilidades cuando se utilizan incorrectamente. La combinación de manipulación de memoria y presuposiciones erróneas acerca del tamaño y la formación de una unidad de datos es el motivo principal de la mayoría de desbordamientos del búfer.gets()
para leer una cantidad arbitraria de datos en un búfer de pila. Como no hay forma de limitar la cantidad de datos leídos por esta función, la seguridad del código depende siempre de que el usuario introduzca un número de caracteres inferior a BUFSIZE
.Ejemplo 1.b: en este ejemplo se muestra lo fácil que es imitar el comportamiento poco seguro de la función
...
char buf[BUFSIZE];
gets(buf);
...
gets()
en C++ mediante el uso del operador >>
para leer la entrada en una cadena char[]
.Ejemplo 2: el código de este ejemplo utiliza también la entrada de usuario para controlar su comportamiento, pero añade un nivel de indirección con el uso de la función de copia de memoria limitada
...
char buf[BUFSIZE];
cin >> (buf);
...
memcpy()
. Esta función acepta un búfer de destino y uno de origen, y el número de bytes que se va a copiar. El búfer de entrada se llena con una llamada limitada a read()
. Sin embargo, el usuario especifica el número de bytes que memcpy()
copia.
...
char buf[64], in[MAX_SIZE];
printf("Enter buffer contents:\n");
read(0, in, MAX_SIZE-1);
printf("Bytes to copy:\n");
scanf("%d", &bytes);
memcpy(buf, in, bytes);
...
lccopy()
utiliza una cadena como argumento y devuelve la copia asignada por montón de la cadena con las letras en mayúsculas convertidas a minúsculas. La función no realiza ninguna comprobación de límites en esta entrada por esquema que str
sea siempre menor que BUFSIZE
. Si un usuario malintencionado omite las comprobaciones del código que llama a lccopy()
o si un cambio realizado en ese código invalida la presuposición acerca del tamaño de str
, lccopy()
desbordará buf
con la llamada a strcpy()
no limitada.Ejemplo 4: El siguiente código demuestra el tercer escenario en el que el código es tan complejo que su comportamiento no se puede predecir fácilmente. Este código proviene del popular decodificador de imágenes libPNG, que es utilizado por una amplia gama de aplicaciones.
char *lccopy(const char *str) {
char buf[BUFSIZE];
char *p;
strcpy(buf, str);
for (p = buf; *p; p++) {
if (isupper(*p)) {
*p = tolower(*p);
}
}
return strdup(buf);
}
png_crc_read()
. Sin embargo, justo después de que se pruebe la longitud, el código realiza una comprobación en png_ptr->mode
y, si esta presenta errores, se emite una advertencia y el proceso continúa. Como length
se prueba en un bloque else if
, length
no se probará si la primera comprobación presenta errores y se utilizará ciegamente en la llamada a png_crc_read()
, provocando un posible buffer overflow de pila.Ejemplo 5: en este ejemplo también se muestra el tercer escenario en el que la complejidad del programa lo expone a desbordamientos del búfer. En ese caso, la exposición se debe a la interfaz ambigua de una de las funciones en lugar de a la estructura del código (como sí lo hacía en el ejemplo anterior).
if (!(png_ptr->mode & PNG_HAVE_PLTE)) {
/* Should be an error, but we can cope with it */
png_warning(png_ptr, "Missing PLTE before tRNS");
}
else if (length > (png_uint_32)png_ptr->num_palette) {
png_warning(png_ptr, "Incorrect tRNS chunk length");
png_crc_finish(png_ptr, length);
return;
}
...
png_crc_read(png_ptr, readbuf, (png_size_t)length);
getUserInfo()
utiliza un nombre de usuario especificado por una cadena multibyte y un puntero a una estructura para la información de usuario, y rellena la estructura con información del usuario. Como la autenticación de Windows utiliza Unicode para los nombres de usuario, el argumento username
se convierte primero de una cadena multibyte a una Unicode. A continuación, esta función transfiere de forma incorrecta el tamaño de unicodeUser
en bytes en lugar de caracteres. Así pues, la llamada a MultiByteToWideChar()
puede escribir hasta (UNLEN+1)*sizeof(WCHAR)
caracteres anchos o (UNLEN+1)*sizeof(WCHAR)*sizeof(WCHAR)
bytes en la matriz unicodeUser
, que solo tiene (UNLEN+1)*sizeof(WCHAR)
bytes asignados. Si la cadena username
contiene más de UNLEN
caracteres, la llamada a MultiByteToWideChar()
desbordará el búfer unicodeUser
.
void getUserInfo(char *username, struct _USER_INFO_2 info){
WCHAR unicodeUser[UNLEN+1];
MultiByteToWideChar(CP_ACP, 0, username, -1,
unicodeUser, sizeof(unicodeUser));
NetUserGetInfo(NULL, unicodeUser, 2, (LPBYTE *)&info);
}
strncpy()
, pueden provocar vulnerabilidades cuando se utilizan incorrectamente. La combinación de manipulación de memoria y presuposiciones erróneas acerca del tamaño y la formación de una unidad de datos es el motivo principal de la mayoría de desbordamientos del búfer.c
porque el tipo double
necesita más espacio que el asignado para c
.
void formatString(double d) {
char c;
scanf("%d", &c)
}