Dernières nouvelles

Restez au courant de tout ce qui se passe à Approach

Blog article

Kekw continue d’évoluer

Date de publication

31.05.2023

image
Découvrez comment un logiciel malveillant furtif a exploité GitHub et PyPi, en évoluant constamment pour contourner la détection. Vos systèmes sont-ils en danger ?

Introduction

Kekw continue d’évoluer – Le mardi 24/04, un collègue de notre équipe rouge a remarqué un post sur security.stackexchange.com. Le post a été fait le 15/04 et l’utilisateur souhaite que quelqu’un regarde le code du dépôt GitHub lié au post pour vérifier s’il y a quelque chose d’étrange avec le code. L’utilisateur signale que le programme fonctionne comme prévu, mais qu’il a commencé à recevoir des alertes pour des tentatives de connexion à plusieurs comptes.

Plusieurs jours après que mon collègue m’en a fait part, le message a été supprimé et n’est plus accessible.

Première analyse

En examinant le compte GitHub ApfelsaftDevs (qui n’est plus disponible), nous pouvons voir que le compte a été créé le 14 juin 2022.

Le compte reste inactif sans dépôt et commence à devenir actif fin février/début mars. En avril en particulier, nous avons constaté une activité presque quotidienne jusqu’à ce que le compte soit supprimé. Même pendant les week-ends.

Le compte contenait de nombreux dépôts différents avec des outils qui peuvent être utilisés pour toutes sortes de cas d’utilisation, certains plus légitimes que d’autres.

Analyse des noms et des descriptions

Sur la base du nom et de la description, nous pouvons voir que certains outils ont un cas d’utilisation quelque peu légitime. Par exemple, un outil pour Discord qui peut être utilisé pour envoyer des messages directs à plusieurs comptes à la fois. Mais nous pouvons également voir d’autres dépôts qui ont clairement des intentions malveillantes.

Trojanisé

Ce que tous ces outils ont en commun, c’est qu’ils sont trojanisés par le logiciel malveillant Kekw. Ce logiciel malveillant est chargé via des paquets Python malveillants lors de l’exécution de l’outil. Ce sont ces paquets Python malveillants qui ont été supprimés, la plupart du temps dans les 24 à 48 heures, obligeant l’acteur de la menace à mettre à jour tous les dépôts presque quotidiennement.

En regardant l’un des commits de ces dépôts, nous pouvons voir que 2 lignes sont modifiées au tout début du script Python main.py. La ligne 2 télécharge le paquet malveillant, et la ligne 3 importe le paquet.

Le blog de Cyble Research and Intelligence Labs (CRIL) fait un excellent travail d’analyse du paquet Python malveillant. Le blog de Cyble mentionne l’utilisation de variables Anti-VM. Après une analyse rapide, les valeurs de ces variables semblent provenir d’un dépôt « virustotal-vm-blacklist » sur GitHub. J’ai pu rapidement identifier deux dépôts avec cette information.

Le premier dépôt provient de Zed1242 et semble être le dépôt original sur lequel l’autre est basé.

Le dépôt de 6nz contient beaucoup plus d’informations et est plus fréquemment mis à jour. Il a 1969 commits d’avance, mais seulement 3 commits de retard sur le premier dépôt au moment de l’écriture, ce qui montre qu’il est plus à jour.

Automatisation

Dans la description du commit, nous pouvons également voir des signes d’automatisation. Je n’ai pas cherché à savoir comment fonctionne cette automatisation et cela sort du cadre de ce blog.

Comme indiqué au début du blog, les paquets PyPi malveillants semblent être diffusés et téléchargés par l’intermédiaire de ces outils. C’est un point que le blog de Cyble, les tweets de l’entreprise de sécurité ESET et divers articles de presse(1, 2, 3, 4) ne mentionnent pas.

Après avoir contacté le chercheur d’ESET et mentionné les dépôts GitHub utilisés pour diffuser les paquets, tous les dépôts sauf un ont été mis hors ligne peu de temps après par GitHub. Un compte GitHub est resté en ligne (PatrickPogoda), ce qui m’a permis de continuer à suivre cette menace. Ce compte avait les mêmes dépôts que « ApfelsaftDev » et a continué à faire des mises à jour presque quotidiennes jusqu’à ce qu’il soit mis hors ligne à la mi-mai.

Le premier d’une longue série

La toute première version que j’ai analysée était un script Python ne comportant pratiquement aucun obscurcissement et plus de 1700 lignes de code. Il s’agit très probablement de la même version que celle analysée par Cyble.

Nom du paquet PyPi : pyfontingtools

Version : 1.0.0

Un script simple comme celui-ci est détecté assez facilement par la plupart des sociétés AV connues.

Qu’en est-il du deuxième scénario ?

Oui, il s’agit bien d’une référence au Seigneur des Anneaux et non d’une faute de frappe. Non seulement les hobbits ont des secondes, mais ils ont aussi des acteurs de menace.

Dans le script, seule une ligne de code est obscurcie par l’utilisation du cryptage Fernet. Comme ce code n’est pas analysé dans le blog de Cyble, examinons-le nous-mêmes.

Une fois décrypté, nous obtenons un autre script Python avec une seule fonction appelée « inject ». Le script est assez simple, sans obscurcissement.

Comment cela fonctionne-t-il ?

Le script importe et télécharge les modules légitimes nécessaires.

Plusieurs variables sont définies et le script vérifie l’existence de %localappdata%/exodus (C:\Users\\AppData\local\exodus).

S’il n’existe pas, la fonction est renvoyée et le script s’arrête.

Si le dossier existe, le script continue et commence à lister tous les fichiers de ce dossier et les ajoute à la variable « apps ».

L’URL à partir de laquelle le fichier app.asar est téléchargé et l’en-tête de l’agent utilisateur à utiliser sont définis. Ces éléments sont ensuite utilisés pour télécharger le fichier.

Le fichier .asar est un format d’archive conçu pour les applications Electron.

L’agent utilisateur complet utilisé : « Mozilla/5.0 (Windows NT 10.0 ; Win64 ; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36 »

Un webhook Discord est défini ainsi que l’exodus.wallet et l’emplacement d’un fichier .zip qui sera créé par le script.

Prochaines étapes

Après avoir défini ces variables, le script passe en revue tous les fichiers et dossiers du dossier exodus.wallet et place toutes ces informations dans l’archive exoduswallet.zip définie ci-dessus.

Téléchargez le fichier zip sur gofile[.]io, stockez le lien de téléchargement dans la variable exolink et envoyez cette information au webhook Discord pour permettre à l’attaquant de télécharger le fichier zip.

Le processus exodus.exe est tué

La dernière étape de la fonction consiste à écrire le fichier app.asar pour chaque valeur de la liste des applications, définie à la ligne 16.

Dans la même boucle, la valeur de la variable khook est écrite dans chaque valeur de la liste des applications sous la forme d’un fichier appelé LICENSE.

Après avoir écrit la fonction, il faut encore l’exécuter. Cela se produit à la fin du script.

Le script obtient un score faible de 3/60 sur VirusTotal.

App.asar n’a que 2 occurrences sur VirusTotal.

Il semble que ce second script soit purement axé sur le vol de portefeuilles Exodus, alors que le script initial est un script de vol plus générique. ESET a pu le comparer à plusieurs voleurs de noms différents dans les tweets cités plus haut, grâce à sa base de données étendue.

Moins, c’est plus

Les défenseurs font évoluer leurs capacités, mais les attaquants aussi.

Le paquet Pypi pyfontingtools version 1.0.0 contenait le script malveillant complet. Ce script est facilement détecté comme indiqué précédemment (17 VT hits).

L’acteur de la menace a adapté et modifié le processus de téléchargement. Pour les nouveaux paquets, le téléchargement initial de PyPi 1.0.0 n’affichait qu’un simple « Hello World ».

Quelques minutes plus tard, l’acteur de la menace télécharge une nouvelle version, 1.1.0. Cette nouvelle version ne contient que 4 lignes de code.

Cette fois, j’analyse la version 1.1.0 du paquet PyPi « syssqlitedbpackageV1 »

L’auteur de la menace a de nouveau recours au cryptage Fernet pour dissimuler la charge utile réelle. L’ensemble de la commande de la ligne 4 contient 96211 caractères !

Après décryptage, on comprend pourquoi la commande Fernet était si longue. C’est exactement le même script que le premier (pyfontingtools).

Utilisons diff pour vérifier !

La sortie montre que deux lignes sont différentes. Il s’agit probablement d’un problème dû au copier-coller d’un script et au décryptage de l’autre. Aucun code réel n’est différent.

Changer le script avec la charge utile cryptée fait bien le travail en ce qui concerne la détection AV. 0 résultats sur VT.

C’est l’heure du morphing !

Un jour plus tard, une nouvelle version de syssqlitedbpackageV1 est téléchargée. J’ai remarqué cela très peu de temps après que l’auteur de la menace ait téléchargé une nouvelle version. Je jure que je ne suis pas l’auteur de la menace 🙂

Non seulement le code est modifié, mais l’auteur a également changé ! Lors de l’analyse des nombreux paquets PyPi utilisés par l’acteur de la menace, ces deux auteurs (Jozef M et NHJonas) ont toujours été utilisés. Le compte du responsable était presque toujours un compte nouvellement créé et différent pour chaque paquet malveillant.

Version 1.2.0 du paquet PyPi « syssqlitedbpackageV1 »
Jetons un coup d’œil au code de cette nouvelle version !

Cette fois, le script ne comporte que 49 lignes de code. Encore une fois, il comprend une très longue ligne de code crypté au Fernet.

Plusieurs modules sont importés et plusieurs autres sont téléchargés.

Obtenir l’utilisateur actuel.

Parcourez en boucle le dossier %localappdata%\Programmes\Python et recherchez les répertoires commençant par Python.

Pour chaque version de Python trouvée, copiez le dossier « Cryptodome » et copiez-le dans le dossier « Crypto » du même dossier parent.

Plusieurs lignes de code vierges sont suivies de la définition de la variable pl.

Le module subprocess est importé et la variable creationflags est définie pour créer un nouveau groupe de processus (pour permettre la gestion des processus enfants) et lance le processus invisible pour l’utilisateur (CREATE_NO_WINDOW). Ensuite, l’exécution désormais bien connue d’une commande cryptée Fernet est définie.

Définir l’emplacement de %appdata% et y ajouter pl.py Aux lignes 29 et 30, la variable pl est utilisée pour écrire dans le fichier %appdata%\pl.py défini ci-dessus.

Drapeaux

La variable Creationflags est à nouveau définie avec des valeurs légèrement différentes. Cette fois, elle doit être utilisée en dehors de la variable pl. L’indicateur « DETACHED_PROCESS » créera un nouveau processus distinct du processus parent. Il s’agit probablement d’un moyen d’échapper à la détection et de rendre plus difficile l’enquête en cas d’incident.

Le script Python pl.py fraîchement créé est exécuté.

Le script écrira alors le script Python run.py, téléchargé depuis le domaine kewltd[.]ru, dans n’importe lequel des dossiers codés en dur à l’intérieur de %appdata%. À la ligne 40, le fichier recevra l’attribut caché (« +h ») et indiquera que le processus doit être exécuté dans un environnement shell (« shell=True »).

Au final, le script exécute tous les scripts run.py placés dans les différents dossiers codés en dur dans la variable startup_folder.

Le script run.py est fortement obfusqué et dépasse mon niveau actuel de capacité à l’inverser. Si vous lisez ceci et que vous voulez essayer, vous pouvez le récupérer à partir de l’analyse urlscan.io que j’ai faite. Toutefois, l’auteur de la menace a laissé un message à l’intention de tous ceux qui s’intéressent au script.

Maintenant que le script en texte clair a été analysé, il est temps de se plonger dans le code crypté du Fernet !

Code crypté Fernet

Pour commencer, le scénario a subi quelques modifications, mais il est pour l’essentiel resté le même. Qu’est-ce qui a changé ?

Alors que le paquet pyfontingtoolsV1 (le tout premier script) utilisait le module os.system pour télécharger tous les paquets PyPi nécessaires, cette version utilise le module subprocess.Popen pour lancer cmd.exe afin de lancer pip install en installant les modules codés en dur. Les deux fois avec la variable creationflags à la fin (non visible dans la deuxième capture d’écran).

Dans cette version du script, le voleur de portefeuille Exodus n’est plus crypté avec une autre commande Fernet mais il est maintenant en texte clair à l’intérieur du script.

Bien que la version 1.2.0 contienne quelques codes potentiellement malveillants, la charge utile principale étant cryptée avec du Fernet, elle échappe à nouveau à toutes les détections AV sur VirusTotal.

PyPi passe à l’action

PyPi a été très affecté par l’afflux de paquets malveillants téléchargés quotidiennement et a pris plusieurs mesures.

Le 20 mai 2023, PyPi suspend temporairement les enregistrements de nouveaux utilisateurs et de nouveaux projets. Un jour plus tard, environ 30 heures après l’annonce, la suspension est à nouveau levée.

L’enregistrement de nouveaux utilisateurs et de nouveaux projets sur PyPI est temporairement suspendu. Le volume d’utilisateurs et de projets malveillants créés sur l’index au cours de la semaine dernière a dépassé notre capacité à y répondre en temps utile, en particulier avec plusieurs administrateurs PyPI en congé.

Pendant le week-end, l’enregistrement des nouveaux utilisateurs et des nouveaux projets est temporairement suspendu.

https://status.python.org/incidents/qy2t9mjjcc7g

Le 25 mai 2023, PyPi annonce qu’il ira plus loin et commencera à imposer le 2FA aux responsables de projets ou d’organisations d’ici la fin de l’année 2023.

Aujourd’hui, dans le cadre de cet effort à long terme pour sécuriser l’écosystème Python, nous annonçons que chaque compte qui gère un projet ou une organisation sur PyPI devra activer 2FA sur son compte d’ici la fin de 2023.

D’ici la fin de l’année, PyPI commencera à restreindre l’accès à certaines fonctionnalités du site en fonction de l’utilisation de 2FA. En outre, nous pourrons commencer à sélectionner certains utilisateurs ou projets pour une application anticipée.

https://blog.pypi.org/posts/2023-05-25-securing-pypi-with-2fa/

Conclusion

Le responsable du développement du logiciel malveillant Kekw fait preuve de résilience en mettant à jour le logiciel malveillant pour éviter d’être détecté. L’acteur de la menace utilise aussi très probablement une forme d’automatisation pour télécharger de nouveaux paquets sur PyPi et mettre à jour tous les différents dépôts GitHub. Initialement sur plusieurs comptes, mais après des actions du côté de GitHub, un seul compte est utilisé.

D’autre part, PyPi a également fait un excellent travail en supprimant les paquets malveillants dès que possible. L’arrêt temporaire des enregistrements a dû être une décision difficile à prendre. Grâce à l’application de la norme 2FA, les menaces de ce type deviendront probablement moins fréquentes. L’application du 2FA présente également l’avantage de rendre un peu plus difficile la compromission de la chaîne d’approvisionnement.

Malgré tout, l’acteur de la menace n’a pas encore disparu de la surface de la terre et a très récemment fait son retour après une ou deux semaines d’inactivité.

More about that in my next blog which will come (hopefully) very soon!

N’hésitez pas à nous contacter !

AUTRES HISTOIRES

Les cybercriminels ne cessent d’évoluer. Découvrez les dernières astuces de diffusion de logiciels malveillants, les tactiques d’évasion et les chaînes d’attaque réelles pour garder une longueur d’avance en matière de cybersécurité.
Le DNS sur HTTPS (DoH) renforce la confidentialité mais ouvre de nouveaux risques de sécurité. Découvrez comment les cybercriminels l’exploitent et comment les entreprises peuvent rester protégées.
La sécurité SSH est menacée par l’attaque Terrapin. Découvrez comment elle exploite les vulnérabilités, affaiblit le chiffrement et quelles sont les mesures à prendre pour rester protégé.

Contactez-nous pour en savoir plus sur nos services et solutions

Notre équipe vous aidera à entamer votre voyage vers la cyber-sérénité

Préférez-vous nous envoyer un courriel ?