Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
accfly — Divulgation des vulnérabilités des caméras Accfly : CVE-2020-25782, CVE-2020-25783, CVE-2020-25784, CVE-2020-25785. | Kitploit
Outils/GitHubGitHub/tezeb/accfly
Sécurité des Systèmes EmbarquésSécurité IoTAnalyse des VulnérabilitésExploitationRétro-ingénierieFuzzingTests d'IntrusionSécurité Matériel et IoTExploitation de Binaires
GitHubtezeb/accfly

accfly

Divulgation des vulnérabilités des caméras Accfly : CVE-2020-25782, CVE-2020-25783, CVE-2020-25784, CVE-2020-25785.

3il y a 5 ansPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager
Voir le dépôt

Dans quelle mesure votre caméra de "sécurité" est-elle sécurisée ?

Synthèse

Au début de 2020, sur mon ancien lieu de travail, j'ai eu l'occasion de participer à un événement interne de type pwn2own. Plusieurs cibles étaient disponibles, mais celle qui m'intéressait le plus était la caméra de sécurité sans fil Accfly. Malheureusement, je n'ai pas pu terminer mes recherches pour l'événement lui-même, mais comme personne d'autre n'avait tenté de s'attaquer à cet appareil, j'ai poursuivi mes travaux.

L'objectif principal de la recherche était les vulnérabilités pouvant mener à une exécution de code à distance (RCE). Ce type de vulnérabilité permet à un attaquant de prendre le contrôle total de l'appareil et, dans le cas d'une caméra vidéo, peut entraîner une compromission totale de la vie privée du propriétaire. Malheureusement, le firmware de l'appareil s'est avéré truffé de tels problèmes.

Premièrement, l'appareil ne fournit aucune authentification. Par conséquent, un attaquant capable de s'y connecter peut y accéder librement et le reconfigurer. Dans sa forme la plus simple, il est possible de redémarrer l'appareil en continu, le rendant totalement inutilisable pour l'utilisateur légitime. La portée de cette attaque est quelque peu limitée, car l'appareil est conçu pour être utilisé au sein d'un réseau WiFi, généralement derrière un NAT, donc pas directement accessible depuis Internet. Cependant, l'absence de chiffrement entre l'appareil et l'application smartphone de son propriétaire, ainsi que l'utilisation du serveur du fournisseur comme proxy pour la communication, crée une opportunité pour des attaques MitM ou de manipulation DNS, qui peuvent franchir la restriction NAT du WiFi.

De plus, l'application utilise un protocole binaire propriétaire pour la communication. Il a été implémenté dans un mélange de C et de C++ et s'est avéré plein de fonctions de gestion de chaînes non sécurisées. L'exécutable principal contient une énorme quantité de code inutilisé, ce qui suggère qu'il est réutilisé sur d'autres appareils. Cela rend la maintenance plus difficile et augmente la surface d'attaque. L'application n'active aucun mécanisme de sécurité moderne qui la protégerait contre de nombreuses techniques d'exploitation courantes. De plus, elle ne limite même pas les permissions utilisateur, tournant en root - avec les privilèges les plus élevés disponibles.

À la suite de ces recherches, les quatre vulnérabilités suivantes ont été documentées.

  • CVE-2020-25782 - débordement de tampon basé sur la pile sans authentification dans la fonction CNetClientManage::ServerIP_Proto_Set lors du traitement des messages entrants
  • CVE-2020-25783 - débordement de tampon basé sur le tas sans authentification dans la fonction CNetClientTalk::OprMsg lors du traitement des messages entrants
  • CVE-2020-25784 - débordement de tampon basé sur la pile sans authentification dans la fonction CNetClientGuard::SubOprMsg lors du traitement des messages entrants
  • CVE-2020-25785 - débordement de tampon basé sur la pile sans authentification dans la fonction CFtpProtocol::FtpLogin pendant la procédure de mise à jour

Pour trois d'entre elles, des exploits RCE ont été développés, permettant à un attaquant d'obtenir le contrôle total de l'appareil. Cependant, en raison de l'absence de réponse du fournisseur aux tentatives de signalement des vulnérabilités, ce dépôt ne contient que des exploits PoC limités, qui ne font que faire planter l'application.

Les problèmes ont été découverts dans la version logicielle V3.10.73 et vérifiés dans la version logicielle V4.15.77, la dernière disponible au moment de cette publication (26 janvier 2021).

Si vous avez des questions, n'hésitez pas à me contacter par e-mail (voir le commit git) ou via les issues Github. Si vous possédez un appareil IoT qui, selon vous, pourrait être intéressant à pirater, si vous recherchez un chercheur en sécurité ou si vous voulez simplement dire bonjour, je serai ravi de vous lire. Vous pouvez également m'offrir un café !

Introduction

L'appareil cible est une caméra vidéo contrôlée à partir de l'application mobile associée. Mon analyse a commencé par le trafic réseau de la caméra et s'est poursuivie dans le firmware de la caméra. Un protocole binaire propriétaire est utilisé pour toutes les communications. Les commandes sont soit envoyées directement à l'appareil mobile lorsqu'il est sur le même réseau, soit transmises via le serveur du fabricant de l'appareil. La caméra elle-même écoute sur plusieurs ports TCP (23456,34567) et UDP (34568, 34569). Il n'y a ni chiffrement ni authentification pour le trafic réseau, ce qui permet des attaques MitM ou un accès direct lorsque la caméra est exposée sur le réseau. Il semble probable qu'un accès au flux vidéo soit également possible sans authentification, mais je n'ai pas fait assez de rétro-ingénierie sur le protocole propriétaire pour tenter l'expérience.

Après un bref aperçu de la communication, l'étape suivante consistait à essayer d'accéder au firmware de l'appareil. Ma première tentative a été de le télécharger directement en détournant le processus de mise à jour de l'appareil, mais rien de tel n'est apparu dans le trafic réseau. Je serais resté bloqué à cette étape sans l'aide très précieuse d'un collègue qui a extrait le firmware de la mémoire flash, ce qui m'a permis de poursuivre ces recherches.

Le firmware exécute Linux sur un CPU MIPS little-endian. Il y a exactement un processus intéressant, appelé Alloca, responsable de la capture vidéo et qui gère également toutes les communications réseau. L'application est créée en C++ et contient beaucoup de code inutilisé sur cet appareil. Cela indique que le même logiciel est également utilisé sur différents appareils.

La fuite

Même si ce problème a été découvert en dernier, il est crucial pour l'exploitation effective de la plupart des autres, car ils découlent de l'utilisation de fonctions de chaînes C non sécurisées. Bien qu'il existe plusieurs techniques pouvant être utilisées pour une exécution de code réussie dans des scénarios similaires, l'application est créée de telle manière qu'elles sont pour la plupart inutiles. Le principal problème est que le code et les données d'Alloca sont alloués statiquement à des adresses basses ( <&nbsp;0x01000000). Ainsi, les tentatives de réutilisation de code existant (c'est-à-dire ROP et autres) ne sont pas utiles, car elles nécessitent la possibilité d'écrire des adresses dans la mémoire du programme. Parce que les chaînes C utilisent \x00 comme caractère de terminaison et que les fonctions de chaînes terminent le traitement au premier octet de ce type, il n'est pas possible d'utiliser plus d'un seul octet NULL. De plus, l'emplacement de la pile est aléatoire et l'application est fortement multi-threadée, ce qui rend les autres techniques beaucoup moins fiables.

Cette vulnérabilité résulte du partage de données entre plusieurs threads et de l'utilisation non sécurisée de strcpy. Bien que j'aie analysé ce problème particulier pendant longtemps, je n'ai repéré l'opportunité de l'utiliser comme vecteur de fuite de données que quelques semaines avant cette publication. Fait intéressant, grâce à la fuite de l'adresse du tas d'un objet C++, cette vulnérabilité permet également une exécution de code à distance. Cependant, cette attaque n'est pas incluse dans ce rapport.

L'application Alloca peut se mettre à jour via FTP. Cette opération peut être demandée par un serveur, qui fournit également le nom d'utilisateur, le mot de passe et le nom de fichier nécessaires. La fonction qui initie la mise à jour est présentée ici : appels strcpy vulnérables

Trois appels à strcpy sont évidemment non sécurisés et conduisent à un débordement de tas, car l' objet ftpUpgrade est alloué dynamiquement. Malheureusement, l'ordre dans lequel les copies sont effectuées et la disposition de la structure ftpUpgrade rendent impossible de démarrer réellement un thread qui fuirait des données. En regardant de plus près, le paquet entrant révèle la structure suivante :

root@kitploit:~
struct ftp_upgrade_pkt {
	struct pktHeader;
	char username[16];
	char password[16];
	char filename[128];
}

tandis que l'objet ftpUpgrade ressemble à peu près à ceci :

root@kitploit:~
struct CNetClientFtpUpgrade {
	// ... something here
	char filename[128];
	char unknown[6];
	char username[16];
	char password[16];
	CFtpDownlad *;
	CNetClientConnect*;
	int something[5];
	bool threadRunning;
	// ... and more
}

La fuite peut se produire après que l'un des pointeurs internes (CFtpDownload*, CNetClientConnect*) a été rempli par l'application. De plus, le nom d'utilisateur et le mot de passe sont copiés (une fois de plus, mais de manière sécurisée cette fois) vers l' objet nouvellement créé avant que son pointeur ne soit stocké dans l'emplacement fuyable, de sorte que la fuite ne peut concerner que filename. Par conséquent, le nom de fichier doit être très long, mais en raison de l'ordre et du comportement de terminaison de strcpy, un nom de fichier suffisamment long entraînera un nom d'utilisateur et un mot de passe encore plus longs, qui finiront par écraser threadRunning et ne démarreront aucun thread.

Si ce code était mono-threadé, on ne pourrait pas faire grand-chose. Mais comme le nouveau thread FtpDownload est créé et exécute la fonction DownloadFile, il présente une opportunité intéressante car il partage l'objet CNetClientFtpUpgrade avec le thread qui traite les paquets entrants. Non seulement il possède plusieurs opérations d'E/S contrôlables de l'extérieur (requêtes DNS, traitement de la connexion FTP), mais il essaie également de se connecter au FTP jusqu'à 10 fois (ceci est fait dans l'appelant de DownloadFile). Cela permet de contrôler l'exécution du thread FtpDownload (en le bloquant sur des opérations d'E/S), donnant ainsi le temps au thread de traitement des messages de traiter d'autres requêtes.

Fonction DownloadFile permettant de faire fuiter l'adresse du tas

En bref, rien qu'en envoyant plusieurs requêtes de mise à jour, il est possible de modifier le filename (et d'autres paramètres) utilisé par le thread FtpDownload déjà en cours et de recevoir l'adresse du tas divulguée. En prime, la fonction FtpSize (marquée en vert) utilise le tampon situé à l'intérieur de l'objet référencé par l'adresse divulguée pour stocker le filename lui-même, ce qui permet une injection triviale du premier étage de shellcode. La seule limitation ici est la longueur et l'absence d'octets NULL, en raison de l'utilisation de strcpy. Un PoC d'exemple est fourni, qui ne fait que divulguer une adresse du tas de l'appareil.

CVE-2020-25782

débordement de tampon basé sur la pile sans authentification dans la fonction CNetClientManage::ServerIP_Proto_Set

L'absence totale d'authentification dans le traitement du trafic entrant m'a poussé à rechercher les gestionnaires de paquets. L'une des fonctions intéressantes est ServerIP_Proto_Set. Elle semble être utilisée pour créer une réécriture statique de la résolution DNS. Je n'ai pas trouvé de moyen de rediriger le trafic de cette façon, mais il y a un autre débordement de tampon ici (marqué en orange).

ServerIP_Proto_Set

Les données, directement lues depuis le paquet, sont utilisées dans la fonction sprintf. Dans ce cas, on suppose que les données du paquet tiendront dans un tampon de 16 octets, mais l'utilisation du format simple %s permet d'écrire autant d'octets que l'on souhaite, à condition qu'ils ne contiennent pas de NULL.

Cette vulnérabilité est plutôt limitée. Bien qu'il soit possible d'écrire beaucoup de données sur la pile, de sorte qu'un NOP-sledge pourrait fonctionner, il n'est pas possible d'écrire des octets NULL. Même tenter d'écrire un seul octet NULL échouera, car le format de la fonction sprintf le fait précéder d'un \n. Un autre obstacle est un objet CMutex stocké après le tampon. Toute tentative de débordement doit remplir ce mutex avec une valeur correcte (ou au moins une qui satisfera le destructeur de CGuard

  • marqué en rouge). C'est problématique, car le destructeur déréférence la variable passée deux fois, puis utilise sa valeur dans l'appel à pthread_mutex_unlock. Après quelques tests, j'ai découvert qu'un tampon rempli de NULL suffit pour revenir correctement de pthread_mutex_unlock, mais il devait encore être déréférencé vers une adresse mémoire valide.

La fuite vient à la rescousse. L'attaque est un peu complexe, car nous avons besoin d'une adresse du tas qui ne contienne aucun octet NULL. Heureusement, la recherche est facilitée, car l'appareil nous offre la possibilité d'effectuer un redémarrage à distance sans authentification. Chaque fois, une allocation d'espace d'adressage du tas différente est fournie. Il est donc possible de simplement réinitialiser l'appareil et de divulguer une adresse jusqu'à ce qu'une adresse appropriée soit trouvée. Pratiquement, cela permet également de stocker un court premier étage du shellcode. Comme nous devons contourner un problème de mutex (un pointeur vers un pointeur est nécessaire), nous divulguons une autre adresse, en passant cette fois une adresse préalablement divulguée comme nom de fichier. Le schéma suivant montre la disposition mémoire attendue :

disposition de la mémoire divulguée

Si tout se passe comme prévu, il est possible de passer une 2e adresse comme mutex et la première comme adresse de retour. Cependant, cela n'est pas nécessaire pour simplement faire planter une application comme le fait le PoC.

CVE-2020-25783

débordement de tampon basé sur le tas sans authentification dans la fonction CNetClientTalk::OprMsg

L'appareil est censé permettre une communication vocale bidirectionnelle. Un autre gestionnaire de paquets entrants semble être responsable de la réception et de la lecture de l'audio. Le paquet réseau audio_pkt_hdr est décrit par la structure suivante :

root@kitploit:~
struct audio_pkt_hdr {
	struct pktHeader field_0x0;
	int field_0x14
	int field_0x18
	int field_0x1c
	char audioBuff[0x140];
}

L'un des champs de la structure pktHeader est la longueur du paquet (telle qu'elle est transférée sur le réseau). Ce champ peut être librement défini par l'expéditeur. La partie vulnérable consiste à copier des données directement depuis le paquet entrant en utilisant une valeur de longueur non fiable fournie dans l'en-tête du paquet entrant.

traitement du paquet audio

Comme on peut le voir, l'objet CNetClientTalk est créé avec le constructeur suivant :

constructeur de CNetClientTalk

L'appel ci-dessus à memcpy entraîne donc un débordement de tampon sur le tas. Malheureusement, l'exploitation réelle de ce problème est plutôt difficile. Même s'il est possible d'écraser le tas à plusieurs reprises, je n'ai pas trouvé de moyen de contrôler les données qui seront stockées sur le tas après le tampon débordant. Comme l'application compte plus de 50 threads actifs, dont certains sont responsables du traitement de l'audio et de la vidéo, elle alloue et désalloue constamment de la mémoire. Cela entraîne une modification constante des données du tas, ce qui rend difficile la prédiction de ce qui est stocké après le tampon et son écrasement correct.

CVE-2020-25784

débordement de tampon basé sur la pile sans authentification dans la fonction CNetClientGuard::SubOprMsg

Voici un autre gestionnaire de paquets entrants. Cette fois, le paquet réseau a la structure suivante (l'en-tête de paquet commun est omis) :

root@kitploit:~
struct pkt_hdr_sub_cliGuard {                            
  dword deviceId;                                 
  dword userId;                                  
  dword magic;                                  
  dword subCmd;                                  
  dword field_0x10;                                
  dword field_0x14;                                
  dword field_0x18;                                
  dword field_0x1c;                                
  dword guard_icommand;                              
  dword moreThenRandomStackValue;                         
  dword itemCnt;                                 
  char array_of_0x18[24];                             
};              

Encore une fois, la partie intéressante est le dernier tableau (car nous pouvons agrandir ce paquet autant que nous le souhaitons), qui contient une structure interne de taille 24. La vulnérabilité découle de l'hypothèse que le itemCnt reçu ne dépassera pas 6, car le tampon de destination de la copie a une taille de 144 (=24*6), ce qui est visible sur la liste suivante (surbrillance orange) :

vulnérabilité de la fonction Guard OprMsg

Cette fois, la copie est effectuée à l'aide de memcpy (surbrillance verte), il n'y a donc aucune limite sur les caractères autorisés. La copie se fait par morceaux, dans une boucle while (marquée en bleu). Il convient de noter que le compteur cnt_v0 diminue dans une boucle, de sorte que les morceaux sont copiés en ordre inverse. En incluant les variables qui suivent le tampon vulnérable buf, le débordement doit avoir 256 octets, puis 4 registres ($s0-$s3) et $ra. Parce que nous n'avons aucune connaissance de la disposition mémoire, le code PoC utilise une technique ROP. Un seul gadget est utilisé, qui joue l'un des sons intégrés de l'appareil (et plante).

CVE-2020-25785

débordement de tampon basé sur la pile sans authentification dans la fonction CFtpProtocol::FtpLogin

L'une des premières directions de mon analyse était de rechercher la procédure de mise à jour. Comme je l'ai découvert, l'appareil dispose d'une fonctionnalité de mise à jour FTP, qui peut être initiée en envoyant une demande de mise à jour et aboutit au téléchargement du firmware depuis le site FTP externe. Comme pour les autres vulnérabilités, il n'est pas nécessaire de s'authentifier avant de demander la mise à jour de l'appareil. L'analyse approfondie de la fonctionnalité FTP a révélé un débordement de tampon basé sur la pile dans la fonction CFtpProtocol::FtpLogin. Comme on peut le voir dans la liste décompilée ci-dessous, la fonction passe un tableau char de taille 256 à la fonction FtpPwd.

vulnérabilité cachée dans la fonction FtpLogin

FtpPwd est utilisée pour obtenir le répertoire de travail courant du serveur FTP. Elle charge son tampon interne avec jusqu'à 1500 octets de réponse, puis les copie dans le tampon fourni. Cette séquence d'appels entraîne un débordement de 1242 octets. Dans ce cas, les caractères autorisés sont très limités, car l'utilisation de " (double-guillemet) raccourcirait la chaîne d'entrée (strchr est utilisé pour rechercher un char dans une chaîne C) et ne ferait pas déborder le tampon. Heureusement, il est seulement nécessaire de fournir une adresse unique vers laquelle l'exécution du code sera redirigée.

fonction FtpPwd vulnérable

Pour exploiter cette vulnérabilité, il faut soit contrôler le DNS, soit rediriger (ou faire un MitM) la connexion vers le serveur FTP. L'application ne dispose d'aucune protection moderne, il est donc possible d'exécuter le code directement depuis la pile. Sans fuite d'adresse, le mieux que l'on puisse faire est soit de deviner l'emplacement de la pile, soit de rediriger l'exécution vers une seule fonction, qui fera ensuite planter l'application. Mes premières tentatives consistaient exactement à cela, jouer l'un des sons intégrés, ce qui est fourni comme PoC. En utilisant la fuite, il est possible d'obtenir le contrôle total de l'appareil.

Chronologie

  • Avril 2020 - Les vulnérabilités ont été découvertes
  • Juin 2020 - Première tentative infructueuse de contacter le fournisseur (Accfly)
  • Juillet 2020 - Seconde tentative infructueuse de contacter le fournisseur (Accfly)
  • Septembre 2020 - Demande d'attribution d'un CVE
  • Janvier 2021 - Divulgation complète des vulnérabilités

Remerciements

  • Michał 'Michoo' Madziar pour sa magie en soudure et pour avoir extrait le firmware
  • _0kami pour ses scripts et astuces ghidra très utiles
  • tzdybal pour la relecture du brouillon de ce document
Télécharger l’outil