Aller au contenu

CICD-SEC-1 : mécanismes de contrôle de flux insuffisants

CICD-SEC-1 : mécanismes de contrôle de flux insuffisants

Section intitulée « CICD-SEC-1 : mécanismes de contrôle de flux insuffisants »

Première entrée du Top 10 OWASP CI/CD. Le libellé officiel est Insufficient Flow Control Mechanisms, et la définition tient en une phrase désagréable : un attaquant qui a obtenu des permissions sur un système de la chaîne (gestion de code source, intégration continue, dépôt d’artefacts) peut pousser seul du code ou un artefact jusqu’en production, faute de mécanisme imposant une approbation ou une revue supplémentaire.

→ Lire l’explication complète de la marmotte

Le mécanisme : le contrôle existe, il n’est pas sur le chemin

Section intitulée « Le mécanisme : le contrôle existe, il n’est pas sur le chemin »

Il n’y a rien à exploiter ici, aucune vulnérabilité. Le défaut est d’organisation : les chaînes de livraison sont conçues pour la vitesse, et chaque dispositif d’approbation se heurte à un cas particulier qui le contourne légitimement. Au bout de deux ans, l’organisation possède une revue de code obligatoire, une protection de branche, une politique d’approbation, et un chemin où rien de tout cela ne s’applique.

Le référentiel énumère sept variantes, et cette liste se lit comme un inventaire des commodités d’équipe :

  • pousser sur une branche déployée automatiquement, cas nominal d’un dépôt en livraison continue ;
  • pousser sur une branche quelconque, puis déclencher le pipeline de déploiement à la main, ce qui dissocie la relecture de la mise en service ;
  • pousser directement dans une bibliothèque utilitaire employée en production, les bibliothèques internes n’ayant presque jamais le régime de protection des applications qu’elles servent ;
  • abuser d’une règle de fusion automatique qui accepte toute demande remplissant des critères prédéfinis : l’incident Homebrew de 2021 a montré qu’une règle destinée à fusionner les modifications insignifiantes pouvait être détournée pour en fusionner d’autres ;
  • exploiter une règle de protection de branche qui exclut certains comptes ou certaines branches, l’exclusion ayant souvent été ajoutée pour débloquer un compte de service un vendredi soir ;
  • déposer dans le dépôt d’artefacts un paquet ou une image ressemblant à ce que l’environnement de construction produit, en espérant qu’aucune vérification ne distingue les deux ;
  • modifier directement le code ou l’infrastructure en production, par la console du fournisseur cloud, sans approbation ni trace dans le dépôt.

Deux variantes sont les moins visibles. L’exclusion dans une règle de protection de branche se cache dans les options avancées : la page affiche « branche protégée » et la protection ne s’applique pas au compte qui livre. Et le dépôt direct d’artefacts échappe entièrement au contrôle de code source, où se trouvent tous les dispositifs de revue ; c’est le sujet propre de CICD-SEC-9.

Le précédent le plus net est la porte dérobée du dépôt Git de PHP : du code non relu poussé directement sur la branche principale, ayant abouti à la publication d’une version officielle du langage. Aucun exploit, seulement un droit d’écriture.

Il obtient la production, avec une seule identité compromise. C’est tout l’enjeu : sans contrôle de flux, le niveau de sécurité de la production est celui du compte le plus faible ayant un droit d’écriture quelque part dans la chaîne. Le vol du jeton d’un compte de service ne donne plus accès à « un dépôt » mais à la capacité de livrer.

Deux conséquences dérivées comptent autant que l’accès. D’abord l’artefact livré est légitime : métadonnées d’une construction normale, déploiement enregistré comme réussi, rien qui le distingue des précédents. Ensuite la persistance est gratuite : le code modifié reste dans la branche, il sera reconstruit à chaque livraison suivante, et survit donc au nettoyage d’un serveur, ce que décrivent la détection de la persistance d’un attaquant et la tactique ATT&CK correspondante.

La dérive entre la production et son origine. La détection la plus utile et la plus rarement en place : comparer ce qui tourne à ce que la chaîne a produit, et traiter tout écart comme un incident. L’inventaire réel contre la dérive de configuration en décrit la difficulté : il faut une source de vérité, et beaucoup n’en ont pas.

Les livraisons sans demande de fusion associée. Un déploiement dont on ne peut pas remonter à une demande de fusion approuvée est un signal fort et facile à calculer : corréler l’événement de déploiement et l’historique du dépôt. Encore faut-il que les deux journaux arrivent au même endroit, objet de CICD-SEC-10.

Les exclusions dans les règles de protection. Elles ne se lisent pas dans un journal mais dans un inventaire : lister périodiquement, par programme, les règles de protection et leurs exceptions. La difficulté est que personne ne regarde, pas que la donnée manque.

Les dépôts d’artefacts qui reçoivent d’ailleurs. Un artefact déposé par un compte autre que celui du service de construction est anormal par définition : règle triviale à écrire, presque jamais écrite.

Les déclenchements manuels de pipelines de déploiement. Rares et nominatifs, donc intéressants : une alerte par déclenchement manuel vers la production reste supportable en volume, argument décisif face à la fatigue d’alerte.

Séparer le droit d’écrire du droit de déployer. C’est la recommandation la plus précise du référentiel, et la moins appliquée : lorsqu’un compte a le droit de pousser du code non relu dans un dépôt, il ne doit pas avoir le droit de déclencher les pipelines de déploiement rattachés à ce dépôt. Cette séparation est une variante de celle décrite dans la séparation des plans de contrôle, appliquée à la chaîne de livraison. Le découpage pratique des droits est traité dans les permissions Git en entreprise et, pour le cas difficile, dans les permissions fines d’un monorepo.

Refuser les exceptions dans les protections de branche. Une exclusion est une porte, et une porte oubliée est une porte ouverte. Quand elle est inévitable, elle se date et se revoit, comme toute dérogation.

N’accepter dans la chaîne que les artefacts produits par le compte de service de construction, et soumettre tout autre dépôt à une revue. Cette règle est le pendant, côté flux, de la vérification cryptographique décrite dans signer commits et artefacts.

Borner les règles de fusion automatique au plus petit nombre de contextes, en relisant leur propre code : une règle de fusion automatique est un programme qui a le droit de fusionner, donc un composant de sécurité, et elle ne doit pas importer de code tiers.

Révoquer réellement les comptes de service, puisque c’est par eux que les exclusions existent : les comptes de service Git et les identités jamais révoquées. Le fond relève du contrôle d’accès défaillant du catalogue CWE, et plus précisément de l’autorisation manquante : « déployer en production » n’est pas autorisé séparément de « écrire du code ».

  • CICD-SEC-1: Insufficient Flow Control Mechanisms, OWASP Top 10 CI/CD Security Risks, 2022 : définition, sept variantes d’impact, recommandations.
  • Références citées par le document : la porte dérobée du dépôt Git de PHP, le contournement d’une règle de fusion automatique de Homebrew (2021), et le contournement des revues obligatoires au moyen d’actions d’intégration continue.

L’organisation découvre après coup que sa revue de code n’a jamais été sur le chemin critique. L’enquête est alors d’un genre particulier : pas d’intrusion à reconstituer, seulement une livraison à expliquer, et cette livraison est enregistrée comme un succès, par un compte autorisé, à une heure ouvrée. Établir qu’elle n’aurait pas dû avoir lieu exige de remonter à l’absence d’une demande de fusion, information que la plupart des chaînes ne conservent pas sous une forme interrogeable. Le coût se mesure ensuite : le code modifié étant resté dans la branche, chaque reconstruction le ramène, et l’équipe qui reconstruit « proprement » un serveur y réinstalle fidèlement le problème. D’où la difficulté particulière de décider d’assainir ou de reconstruire dans une chaîne de livraison.

Dans une entreprise qui fabrique du logiciel, le code écrit par une personne passe par une machinerie automatique qui l’assemble, le teste, puis l’installe sur les serveurs qui servent les clients. Cette machinerie va vite : quelques minutes, parfois.

Pour éviter qu’une seule personne puisse envoyer n’importe quoi en service, on pose des garde-fous : une deuxième personne relit le code, certaines branches sont protégées, certaines mises en service exigent une approbation. Tout cela existe dans presque toutes les entreprises.

Le défaut décrit ici consiste à avoir laissé, à côté de ces garde-fous, un chemin où ils ne s’appliquent pas. Les cas sont toujours les mêmes, et toujours justifiés au moment où on les crée : une branche qui partait directement en service parce que c’était pratique ; un compte technique exclu de la protection parce qu’il bloquait les livraisons ; une petite bibliothèque interne que personne n’a pensé à protéger comme une application ; une règle qui fusionne automatiquement les corrections mineures et s’avère fusionner un peu plus ; et le plus simple de tous, le droit de modifier les serveurs sans passer par le code.

La conséquence est que la solidité de l’ensemble n’est pas celle du garde-fou le plus sérieux, mais celle du chemin le plus négligé. Un seul compte dérobé suffit alors à faire installer un programme en service, et ce programme arrive avec toutes les apparences de la normalité : la machinerie a fonctionné correctement, elle a simplement fabriqué ce qu’on lui a demandé de fabriquer.

La mesure la plus efficace est une règle rarement écrite : celui qui a le droit d’écrire du code sans relecture ne doit pas avoir le droit de déclencher la mise en service. Deux droits différents, deux comptes différents, et le chemin négligé cesse de mener en production.

À lire aussi

  • CICD-SEC-4 : exécution de pipeline empoisonnéeCICD-SEC-4 du Top 10 OWASP CI/CD : l'exécution de pipeline empoisonnée, ses trois formes directe, indirecte et publique, ce que l'identité du pipeline apporte à l'attaquant, et pourquoi la revue de code n'est pas sur ce chemin.
  • CICD-SEC-6 : hygiène des identifiants insuffisanteCICD-SEC-6 du Top 10 OWASP CI/CD : les cinq endroits où les secrets d'une chaîne de livraison finissent par traîner, l'historique Git, les couches d'image, la sortie console, et ce que la rotation change réellement.
  • CICD-SEC-7 : configuration système non sécuriséeCICD-SEC-7 du Top 10 OWASP CI/CD : les défauts de durcissement des systèmes de la chaîne, l'accès réseau, les identifiants par défaut, et le piège du mode de mise au point sur un nœud de construction.
  • CICD-SEC-5 : contrôles d'accès du pipeline insuffisantsCICD-SEC-5 du Top 10 OWASP CI/CD : le PBAC, contexte d'exécution de chaque pipeline et de chaque étape. Ce que le nœud atteint, ce qu'une exécution hostile en tire, et la granularité qui décide des dégâts.

Pages voisines

: les deux pages se citent l’une l’autre.