
CVE-2017-14948 para firmware D-Link 880
Neste pequeno artigo, veremos algumas falhas que encontrei em produtos D-Link. A D-Link oferece uma ampla gama de produtos, incluindo muitos modelos diferentes de roteadores, com diferentes versões de firmware. Neste documento, abordarei as seguintes versões de firmware: DIR-880L, DIR-868L, DIR-890L, DIR-885L e DIR-895L. Sem mais delongas, vamos começar.
Como eu não possuía nenhum dos roteadores D-Link, e eles fornecem acesso gratuito aos seus firmwares, decidi encontrar falhas apenas por meio de análise estática. Observe que, nesta seção, me referirei ao firmware DIR-880L; os outros firmwares possuem estruturas semelhantes.
Após baixar e descompactar o firmware do DIR-880L, descobri que seu firmware contém um sistema de arquivos squashFS completo, com cerca de 2160 arquivos. Como não queria considerar cada um deles individualmente, comecei a procurar aquele que lida com entradas do usuário.
Após analisar os arquivos de configuração e procurar por cabeçalhos HTTP conhecidos, finalmente restringi meu foco a três binários e, por fim, a um: fileaccess.cgi.
Aqui está a desmontagem da função vulnerável:
signed int __fastcall content_type(char *a1)
{
char *dest; // [sp+4h] [bp-10h]@1
const char *haystack; // [sp+Ch] [bp-8h]@1
char *haystacka; // [sp+Ch] [bp-8h]@3
dest = a1;
haystack = getenv("CONTENT_TYPE");
if ( !haystack )
return -22;
haystacka = strstr(haystack, "boundary=");
if ( !haystacka )
return -22;
strcpy(dest, haystacka + 9);
return 0;
}
No código acima, o conteúdo da variável 'CONTENT_TYPE' (apontada pela variável haystack) é controlado pelo usuário (através do cabeçalho da requisição HTTP). Seu conteúdo, após a palavra-chave 'boundary', é então copiado para um buffer dest, sem verificar o comprimento de haystacka. Se observarmos a função chamadora (endereço 0x1CE6C), podemos inferir que o tamanho de dest é de 256 bytes. Como um atacante pode controlar o conteúdo de CONTENT_TYPE, ele poderia enviar a string 'boundary=' seguida de pelo menos 257 caracteres para desencadear um estouro de buffer.
Outras duas falhas semelhantes foram encontradas na mesma amostra de firmware, envolvendo o cookie HTTP. Uma delas é mostrada abaixo:
v10 = getenv("HTTP_COOKIE");
if ( v10 )
{
strcpy((char *)&v5, &v10[v11]);
v17 = strlen((const char *)&v5);
}
Aqui, a variável v10 aponta para o cookie do usuário, que pode ter no máximo 4k bytes (de acordo com a RFC2109). No entanto, a variável v5 tem 1024 bytes (como podemos inferir pelo quadro de pilha da função). Isso pode desencadear um estouro de buffer.
Essas falhas foram reportadas e confirmadas pela D-Link.
Essas amostras de firmware apresentam estrutura semelhante ao DIR-880L e possuem as mesmas falhas relacionadas aos mesmos campos HTTP.