
Routeur ASUS — Exécution de commandes root par infosvr UDP Broadcast
Plusieurs modèles de routeurs d'ASUS incluent un service appelé infosvr qui écoute sur le port de diffusion UDP 9999 sur l'interface LAN ou WLAN. Il est utilisé par l'un des outils d'ASUS pour faciliter la configuration du routeur en localisant automatiquement les routeurs sur le sous-réseau local. Ce service s'exécute avec les privilèges root et contient une vulnérabilité d'exécution de commande sans authentification. Le code source de ce service, ainsi que celui du reste du routeur, est disponible sur le site d'assistance d'ASUS.
Le CVE attribué à ce problème est CVE-2014-9583 (hélas, pas CVE-2014-10000 finalement :-/).
Actuellement, toutes les versions de firmware connues pour les routeurs concernés (RT-AC66U, RT-N66U, etc.) sont supposées vulnérables. Les tests ont été effectués contre la version 3.0.0.4.376.2524-g0013f52.
Les routeurs/versions de firmware suivants sont confirmés vulnérables :
| Routeur | Version du firmware | Vérifié par |
|---|---|---|
| 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 |
De plus, les routeurs exécutant un firmware basé sur asuswrt-merlin, soutenu par la communauté, sont vulnérables avant la version 376.49_5.
Les routeurs utilisant des révisions de firmware publiées le 12 janvier 2015 ou après ne devraient pas être affectés. Le tableau suivant recense les signalements de routeurs/firmwares non affectés.
| Routeur | Version du firmware | Vérifié par |
|---|---|---|
| RT-AC66R | 3.0.0.4.376_3754-g5ef7c1f | @asgh |
| RT-N12HP_B1 | 3.0.0.4.376_3754-g5ef7c1f | @vittee |
Considérez l'extrait suivant du projet ASUSWRT-Merlin, qui est un fork amélioré du code d'ASUS. Vous pouvez consulter le fichier dans son intégralité (recommandé pour des fous rires supplémentaires) ici.
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 {
...
La fonction processPacket est appelée après réception d'un paquet de INFO_PDU_LENGTH (512) octets. Le chemin de code vulnérable spécifique est main->processReq->processPacket. Le service convertit ensuite le paquet en une structure et vérifie que les champs ServiceID et PacketType correspondent aux valeurs attendues.
Le bloc suivant contient ce qui est considéré comme la cause racine de cette vulnérabilité.
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 }
Le bloc commence par exclure quelques valeurs de OpCode, qui ne nécessitent probablement pas d'authentification par conception. Ensuite, il appelle memcpy et vérifie de manière suspecte la valeur de retour par rapport à zéro. Cela indique fortement que l'auteur avait l'intention d'utiliser memcmp à la place. Cela dit, même si cette vérification était implémentée correctement, connaître l'adresse MAC de l'appareil ne constitue guère une authentification suffisante.
Le bloc suivant est commenté, mais montre que l'auteur a, à un moment donné, expérimenté la vérification d'un mot de passe. Bien que, dans ce cas, le mot de passe était codé en dur comme « admin ».
Ensuite, l'instruction switch suivante répartit le traitement en fonction de la valeur OpCode fournie.
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);
Si un attaquant spécifie la valeur de OpCode NET_CMD_ID_MANU_CMD, le bloc précédent traite le paquet en le convertissant en une structure PKT_SYSCMD. Ainsi, tous les membres de syscmd sont entièrement contrôlés par l'attaquant. Avant de prendre soin (clin d'œil) de terminer la chaîne de commande par un NUL, l'auteur exécute la commande à la ligne 514. Après l'exécution de la commande, la sortie est lue depuis le fichier temporaire et renvoyée à l'adresse source du paquet initiateur.
Utilisateurs finaux : Mettez à jour le firmware vers la révision 3.0.0.4.376.3754 ou plus récente. Il est important de noter que la fonctionnalité « Rechercher une mise à jour » du routeur peut ne pas fonctionner correctement. Vérifiez manuellement la version du firmware que vous exécutez et, si elle est plus ancienne, téléchargez/installez le nouveau firmware.
ASUS/Merlin : Supprimez la fonctionnalité d'exécution de commande à distance de ce service. Même si elle était protégée par une authentification forte, diffuser un mot de passe sur l'ensemble du réseau local n'est pas vraiment souhaitable. Si l'exécution de commandes est véritablement souhaitée, elle devrait être fournie via SSH ou un mécanisme sécurisé similaire.
David Longenecker recommande d'utiliser un script (JFFS) en combinaison avec le paramètre nvram script_usbmount pour tuer le processus infosvr au démarrage. Pour plus d'informations, consultez son article de blog.
Eric Sauvageau (@RMerl) recommande de bloquer le port 9999 par pare-feu. Pour plus d'informations, consultez son message sur le forum Small Net Builder.
Alternativement, désactivez le service infosvr en tuant le processus après chaque démarrage. Pour plus de plaisir/d'ironie, utilisez l'exploit pour ce faire :
$ ./asus-cmd "killall -9 infosvr"
[...]
REMARQUE : vous n'obtiendrez pas de réponse à cette commande. Encore une fois, cela devra être fait à chaque redémarrage de l'appareil.
Après la divulgation initiale de ce problème, plusieurs parties ont traité le problème dans leurs bases de code.
2015/01/08 - Eric Sauvageau a corrigé ce problème dans la base de code asuswrt-merlin. La première version intégrant le correctif est la 376.49_5. Ses modifications peuvent être consultées ici, ici et ici. 2015/01/12 - ASUS a publié de nouvelles révisions de firmware pour les appareils concernés (3.0.0.4.376.3754) qui ne seraient pas vulnérables.
ASUS a résolu le problème en s'assurant que la variable nvram ateCommand_flag est définie sur 1 avant d'exécuter la commande fournie. Cette variable n'est pas définie dans les builds classiques.
loc_404958:
la $v0, 0x400000
addiu $a0, $v0, (aAtecommand_fla - 0x400000) # "ateCommand_flag"
la $v0, 0x400000
addiu $a1, $v0, (g_ascONE - 0x400000) # "1"
la $v0, 0x400000
addiu $t9, $v0, (check_nvram - 0x400000)
jalr $t9 ; check_nvram
nop
lw $gp, 0x290+var_270($fp)
bnez $v0, lbl_execute_command
nop
sw $zero, 0x290+var_14($fp)
b lbl_return_zero
Le dépôt dans lequel se trouve cet avis contient un exploit fonctionnel pour ce problème.
$ ./asus-cmd "nvram show | grep -E '(firmver|buildno|extendno)'"
[*] sent command: nvram show | grep -E '(firmver|buildno|extendno)'
[!] received 512 bytes from 10.0.0.2:37625
0c 15 0033 54ab7bc4 41:41:41:41:41:41
0031 nvram show | grep -E '(firmver|buildno|extendno)'
[!] received 512 bytes from 10.0.0.1:9999
0c 16 0033 54ab7bc4 xx:xx:xx:xx:xx:xx
004e buildno=376
extendno_org=2524-g0013f52
extendno=2524-g0013f52
firmver=3.0.0.4
« ASUSWRT 3.0.0.4.376_1071 - Exécution de commande backdoor LAN »
(cela a déclenché ma publication. son exploit est également copié dans le répertoire others/)
http://www.exploit-db.com/exploits/35688/
« SÉCURITÉ : faille de sécurité côté LAN - atténuation »
http://forums.smallnetbuilder.com/showthread.php?t=21774
« Vous avez un routeur Asus ? Quelqu'un sur votre réseau peut probablement le pirater »
http://arstechnica.com/security/2015/01/got-an-asus-router-someone-on-your-network-can-probably-hack-it/
« Un bug d'ASUS permet à des personnes de votre réseau local de prendre le contrôle de votre routeur sans fil »
http://dnlongen.blogspot.com/2015/01/asus-bug-lets-those-on-your-local.html
« Un exploit permet de pirater les routeurs Asus depuis le réseau local »
http://www.itworld.com/article/2867255/exploit-allows-asus-routers-to-be-hacked-from-local-network.html
« Les routeurs sans fil Asus peuvent être exploités par n'importe qui à l'intérieur du réseau »
http://it.slashdot.org/story/15/01/09/1349229/asus-wireless-routers-can-be-exploited-by-anyone-inside-the-network
« La plupart des routeurs Asus affectés par un bug de détournement ; exploit publié » http://www.zdnet.com/article/asus-routers-vulnerable-to-network-attack-exploit-published/
« Une faille d'exécution de commande root hante les routeurs ASUS » http://threatpost.com/root-command-execution-flaw-haunts-asus-routers/110276