Reino: API Abuse

Un API es un contrato entre un autor de llamada y un receptor de llamada. Las formas de abuso de API más comunes los produce el autor de llamada cuando no consigue atender su fin de este contrato. Por ejemplo, si un programa no consigue llamar chdir() después de llamar chroot(), se viola el contrato que especifica cómo cambiar el directorio de origen activo de una forma segura. Otro buen ejemplo de un abuso de manual es esperar que el receptor devuelva una información de DNS de confianza al autor de llamada. En este caso, el autor de llamada abusa el API del receptor haciendo determinadas suposiciones sobre su comportamiento (que el valor de retorno se puede usar con fines de autenticación). También se puede violar el contrato entre el autor de llamada y el receptor desde el otro lado. Por ejemplo, si un codificador envía SecureRandom y devuelve un valor no aleatorio, se viola el contrato.

Missing Check against Null

Abstract
Es posible que el programa elimine la referencia de un puntero nulo porque no comprueba el valor de devolución de una función que puede que devuelva un valor null.
Explanation
Prácticamente cada ataque grave a un sistema de software comienza con la infracción de los supuestos del programador. Después del ataque, las suposiciones del programador parecen débiles y mal fundadas, pero antes de un ataque muchos programadores defenderían sus suposiciones mucho más allá del final de la hora del almuerzo.

Dos supuestos dudosos fácilmente detectables en el código son "la llamada a esta función no presentará nunca errores" y "no importa si presenta errores la función a esta llamada". Si un programador omite el valor de devolución de una función, indican de forma implícita que están trabajando baso una de estas suposiciones.
Ejemplo 1: el siguiente código no comprueba si la cadena devuelta por la propiedad Item es null antes de llamar a la función miembro Equals(), lo que podría provocar una eliminación de referencia de un valor null.


string itemName = request.Item(ITEM_NAME);
if (itemName.Equals(IMPORTANT_ITEM)) {
...
}
...


La defensa tradicional de este código de error es la siguiente:

"Sé que el valor solicitado siempre existirá porque... Si no existe, el programa no puede presentar el comportamiento deseado, por lo que no importa si gestiono el error o solo permito que el programa se anule mediante la eliminación de la referencia de un valor null".

Sin embargo, los usuarios malintencionados son expertos en buscar rutas inesperadas a través de programas, sobre todo, cuando se producen excepciones.
desc.controlflow.dotnet.missing_check_against_null
Abstract
Es posible que el programa elimine la referencia de un puntero nulo porque no comprueba el valor de devolución de una función que puede que devuelva un valor null.
Explanation
Prácticamente cada ataque grave a un sistema de software comienza con la infracción de los supuestos del programador. Después del ataque, las suposiciones del programador parecen débiles y mal fundadas, pero antes de un ataque muchos programadores defenderían sus suposiciones mucho más allá del final de la hora del almuerzo.

Dos supuestos dudosos fácilmente detectables en el código son "la llamada a esta función no presentará nunca errores" y "no importa si presenta errores la función a esta llamada". Si un programador omite el valor de devolución de una función, indican de forma implícita que están trabajando baso una de estas suposiciones.
Ejemplo 1: el siguiente código no comprueba si la asignación de memoria se realizó correctamente antes de intentar usar el puntero devuelto por malloc().


buf = (char*) malloc(req_size);
strncpy(buf, xfer, req_size);


La defensa tradicional de este código de error es la siguiente:

"Si se agota la memoria del programa, este presentará errores. No importa si administro el error o simplemente dejo que el programa finalice con un error de segmentación cuando intenta eliminar la referencia del puntero nulo".

Este argumento pasa por alto tres consideraciones importantes:

- En función del tipo y el tamaño de la aplicación, puede que sea posible liberar la memoria que se está utilizando en otra ubicación para que la ejecución pueda continuar.

- Es imposible que el programa realice una salida de manera hábil si es necesario. Si el programa realiza una operación atómica, puede dejar el sistema en un estado inconsistente.

- El programador ha perdido la oportunidad de registrar la información de diagnóstico. ¿La llamada a malloc() presentó errores debido a que req_size era demasiado grande o a que se estaban administrando demasiadas solicitudes al mismo tiempo? ¿O el error lo provocó una pérdida de memoria que se acumuló a lo largo de un periodo? Si no se administra el error, es imposible saberlo.
References
[1] J. Viega, G. McGraw Building Secure Software Addison-Wesley
desc.controlflow.cpp.missing_check_against_null
Abstract
Es posible que el programa elimine la referencia de un puntero nulo porque no comprueba el valor de devolución de una función que puede que devuelva un valor null.
Explanation
Prácticamente cada ataque grave a un sistema de software comienza con la infracción de los supuestos del programador. Después del ataque, las suposiciones del programador parecen débiles y mal fundadas, pero antes de un ataque muchos programadores defenderían sus suposiciones mucho más allá del final de la hora del almuerzo.

Dos supuestos dudosos fácilmente detectables en el código son "la llamada a esta función no presentará nunca errores" y "no importa si presenta errores la función a esta llamada". Si un programador omite el valor de devolución de una función, indican de forma implícita que están trabajando baso una de estas suposiciones.

Ejemplo 1: El siguiente código no comprueba si la cadena devuelta por getParameter() es null antes de llamar a la función miembro compareTo(), lo que podría provocar una desreferencia de null.


String itemName = request.getParameter(ITEM_NAME);
if (itemName.compareTo(IMPORTANT_ITEM)) {
...
}
...
Ejemplo 2:. en el siguiente código se muestra una propiedad del sistema que se establece en un valor null y un programador elimina posteriormente su referencia al presuponer de forma incorrecta que siempre está definida.


System.clearProperty("os.name");
...
String os = System.getProperty("os.name");
if (os.equalsIgnoreCase("Windows 95") )
System.out.println("Not supported");


La defensa tradicional de este código de error es la siguiente:

"Sé que el valor solicitado siempre existirá porque... Si no existe, el programa no puede presentar el comportamiento deseado, por lo que no importa si gestiono el error o solo permito que el programa se anule mediante la eliminación de la referencia de un valor null".

Sin embargo, los usuarios malintencionados son expertos en buscar rutas inesperadas a través de programas, sobre todo, cuando se producen excepciones.
desc.controlflow.java.missing_check_against_null