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.
Often Misused: File System
MAX_PATH
bytes, aunque debe consultar la documentación de cada función individualmente. Si el búfer no tiene la longitud suficiente como para almacenar el resultado de la manipulación, podría producirse un desbordamiento de búfer.Ejemplo 1:
char *createOutputDirectory(char *name) {
char outputDirectoryName[128];
if (getCurrentDirectory(128, outputDirectoryName) == 0) {
return null;
}
if (!PathAppend(outputDirectoryName, "output")) {
return null;
}
if (!PathAppend(outputDirectoryName, name)) {
return null;
}
if (SHCreateDirectoryEx(NULL, outputDirectoryName, NULL)
!= ERROR_SUCCESS) {
return null;
}
return StrDup(outputDirectoryName);
}
En este ejemplo, la función crea un directorio llamado "
output\<name>
" en el directorio actual y devuelve una copia de su nombre asignada por montón. Para la mayoría de los valores del directorio actual y el parámetro de nombre, esta función funcionará correctamente. Sin embargo, si el parámetro name
es especialmente largo, entonces la segunda llamada a PathAppend()
podría provocar el buffer overflow outputDirectoryName
, que tiene menos de MAX_PATH
bytes.umask()
se confunde habitualmente con el argumento para chmod()
.umask()
comienza por la instrucción falsa:"umask sets the umask to mask & 0777"
Aunque este comportamiento se ajustaría más al uso de
chmod()
, cuando el argumento proporcionado por el usuario especifica los bits para habilitar el archivo concreto, el comportamiento de umask()
es precisamente el contrario: umask()
establece umask en ~mask & 0777
.La página man de
umask()
continúa para describir el uso correcto de umask()
:"
open()
utiliza umask para establecer los permisos de archivo iniciales de un archivo recién creado. De forma específica, los permisos de umask se desactivan desde el argumento de modo para open(2)
(de esta forma, por ejemplo, el valor predeterminado umask normal de 022 resultados en los archivos que se están creando con permisos 0666 & ~022 = 0644 = rw-r--r-- en el caso habitual donde se encuentra el modo se especifica como 0666)".Ejemplo 1: el código siguiente utiliza las funciones que siguen los vínculos simbólicos:
...
struct stat output;
int ret = stat(aFilePath, &output);
// error handling omitted for this example
struct timespec accessTime = output.st_atime;
...
umask()
se confunde habitualmente con el argumento para chmod()
.umask()
comienza por la instrucción falsa:"umask establece umask para enmascarar & 0777"
Aunque este comportamiento se ajustaría más al uso de
chmod()
, cuando el argumento proporcionado por el usuario especifica los bits para habilitar el archivo concreto, el comportamiento de umask()
es precisamente el contrario: umask()
establece umask en ~mask & 0777
.La página man de
umask()
continúa para describir el uso correcto de umask()
:"Se utiliza umask para establecer los permisos de archivo iniciales de un archivo recién creado. De forma específica, los permisos umask se desactivan desde el argumento de modo (de esta forma, por ejemplo, el valor predeterminado umask normal de 022 da como resultado nuevos archivos que se crean con permisos 0666 & ~022 = 0644 = rw-r--r-- en el caso habitual donde el modo se especifica como 0666)."
Ejemplo 1: el código siguiente escribe el
transactionId
activo en un archivo temporal del directorio Documentos de la aplicación empleando un método vulnerable:
...
//get the documents directory:
let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0]
//make a file name to write the data to using the documents directory:
let fileName = NSString(format:"%@/tmp_activeTrans.txt", documentsPath)
// write data to the file
let transactionId = "TransactionId=12341234"
transactionId.writeToFile(fileName, atomically:true)
...