Uma API é um contrato entre quem chama e o que se chama. As formas mais comuns de abuso de API ocorrem quando o responsável pela chamada não respeita sua parte do contrato. Por exemplo, se um programa não chama chdir() após chamar chroot(), ele viola o contrato que especifica como alterar o diretório raiz ativo de forma segura. Outro bom exemplo de abuso de biblioteca é esperar que o elemento chamado retorne informações confiáveis de DNS ao responsável pela chamada. Nesse caso, o responsável pela chamada abusa a API do elemento chamado ao fazer certas suposições sobre seu comportamento (isto é, que o valor de retorno pode ser usado para fins de autenticação). A outra parte também pode violar o contrato entre quem chama e o que se chama. Por exemplo, se um programador definir SecureRandom como subclasse e retornar um valor não aleatório, o contrato será violado.
Often Misused: File System
MAX_PATH
bytes de comprimento, mas você deve verificar a documentação para cada função individualmente. Se o buffer não for grande o suficiente para armazenar o resultado da manipulação, poderá ocorrer um buffer overflow.Exemplo 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);
}
Nesse exemplo, a função cria um diretório chamado "
output\<name>
" no diretório atual e retorna uma cópia de heap alocado do seu nome. Para a maioria dos valores do diretório atual e do parâmetro "name", essa função funcionará corretamente. No entanto, se o parâmetro name
for particularmente longo, a segunda chamada para PathAppend()
poderá causar um estouro do buffer de outputDirectoryName
, que é menor que MAX_PATH
bytes.umask()
é muitas vezes confundida com o argumento para chmod()
.umask()
começa com a instrução falsa:"umask define a máscara do usuário como a máscara & 0777"
Embora esse comportamento possa condizer melhor com o uso de
chmod()
, no qual o argumento fornecido pelo usuário especifica os bits a serem habilitados no arquivo especificado, o comportamento de umask()
é, na verdade, o oposto: umask()
define umask como ~mask & 0777
.A página man
umask()
continua e descreve o uso correto de umask()
:"Umask é usado por
open()
para definir as permissões de arquivo iniciais em um arquivo recém-criado. Especificamente, as permissões em umask estão desativadas no argumento de modo para open(2)
(e portanto, por exemplo, o valor padrão comum de umask 022 faz com que novos arquivos sejam criados com permissões 0666 & ~022 = 0644 = rw-r--r-- no caso usual em que o modo é especificado como 0666)."Exemplo 1: Este código utiliza as funções que seguem links simbólicos:
...
struct stat output;
int ret = stat(aFilePath, &output);
// error handling omitted for this example
struct timespec accessTime = output.st_atime;
...
umask()
é muitas vezes confundida com o argumento para chmod()
.umask()
começa com a instrução falsa:"umask define a máscara do usuário como a máscara & 0777"
Embora esse comportamento possa condizer melhor com o uso de
chmod()
, no qual o argumento fornecido pelo usuário especifica os bits a serem habilitados no arquivo especificado, o comportamento de umask()
é, na verdade, o oposto: umask()
define umask como ~mask & 0777
.A página man
umask()
continua e descreve o uso correto de umask()
:"A umask é usada para definir as permissões de arquivo iniciais em um arquivo recém-criado. Especificamente, as permissões na umask são desativadas a partir do argumento de modo (assim, por exemplo, o valor umask padrão comum de 022 resulta em novos arquivos que estão sendo criados com permissões 0666 & ~022 = 0644 = rw-r-r-- no caso habitual em que o modo é especificado como 0666)".
Exemplo 1: O seguinte código grava a
transactionId
ativa em um arquivo temporário no diretório Documentos de aplicativo usando um método vulnerável:
...
//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)
...