
Roteador ASUS infosvr UDP Broadcast Execução de Comandos como root
========================================================
Diversos modelos de roteadores da ASUS incluem um serviço chamado infosvr que escuta na porta 9999 de broadcast UDP nas interfaces LAN ou WLAN. Ele é usado por uma das ferramentas da ASUS para facilitar a configuração do roteador, localizando automaticamente os roteadores na sub-rede local. Esse serviço executa com privilégios de root e contém uma vulnerabilidade de execução de comandos sem autenticação. O código-fonte desse serviço, bem como do restante do roteador, está disponível no Site de Suporte da ASUS.
O CVE atribuído a este problema é CVE-2014-9583 (infelizmente, não foi CVE-2014-10000, afinal :-/).
Atualmente, presume-se que todas as versões de firmware conhecidas para os roteadores aplicáveis (RT-AC66U, RT-N66U, etc.) sejam vulneráveis. Os testes foram realizados contra a versão 3.0.0.4.376.2524-g0013f52.
Os seguintes roteadores/versões de firmware são confirmadamente vulneráveis:
| Roteador | Versão do Firmware | Verificado Por |
|---|---|---|
| RT-N66U | 3.0.0.4.376_1071-g8696125 | Friedrich Postelstorfer |
| RT-AC87U | 3.0.0.4.378_3754 | David Longenecker |
| RT-N56U | 3.0.0.4.374_5656 | @argilo |
| RT-AC68U | 3.0.0.4.376_3626-g9a8323e | @Arie |
| DSL-N55U | 3.0.0.4.374_4422-gc83c78f | @S2- |
| DSL-AC68U | 3.0.0.4.376_2158-g340202b | @magJ, @gitFurious |
| RT-AC66R | 3.0.0.4.376_2524-g0013f52 | @asgh |
| RT-AC66R | 3.0.0.4.376_3602 | @facerolling |
| RT-AC55U | 3.0.0.4.376_6587-gaa506e9 | @pellaeon |
| RT-N12HP_B1 | 3.0.0.4.374_1327 | @vittee |
| RT-N16 | 3.0.0.4.220 | @xorrbit |
Além disso, roteadores que executam firmware baseado no asuswrt-merlin, apoiado pela comunidade, são vulneráveis em versões anteriores à 376.49_5.
Roteadores que usam revisões de firmware lançadas em ou após 12 de janeiro de 2015 não devem ser afetados. A tabela a seguir reúne relatos de roteadores/firmwares não afetados.
| Roteador | Versão do Firmware | Verificado Por |
|---|---|---|
| RT-AC66R | 3.0.0.4.376_3754-g5ef7c1f | @asgh |
| RT-N12HP_B1 | 3.0.0.4.376_3754-g5ef7c1f | @vittee |
Considere o seguinte trecho do projeto ASUSWRT-Merlin, que é um fork aprimorado do código da ASUS. Você pode visualizar o arquivo por completo (recomendado para diversão extra) aqui.
177 char *processPacket(int sockfd, char *pdubuf)
178 {
...
202 phdr = (IBOX_COMM_PKT_HDR *)pdubuf;
...
207 if (phdr->ServiceID==NET_SERVICE_ID_IBOX_INFO &&
208 phdr->PacketType==NET_PACKET_TYPE_CMD)
209 {
...
A função processPacket é chamada após o recebimento de um pacote de INFO_PDU_LENGTH (512) bytes. O caminho de código especificamente vulnerável é main->processReq->processPacket. O serviço então converte o pacote para uma estrutura e verifica se os campos ServiceID e PacketType correspondem aos valores esperados.
O bloco a seguir contém o que se acredita ser a causa raiz desta vulnerabilidade.
222 if (phdr->OpCode!=NET_CMD_ID_GETINFO && phdr->OpCode!=NET_CMD_ID_GETINFO_MANU)
223 {
224 phdr_ex = (IBOX_COMM_PKT_HDR_EX *)pdubuf;
225
226 // Check Mac Address
227 if (memcpy(phdr_ex->MacAddress, mac, 6)==0)
228 {
229 _dprintf("Mac Error %2x%2x%2x%2x%2x%2x\n",
230 (unsigned char)phdr_ex->MacAddress[0],
231 (unsigned char)phdr_ex->MacAddress[1],
232 (unsigned char)phdr_ex->MacAddress[2],
233 (unsigned char)phdr_ex->MacAddress[3],
234 (unsigned char)phdr_ex->MacAddress[4],
235 (unsigned char)phdr_ex->MacAddress[5]
236 );
237 return NULL;
238 }
239
240 // Check Password
241 //if (strcmp(phdr_ex->Password, "admin")!=0)
242 //{
243 // phdr_res->OpCode = phdr->OpCode | NET_RES_ERR_PASSWORD;
244 // _dprintf("Password Error %s\n", phdr_ex->Password);
245 // return NULL;
246 //}
247 phdr_res->Info = phdr_ex->Info;
248 memcpy(phdr_res->MacAddress, phdr_ex->MacAddress, 6);
249 }
O bloco começa excluindo alguns valores de OpCode, que presumivelmente não exigem autenticação por design. Em seguida, ele chama memcpy e, suspeitamente, verifica o valor de retorno contra zero. Isso é um forte indício de que o autor pretendia usar memcmp no lugar. Dito isso, mesmo que essa verificação fosse implementada corretamente, saber o endereço MAC do dispositivo dificilmente seria autenticação suficiente.
O bloco a seguir está comentado, mas mostra que o autor, em algum momento, experimentou verificar uma senha. Contudo, nesse caso, a senha foi codificada diretamente no código como "admin".
Prosseguindo, o seguinte comando switch despacha o processamento com base no OpCode fornecido.
251 switch(phdr->OpCode)
252 {
...
428 case NET_CMD_ID_MANU_CMD:
429 {
430 #define MAXSYSCMD 256
431 char cmdstr[MAXSYSCMD];
432 PKT_SYSCMD *syscmd;
...
440 syscmd = (PKT_SYSCMD *)(pdubuf+sizeof(IBOX_COMM_PKT_HDR_EX));
...
443 if (syscmd->len>=MAXSYSCMD) syscmd->len=MAXSYSCMD;
444 syscmd->cmd[syscmd->len]=0;
445 syscmd->len=strlen(syscmd->cmd);
446 fprintf(stderr,"system cmd: %d %s\n", syscmd->len, syscmd->cmd);
447 #if 0
...
512 #endif
513 {
514 sprintf(cmdstr, "%s > /tmp/syscmd.out", syscmd->cmd);
515 system(cmdstr);
Se um atacante especificar o valor de OpCode de NET_CMD_ID_MANU_CMD, o bloco anterior processa o pacote convertendo-o para uma estrutura PKT_SYSCMD. Dessa forma, todos os membros de syscmd são totalmente controlados pelo atacante. Antes de tomar o cuidado (piscadela) de terminar a string de comando com NUL, o autor executa o comando na linha 514. Após executar o comando, a saída é lida do arquivo temporário e enviada de volta ao endereço de origem do pacote inicial.
Usuários finais: Atualize o firmware para a revisão 3.0.0.4.376.3754 ou mais recente. É importante observar que a funcionalidade "Check for Update" do roteador pode não funcionar corretamente. Verifique manualmente a versão do firmware que você está executando e, se for mais antiga, baixe/instale o novo firmware.
ASUS/Merlin: Remova a funcionalidade de execução remota de comandos deste serviço. Mesmo que fosse protegida com autenticação forte, transmitir uma senha para toda a rede local não é algo desejável. Se a execução de comandos for realmente necessária, ela deve ser fornecida via SSH ou mecanismo seguro similar.