Qu'est-ce que l'exécution d'un pipeline empoisonné (EPP) ?
L'exécution de pipeline empoisonné (PPE), un risque de sécurité CI/CD de l'OWASP, est un vecteur d'attaque qui abuse des autorisations d'accès à un système de gestion du code source (SCM) dans le but d'amener un pipeline CI à exécuter des commandes malveillantes. Bien que les attaquants PPE n'aient pas accès à l'environnement de construction, ils ont obtenu l'accès au SCM, ce qui leur permet d'injecter du code malveillant dans la configuration du pipeline de construction afin de manipuler le processus de construction.
CICD-SEC-4 : Explication de l'exécution d'un pipeline empoisonné
L'exécution de pipelines empoisonnés (PPE), répertoriée comme CICD-SEC-4 dans le Top 10 des risques de sécurité CI/CD de l'OWASP, représente une stratégie d'attaque sophistiquée ciblant les systèmes d'intégration continue et de déploiement continu (CI/CD).
Les clients peuvent disposer d'une variété d'options :
Dans la stratégie PPE, les attaquants exécutent un code malveillant dans la partie CI du Pipelines CI/CD, en contournant la nécessité d'un accès direct au système CI/CD. La méthode consiste à manipuler les référentiels des codes d'un dépôt de gestion du code source (SCM). En modifiant les fichiers de configuration de l'IC ou d'autres fichiers dont dépend le travail du pipeline de l'IC, les attaquants injectent des commandes malveillantes, ce qui a pour effet d'empoisonner le pipeline de l'IC et de permettre l'exécution de code non autorisé.
Les attaques réussies de l'EPI peuvent permettre un large éventail d'opérations, toutes exécutées dans le contexte de l'identité du pipeline. Les opérations malveillantes peuvent inclure l'accès à des secrets disponibles pour le travail d'IC, l'accès à des ressources externes pour lesquelles le nœud de travail dispose d'autorisations, l'envoi de code et d'artefacts apparemment légitimes le long du pipeline et l'accès à des hôtes et des ressources supplémentaires dans le réseau ou l'environnement du nœud de travail.
Compte tenu de son impact critique, de sa faible détectabilité et de l'existence de multiples techniques d'exploitation, l'attaque PPE constitue une menace de grande ampleur. Pour les équipes de sécurité, les ingénieurs et les équipes rouges, la compréhension des EPI et de leurs contre-mesures est essentielle à la sécurité des IC/CD
Définition de l'exécution du pipeline
Dans le contexte de l'intégration continue (CI), le flux d'exécution du pipeline fait référence à la séquence d'opérations définie par le fichier de configuration CI hébergé dans le référentiel que le pipeline construit. Ce fichier décrit l'ordre d'exécution des travaux, ainsi que les paramètres de l'environnement de construction et les conditions qui affectent le flux. Lorsqu'il est déclenché, le travail de pipeline extrait le code de la source choisie (par exemple, commit/branche) et exécute les commandes spécifiées dans le fichier de configuration de l'IC par rapport à ce code.
Les commandes du pipeline sont invoquées soit directement par le fichier de configuration de l'IC, soit indirectement par un script, un test de code ou un linter résidant dans un fichier distinct référencé dans le fichier de configuration de l'IC. Les fichiers de configuration de l'IC ont généralement des noms et des formats cohérents, tels que Jenkinsfile (Jenkins), .gitlab-ci.yml (GitLab), .circleci/config.yml (CircleCI), et les fichiers YAML des actions GitHub situés sous .github/workflows.
Les attaquants peuvent exploiter la capacité à manipuler les commandes exécutées par le pipeline, directement ou indirectement, pour exécuter un code malveillant dans l'IC.
Comment l'exploitation du CICD-SEC-4 se produit-elle ?
Pour qu'une attaque par EPI soit réussie, plusieurs critères doivent être remplis :
- L'attaquant doit obtenir les autorisations nécessaires pour accéder à un dépôt SCM. Il peut s'agir d'informations d'identification de l'utilisateur, de jetons d'accès, de clés SSH, de jetons OAuth ou d'autres méthodes. Dans certains cas, un accès anonyme à un dépôt public peut suffire.
- Les modifications apportées au référentiel en question doivent déclencher un pipeline de CI sans approbations ou révisions supplémentaires. Cela peut se faire par des poussées directes vers des branches distantes ou par des changements suggérés via une demande de traction provenant d'une branche ou d'une fourche distante.
- Les permissions obtenues par l'attaquant doivent permettre de déclencher les événements qui entraînent l'exécution du pipeline.
- Les fichiers que l'attaquant peut modifier doivent définir les commandes qui sont exécutées (directement ou indirectement) par le pipeline.
- Le nœud de pipeline doit avoir accès à des ressources non publiques, telles que des secrets, d'autres nœuds ou des ressources informatiques.
Les pipelines qui exécutent du code non revu, tels que ceux qui sont déclenchés par des demandes d'extraction ou des commits vers des branches arbitraires du référentiel, sont plus susceptibles de faire l'objet d'un EPI. Une fois qu'un attaquant peut exécuter un code malveillant dans le pipeline d'IC, il peut mener des opérations malveillantes dans le contexte de l'identité du pipeline.
Trois types d'exécution de pipelines empoisonnés
L'exécution d'un pipeline empoisonné se manifeste sous trois formes distinctes : la PPE directe (D-PPE), la PPE indirecte (I-PPE) et la PPE publique (3PE).
EPI direct
Dans un scénario d'EPI direct, les attaquants modifient le fichier de configuration de l'IC dans un dépôt auquel ils ont accès, soit en poussant la modification directement vers une branche distante non protégée sur le dépôt, soit en soumettant une demande d'extraction avec la modification à partir d'une branche ou d'une fourche. L'exécution du pipeline est déclenchée par les événements de requête "push" ou "pull", tels que définis par les commandes dans le fichier de configuration CI modifié, ce qui entraîne l'exécution des commandes malveillantes dans le nœud de construction une fois que le pipeline de construction est déclenché.

Figure 1 : Flux de l'attaque directe par l'exécution d'un pipeline empoisonné
L'exemple d'attaque D-PPE illustré à la figure 1 se déroule selon la succession d'étapes suivante :
- Un adversaire initie une nouvelle branche distante au sein du référentiel, modifiant le fichier de configuration du pipeline avec des instructions nuisibles pour récupérer les identifiants AWS stockés au sein de l'organisation GitHub et les transmettre à un serveur externe sous le contrôle de l'attaquant.
- La poussée de code active un pipeline qui extrait le code, y compris le fichier de configuration du pipeline malveillant, du référentiel.
- Le pipeline fonctionne selon le fichier de configuration, qui est maintenant entaché par l'attaquant. Les instructions malveillantes commandent le chargement en mémoire des informations d'identification AWS, stockées en tant que secrets de dépôt.
- Suivant les instructions de l'attaquant, le pipeline transmet les informations d'identification AWS à un serveur contrôlé par l'attaquant.
- En possession des informations d'identification volées, l'attaquant a la possibilité d'infiltrer l'environnement de production.
EPI indirect
Il y a EPI indirect lorsque la possibilité d'EPD n'est pas disponible pour un adversaire ayant accès à un référentiel SCM :
- Si le pipeline est configuré pour extraire le fichier de configuration CI d'une branche séparée et protégée dans le même dépôt.
- Si le fichier de configuration de l'IC est stocké dans un référentiels des codes séparés du code source, sans possibilité pour un utilisateur de le modifier directement.
- Si le build CI est défini dans le système CI lui-même - au lieu d'un fichier stocké dans le code source.
Dans ces scénarios, l'attaquant peut toujours empoisonner le pipeline en injectant du code malveillant dans les fichiers référencés par le fichier de configuration du pipeline, tels que les scripts référencés dans le fichier de configuration du pipeline, les tests de code ou les outils automatiques tels que les linters et les scanners de sécurité utilisés dans l'IC. Par exemple :
- L'utilitaire make exécute les commandes définies dans le fichier Makefile.
- Les scripts référencés à partir du fichier de configuration du pipeline, qui sont stockés dans le même référentiels que le code source lui-même (par exemple, python myscript.py - où myscript.py serait manipulé par l'attaquant).
- Tests de code : Les référentiels de test fonctionnant sur le code de l'application dans le cadre du processus de construction s'appuient sur des fichiers dédiés, stockés dans le même référentiel que le code source. Les attaquants qui parviennent à manipuler le code responsable des tests peuvent alors exécuter des commandes malveillantes à l'intérieur de la construction.
- Outils automatiques : Les linters et les scanners de sécurité utilisés dans l'IC s'appuient généralement sur un fichier de configuration résidant dans le référentiel qui charge et exécute généralement du code externe à partir d'un emplacement défini dans le fichier de configuration.
Plutôt que d'empoisonner le pipeline par une attaque PPE directe, l'attaquant qui lance une attaque PPE indirecte injecte un code malveillant dans les fichiers référencés par le fichier de configuration. Le code malveillant est finalement exécuté sur le nœud du pipeline et exécute les commandes déclarées dans les fichiers.

Figure 2 : Flux de l'attaque indirecte par l'exécution d'un pipeline empoisonné
Dans cet exemple d'attaque I-PPE, la chaîne des événements se déroule comme suit :
- Un attaquant crée une demande d'extraction dans le dépôt, en ajoutant des commandes malveillantes au fichier Makefile.
- Puisque le pipeline est configuré pour se déclencher sur tout PR contre le repo, le pipeline Jenkins est déclenché, récupérant le code du repo - y compris le Makefile malveillant.
- Le pipeline s'exécute sur la base du fichier de configuration stocké dans la branche principale. Il arrive à l'étape de construction et charge les informations d'identification AWS dans les variables d'environnement - comme défini dans le fichier Jenkins d'origine. Il lance ensuite la commande make build, qui exécute la commande malveillante ajoutée dans Makefile.
- La fonction de compilation malveillante définie dans le fichier Makefile est exécutée, envoyant les informations d'identification AWS à un serveur contrôlé par l'attaquant.
- L'attaquant peut alors utiliser les informations d'identification volées pour accéder à l'environnement de production AWS.
EPI public
L'EPI public est un type d'attaque EPI exécutée par des attaquants anonymes sur l'internet. Les dépôts publics permettent souvent à n'importe quel utilisateur de contribuer, généralement en créant des demandes d'extraction. Si le pipeline d'IC d'un référentiel public exécute du code non revu suggéré par des utilisateurs anonymes, il est susceptible de faire l'objet d'une attaque EPI publique. L'EPI public peut également exposer des actifs internes, tels que des secrets de projets privés, dans les cas où le pipeline du référentiel public vulnérable fonctionne sur la même instance d'IC que des projets privés.
Importance de l'exécution sécurisée des pipelines dans CI/CD
L'exécution d'un code malveillant non revu dans l'IC par une attaque PPE réussie donne aux attaquants le même niveau d'accès et de capacité que le travail de construction :
- Accès aux secrets disponibles pour le travail de CI, tels que les secrets injectés en tant que variables d'environnement ou les secrets supplémentaires stockés dans le CI. Responsables de la construction du code et du déploiement des artefacts, les systèmes CI/CD contiennent généralement des dizaines d'informations d'identification et de jetons de grande valeur - par exemple vers un fournisseur de cloud, vers des registres d'artefacts et vers le SCM lui-même.
- Accès à des actifs externes sur lesquels le nœud de travail dispose d'autorisations, tels que des fichiers stockés dans le système de fichiers du nœud, ou des informations d'identification sur un environnement cloud accessible par l'intermédiaire de l'hôte sous-jacent.
- Possibilité d'envoyer du code et des artefacts plus loin dans le pipeline, sous l'apparence d'un code légitime construit par le processus de construction.
- Capacité d'accéder à des hôtes et à des actifs supplémentaires dans le réseau/l'environnement du nœud de travail.
Mais les organisations peuvent protéger leurs produits logiciels et leur infrastructure grâce à un pipeline d'exécution sécurisé qui garantit que tout le code compilé, testé et déployé est légitime et n'a pas été altéré.
Risques associés à l'exécution d'un pipeline empoisonné
Les conséquences de l'EPI peuvent être graves, allant de l'accès non autorisé aux données, à la compromission de l'intégrité des logiciels, aux interruptions de système, aux violations de données ou même à la prise de contrôle totale du système. Ces risques constituent des menaces importantes pour l'entreprise et ses clients, ce qui souligne l'importance de l'EPI.

Figure 3 : Impact en aval d'un pipeline CI empoisonné
Dans l'opération de compromission de la chaîne d'approvisionnement en huit étapes présentée dans la figure 3, l'attaquant accède au pipeline de CI et empoisonne les composants de l'application SaaS. Par l'intermédiaire du composant empoisonné, l'attaquant crée une fonctionnalité de porte dérobée dans l'application et envoie les plugins empoisonnés aux clients en aval. Comme les organisations en aval perçoivent probablement le progiciel empoisonné comme légitime, elles l'intègrent à leur infrastructure dans le cloud ou sur place.
À partir d'un seul pipeline d'informations critiques empoisonné, l'attaquant réalise des dommages collatéraux exponentiels, en créant des accès dérobés à d'innombrables organisations. C'est le cas de l'attaque SolarWinds.
LIRE LA SUITE : Anatomie d'une attaque sur le pipeline CI/CD
Prévention de l'exécution d'un pipeline empoisonné
La prévention et l'atténuation du vecteur d'attaque EPI impliquent de multiples mesures couvrant à la fois les systèmes SCM et CI :
- Veillez à ce que les pipelines exécutant du code non revu soient exécutés sur des nœuds isolés plutôt qu'exposés à des secrets et à des environnements sensibles.
- Évaluer la nécessité de déclencher des pipelines sur des dépôts publics provenant de contributeurs externes. Dans la mesure du possible, abstenez-vous d'exécuter des pipelines provenant de forks et envisagez d'ajouter des contrôles tels que l'exigence d'une approbation manuelle pour l'exécution des pipelines.
- Pour les pipelines sensibles, par exemple ceux qui sont exposés à des secrets, assurez-vous que chaque branche configurée pour déclencher un pipeline dans le système CI dispose d'une règle de protection de branche corrélative dans le SCM.
- Afin d'empêcher la manipulation du fichier de configuration de l'IC pour exécuter un code malveillant dans le pipeline, chaque fichier de configuration de l'IC doit être examiné avant l'exécution du pipeline. Le fichier de configuration de l'IC peut également être géré dans une branche distante, séparée de la branche contenant le code en cours de construction dans le pipeline. La branche distante doit être configurée comme protégée.
- Supprimez les permissions accordées sur le référentiel SCM aux utilisateurs qui n'en ont pas besoin.
- Chaque filière ne doit avoir accès qu'aux informations d'identification dont elle a besoin pour remplir sa mission. Les exigences doivent être assorties des privilèges minimums requis.