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: Authentication
Exemplo: A amostra de código a seguir usa uma pesquisa de DNS para decidir se uma solicitação de entrada é ou não proveniente de um host confiável. Se um invasor puder envenenar o cache de DNS, ele poderá obter um status confiável.
IPAddress hostIPAddress = IPAddress.Parse(RemoteIpAddress);
IPHostEntry hostInfo = Dns.GetHostByAddress(hostIPAddress);
if (hostInfo.HostName.EndsWith("trustme.com")) {
trusted = true;
}
Endereços IP são mais confiáveis que nomes DNS, mas também podem ser falsificados. Os invasores podem facilmente falsificar o endereço IP de origem dos pacotes que eles enviam, mas os pacotes de resposta retornarão ao endereço IP falsificado. Para ver os pacotes de resposta, o invasor precisa realizar o sniffing do tráfego entre a máquina da vítima e o endereço IP falsificado. Para realizar o sniffing necessário, os invasores normalmente tentam se localizar na mesma sub-rede que a máquina da vítima. Os invasores podem ser capazes de se esquivar dessa exigência usando o roteamento de origem, mas esse roteamento não está habilitado em uma grande extensão da Internet hoje em dia. Em resumo, a verificação de endereços IP pode ser uma parte útil de um esquema de autenticação, mas não deve ser o único fator necessário para a autenticação.
getlogin()
é fácil de falsificar. Não confie no nome que ela retorna.getlogin()
deve retornar uma string contendo o nome do usuário atualmente conectado ao terminal, mas um invasor pode fazer com que getlogin()
retorne o nome de qualquer usuário conectado à máquina. Não confie no nome retornado por getlogin()
ao tomar decisões de segurança.Exemplo 1: O código a seguir se baseia em
getlogin()
para determinar se um usuário é ou não confiável. Isso é facilmente contestado.
pwd = getpwnam(getlogin());
if (isTrustedGroup(pwd->pw_gid)) {
allow();
} else {
deny();
}
Exemplo: O código a seguir usa uma pesquisa de DNS para determinar se uma solicitação de entrada é proveniente de um host confiável. Se um invasor puder envenenar o cache de DNS, ele poderá obter um status confiável.
String ip = request.getRemoteAddr();
InetAddress addr = InetAddress.getByName(ip);
if (addr.getCanonicalHostName().endsWith("trustme.com")) {
trusted = true;
}
Endereços IP são mais confiáveis que nomes DNS, mas também podem ser falsificados. Os invasores podem facilmente falsificar o endereço IP de origem dos pacotes que eles enviam, mas os pacotes de resposta retornarão ao endereço IP falsificado. Para ver os pacotes de resposta, o invasor precisa realizar o sniffing do tráfego entre a máquina da vítima e o endereço IP falsificado. Para realizar o sniffing necessário, os invasores normalmente tentam se localizar na mesma sub-rede que a máquina da vítima. Os invasores podem ser capazes de se esquivar dessa exigência usando o roteamento de origem, mas esse roteamento não está habilitado em uma grande extensão da Internet hoje em dia. Em resumo, a verificação de endereços IP pode ser uma parte útil de um esquema de autenticação, mas não deve ser o único fator necessário para a autenticação.