Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
blogpost_cve-2018-19987-analysis — Este repositório contém um post de blog sobre minha análise do CVE-2018-19987, uma injeção autenticada de comandos do SO que afeta vários roteadores D-Link. | Kitploit
Ferramentas/GitHubGitHub/nahueldsanchez/blogpost_cve-2018-19987-analysis
Segurança IoTAnálise de VulnerabilidadesExploraçãoExploração de Aplicações WebPapers e PesquisaAprendizado e EducaçãoAnálise de Firmware
GitHubnahueldsanchez/blogpost_cve-2018-19987-analysis

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

blogpost_cve-2018-19987-analysis

Este repositório contém um post de blog sobre minha análise do CVE-2018-19987, uma injeção autenticada de comandos do SO que afeta vários roteadores D-Link.

Ver Repositório
213há 5 anosAinda não revisado

Análise de CVE-2018-19987 (injeção de comando no sistema operacional D-Link) URL do Twitter

Seguir no Twitter

Olá!

Neste pequeno post do blog, vou detalhar uma análise rápida que realizei para entender melhor os detalhes por trás do CVE-2018-19987. No começo, procurei esse CVE porque pensei que não houvesse nenhuma informação pública ou exploit. Pouco depois de fazer uma primeira análise, encontrei dois PoCs públicos no GitHub que você pode encontrar aqui e aqui.

Como já tinha feito a maior parte do trabalho e não tinha encontrado uma análise completa, decidi escrever o post de qualquer forma.

Espero que goste!

Atualização: Bem... depois de pesquisar no Google enquanto estava preso neste post do blog, encontrei o seguinte artigo que descreve uma vulnerabilidade muito semelhante (CVE-2018-19986) no D-Link DIR-818. Análise de vulnerabilidade de roteador série (5): Análise e reprodução de injeção de comando CVE-2018-19986 DIR-818LW&828 (traduzido pelo Google) por Ogur1.

Análise de CVE-2018-19987

Comecei minha análise reunindo todas as informações que pude sobre o dispositivo:

  • Nome do consumidor: D-Link DIR-822-US
  • Página do produto: https://us.dlink.com/en/products/dir-822-d-link-wifi-router-ac1200-dual-band
  • Página(s) de suporte: https://support.dlink.com/ProductInfo.aspx?m=DIR-822-US
  • Modelo: DIR-822 Revisão C (Outros dispositivos foram afetados)
  • Versão de firmware afetada: FW v3.01B02
  • Nome do arquivo de firmware afetado: DIR822C1_FW301WWb02.bin (md5sum: 1bff7ec8b4da0643f65b4d44c630e92b)
  • Versão de firmware corrigida: FW v3.13
  • Nome do arquivo de firmware corrigido: DIR822C1_FW313WWb01.bin (md5sum: aa16c7016f67be384e0784e439ce26d2)
  • Página de arquivo de firmware: ftp://ftp2.dlink.com/PRODUCTS/DIR-822-US/REVC/

Análise da causa raiz

Nota: realizei toda a análise com o firmware v3.01B02.

As informações públicas para esta vulnerabilidade, disponíveis na página do Mitre, forneceram informações suficientes para começar:

root@kitploit:~
dispositivos D-Link DIR-822 Rev.B 202KRb06, DIR-822 Rev.C 3.10B06, DIR-860L Rev.B 2.03.B03, DIR-868L Rev.B 2.05B02, DIR-880L Rev.A 1.20B01_01_i3se_BETA e DIR-890L Rev.A 1.21B02_BETA manipulam incorretamente IsAccessPoint em /HNAP1/SetAccessPointMode. No código-fonte do SetAccessPointMode.php, o parâmetro IsAccessPoint é salvo no arquivo de script ShellPath sem qualquer verificação de regex. Após a execução do arquivo de script, ocorre a injeção de comando. Uma mensagem XML vulnerável do /HNAP1/SetAccessPointMode poderia conter metacaracteres de shell no elemento IsAccessPoint, como a string `telnetd`.

Para iniciar a análise, precisei de algo para examinar, então prossegui para extrair o sistema de arquivos do roteador.

root@kitploit:~
binwalk -eM DIR822C1_FW301WWb02.bin

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             DLOB firmware header, boot partition: "dev=/dev/mtdblock/1"
10380         0x288C          LZMA compressed data, properties: 0x5D, dictionary size: 8388608 bytes, uncompressed size: 4213444 bytes
1376372       0x150074        PackImg section delimiter tag, little endian size: 10505216 bytes; big endian size: 5021696 bytes
1376404       0x150094        Squashfs filesystem, little endian, version 4.0, compression:lzma, size: 5019773 bytes, 2282 inodes, blocksize: 131072 bytes, created: 2016-03-18 09:35:31

Como podemos ver, o Binwalk detecta um sistema de arquivos Linux. Se olharmos mais atentamente as informações que temos, podemos ver que o aviso menciona o caminho /HNAP1. Portanto, podemos começar a examinar como o roteador lida com essas URLs.

Tratamento de solicitações HNAP1

Conforme explicado no excelente post do blog /dev/tty0, essas URLs no final são tratadas por um binário chamado cgibin, localizado em htdocs/cgibin. Mas eu queria entender melhor como isso estava configurado e, no final, me levou a ter que entender como o servidor HTTP estava configurado para processar solicitações. Procurei pelo nome do arquivo httpd.conf, assumindo que era usado para configurar o servidor HTTP, e encontrei um arquivo chamado HTTP.php na pasta /etc/services/, contendo, entre outras coisas, as seguintes linhas interessantes:

root@kitploit:~
$httpd_conf = "/var/run/httpd.conf";
fwrite("a",$START, "xmldbc -P /etc/services/HTTP/httpcfg.php > ".$httpd_conf."\n");
fwrite("a",$START, "event PREFWUPDATE add /etc/scripts/prefwupdate.sh\n");
fwrite("a",$START, "httpd -f ".$httpd_conf."\n");
fwrite("a",$START, "event HTTP.UP\n");
fwrite("a",$START, "exit 0\n");

Presumi que em algum momento esse arquivo é executado e escreve o arquivo /var/run/httpd.conf. Para aprender como o servidor web estava configurado, prossegui para analisar o arquivo /etc/services/HTTP/httpcfg.php (incluí apenas as partes relevantes):

root@kitploit:~
	if ($hnap > 0)
	{
		echo
		"		Control".							"\n".
		"		{".									"\n".
		"			Alias /HNAP1".					"\n".
		"			Location /htdocs/HNAP1".		"\n".
		"			External".						"\n".
		"			{".								"\n".
		"				/usr/sbin/hnap { hnap }".	"\n".
		"			}".								"\n".
		"			IndexNames { index.hnap }".		"\n".
		"		}".									"\n";
	}

Agora temos todas as peças! Podemos assumir que o servidor web está configurado para lidar com solicitações HTTP para /HNAP1 usando o /usr/sbin/hnap, e com base no post do blog /dev/tty0 sabemos que será um link para o binário htdocs/cgibin.

O próximo passo foi dar uma olhada no binário cgibin para entender como ele lidava com solicitações HNAP. Na imagem a seguir podemos ver parte da função main descompilada, onde o caminho da URL passado para ela é comparado com diferentes caminhos (como session.cgi, authentication.cgi, captcha.cgi, para citar alguns) até que hnap seja encontrado e nossa função hnap_main seja chamada.

nota: Ao analisar a função main, tive alguns problemas para identificar a string hnap, pois o Ghidra não a detectou como string durante a análise inicial.

O próximo passo foi entender o que essa função fazia. Fornecerei apenas trechos de código para as partes relevantes que ajudarão a entender melhor o que a função faz, e também completarei outras partes relevantes com algum pseudocódigo — renomeei algumas variáveis para esclarecer seu propósito.

root@kitploit:~
...
HTTP_SOAPACTION = getenv("HTTP_SOAPACTION");
REQUEST_METHOD = getenv("REQUEST_METHOD");
HNAP_AUTH = getenv("HTTP_HNAP_AUTH");
__haystack = getenv("HTTP_COOKIE");
pcVar1 = getenv("HTTP_REFERER");

...
if (HTTP_SOAPACTION != "") {
	if  (HTTP_SOAPACTION == GetDeviceSettings) {
		...
	} else {
		// These actions will occur during auth. Process
		if ("GetCAPTCHAsetting" in HTTP_SOAPACTION) {
			sess_generate_captcha();
		} else {
			if ("Login" in HTTP_SOAPACTION) {
				perform_login();
			}
			// We'll land here once auth.
			if (HNAP_AUTH != "") {
				if ("uid=" in HTTP_COOKIE){
					is_valid_auth = perform_auth_process()
					if (is_valid_auth) {
						if("logout" in HTTP_SOAPACTION){
							perform_logout();
						// If we are auth. and NOT trying to logout
						// the code will try to perform the action
						// we requested
						} else {
							// If we arrive here we win
							// interesting code below
							goto LAB_004141d4;
						}

					}
				}
			}
			// If we are not authenticated we can't do anything
			Return "You need proper authorization to use this resource"
		}
	}
} else {
	...
}

LAB_004141d4:
    hnap_action = get_hnap_operation(HTTP_SOAPACTION);
    if (HTTP_SOAPACTION != "") {
    	hnap_action_len = strlen(hnap_action);
	}
	snprintf(path_to_hnap_php_file,0x100,"%s/%s.php","/etc/templates/hnap/",hnap_action);
	if (!check_file_access(path_to_hnap_php_file)){
		return "HNAP ACTION DOES NOT EXIST (FAIL)"
	}
	if (REQUEST_METHOD == "POST") {

		// Here arguments for the PHP are extracted
		parse_request_and_extract_xml()
    
		if (hnap_action == "GetFirmwareStatus") {
        	system("sh /etc/events/checkfw.sh > /dev/console");
		}

		// Here the final arguments for the xmldbc_ephp are crafted
        snprintf(ARGS_FOR_XMLDBC_PHP,0x100,"%s%s.php\nShellPath=%s%s.sh\nPrivateKey=%s\n",
                 "/etc/templates/hnap/", hnap_action, &ShellPath, hnap_action, &PRIVATE_KEY);

		// PHP is executed (in our case SetAccessPointMode.php) and the shell
		// script is written to ShellPath 
        xmldbc_ephp(0,0,ARGS_FOR_XMLDBC_PHP,stdout);
        snprintf(hnap_action, 0x100, "%s", hnap_action);
       
	   	// Shell command is built to run the previously written shell file
		// (File written by the PHP script)
        shell_command = "sh %s%s.sh > /dev/console &";
        }
        snprintf(cmd_to_execute, 0x100, shell_command, &PATH, hnap_action);

		// File is executed containing the command injection
        system(cmd_to_execute);
    }
...

Após concluir a análise desta função, decidi dar uma olhada no arquivo PHP SetAccessPointMode.php — que no final era o que continha a falha — e tentei juntar todas as peças:

root@kitploit:~
...
$IsAccessPoint	= query("/runtime/hnap/SetAccessPointMode/IsAccessPoint");
...
fwrite("w",$ShellPath, "#!/bin/sh\n");
fwrite("a",$ShellPath, "echo [$0] $1 ... > /dev/console\n");
fwrite("a",$ShellPath, "echo IsAccessPoint = ".$IsAccessPoint." > /dev/console\n");
fwrite("a",$ShellPath, "echo Result = ".$Result."\n");
...

Como podemos ver, temos a variável $ShellPath que é preenchida pela função hnap_main e a variável $IsAccessPoint controlada pelo usuário e passada na solicitação XML enviada. Com isso, podemos corroborar como uma injeção de comando do sistema operacional na variável escrita pelo arquivo PHP é executada. Aqui você pode encontrar um PoC completo desenvolvido por pr0v3rbs para explorar este problema.

Discutiremos um pouco mais sobre as versões afetadas e corrigidas mais tarde. Como você pode ver na tabela abaixo, parece que houve algum tipo de regressão com o patch, que reintroduziu essa vulnerabilidade em versões que já deveriam ter sido corrigidas.

Firmware versions analyzed

(*) Não verifiquei essas versões de firmware, pois suas contrapartes não criptografadas eram vulneráveis.

Como podemos ver na tabela acima, a vulnerabilidade foi corrigida em algumas versões de firmware removendo o arquivo PHP afetado SetAccessPointMode.php. Uma vez que o arquivo não existe, as verificações realizadas na função falharão e nada será executado. Confirmei isso analisando a hnap_function nas versões de firmware FW v3.131 e 3.15B02 WW; o código para hnap_main não mudou em relação a este problema, mas o arquivo PHP não estava mais presente.

O que é mais interessante é que, de alguma forma, esse bug foi reintroduzido na versão de firmware FW v3.11 até FW v3.12B04, depois de ter sido corrigido na versão 3.11B01_icjg_WW.

Conclusões e próximos passos

Como primeira conclusão, diria: nunca confie nesses dispositivos como um dispositivo verdadeiramente seguro — o que aconteceu com as atualizações é um exemplo claro de por que você não deveria fazer isso. Além disso, após a análise realizada, posso concluir que o primeiro PoC listado neste post do blog não funcionará para esta versão específica, pois vimos que existem algumas condições que devem ser cumpridas para executar o arquivo PHP vulnerável.

E a conclusão mais importante: tenha muito cuidado ao decidir o quão crítica é uma vulnerabilidade com base em sua pontuação CVSS. Decidi analisar este CVE porque foi classificado como 9.8 (CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H) e está claro que, pelo menos para esta versão, o invasor precisará de credenciais para poder explorá-la.

Como próximos passos, vou trabalhar para conseguir emular este binário para explorar essa vulnerabilidade sem ter acesso ao roteador em si, mas isso será material para outro post!

Obrigado por ler.

References

  • Write-up de Ogur1 para CVE-2018-19986
  • Post do blog /dev/tty0 sobre HNAP da D-Link
  • Aviso de HNAP de Pedro Ribeiro
  • CVE-2018-19987 PoC #0 por Mario Ceballos
  • CVE-2018-19987 PoC #1 por Mingeun Kim
  • Link de detalhes do CVE-2018-19987
  • Descriptografando firmware D-Link
  • Binwalk
  • pro0v3rbs Poc
Baixar ferramenta
FirmwareVersãoHash MD5Data de lançamentoVulnerável
DIR822C1_FW315WWb02.bin3.15B02 WW7121771c3e1706ba76fbf244023efad306/11/2019NÃO
DIR822C1_FW313WWb01.binFW v3.13aa16c7016f67be384e0784e439ce26d210/07/2019NÃO
DIR822C1_FW303WWb04_i4sa_middle.binFW v3.12B04c3b9a3f115c02e739690616aba2f2d9926/04/2019SIM
DIR822C1_FW312WWb04.binFW v3.12B04eb11afbd136a5b29cea18141f727bfa826/04/2019SIM (*)
DIR822C1_FW311WWb01.binFW v3.116d7c90eaaae835667faea65c862b3c8201/01/2019SIM
DIR822C1_FW311bWWb01_icjg.bin3.11B01_icjg_WW75e361e1465604aeda5d5dbcaecca97721/12/2018NÃO
DIR822C1_FW303WWb04_i4sa_middle.binFW v3.10B06c3b9a3f115c02e739690616aba2f2d9917/08/2018SIM
DIR822C1_FW310WWb06.binFW v3.10B06e33db75d0801fddb1c90308982e69fe517/08/2018SIM (*)
DIR-822_C1_FW302WWb05.binFW v3.020dbf840c0ff5d3a5b593d33690e15d8214/09/2017SIM
DIR822C1_FW301WWb02.binFW v3.01B021bff7ec8b4da0643f65b4d44c630e92b27/04/2016SIM