Qu’il s’agisse de détournement de paquets, de confusion entre dépendances, de typosquatting, de compromission de l’intégration et de la livraison continues ([CI/CD) ou de l’exploitation web basique de dépendances obsolètes, il existe de nombreuses attaques de la chaîne d’approvisionnement logicielle que les adversaires peuvent mener pour mettre leurs victimes hors service, les soumettre à une rançon et exfiltrer des données critiques.
Il est souvent plus efficace d’attaquer un maillon faible de la chaîne pour atteindre une cible plus importante, comme cela est arrivé à Kaseya ou à SolarWinds ces dernières années. Les attaquants peuvent implanter une exécution de code à distance (RCE) ou dérober les identifiants des développeurs afin d’élever leurs privilèges et de mener discrètement des actions malveillantes.
De plus, il peut leur suffire de compromettre un seul paquet pour diffuser des logiciels malveillants à un grand nombre d’utilisateurs et d’organisations, car la chaîne d’approvisionnement actuelle est extrêmement complexe et interconnectée.
Bien sûr, les développeurs ne peuvent pas être tenus responsables de toutes les vulnérabilités, mais ils disposent généralement de comptes privilégiés et même d’un accès direct à des documents et des pipelines sensibles, ce qui en fait des cibles de plus en plus attrayantes.
Pour aider les développeurs à se protéger contre les attaques visant la chaîne d’approvisionnement, la National Security Agency (NSA), la Cybersecurity and Infrastructure Security Agency (CISA) et l’Office of the Director of National Intelligence (ODNI) des États-Unis ont récemment publié un guide complet pour les aider à sécuriser leur code et leurs processus.
Voir les Principaux outils de débogage et de sécurité du code
Bloquer les injections de code malveillant
Selon le guide, les acteurs malveillants continuent d’exploiter les divulgations publiques de vulnérabilités, mais au lieu de les attendre, « ils injectent de manière proactive du code malveillant dans des produits qui sont ensuite distribués légitimement en aval par la chaîne d’approvisionnement mondiale ».
Les équipes de développement ont souvent du mal à gérer les mises à jour et les opérations DevOps (développement et opérations), qui prennent beaucoup de temps. Elles automatisent donc les pipelines CI/CD pour les déploiements et les tests, mais le processus est parfois mal configuré et manque souvent de contrôles de sécurité.
Une autre technique courante consiste à compromettre un paquet utilisé uniquement par les développeurs (par exemple, les devDependencies dans Node) afin de dérober leurs identifiants, comme les clés AWS.
Les nouvelles recommandations américaines recensent les scénarios de menace courants au cours du cycle de vie des logiciels :
- Un adversaire injecte intentionnellement du code malveillant, ou un développeur inclut involontairement du code vulnérable dans un produit.
- Du code source ou des binaires vulnérables provenant de tiers sont intégrés à un produit, sciemment ou non.
- Des faiblesses du processus de compilation sont exploitées pour injecter un logiciel malveillant dans un composant d’un produit.
- Un produit du mécanisme de livraison est modifié, ce qui entraîne l’injection d’un logiciel malveillant dans le paquet d’origine, la mise à jour ou le bundle de mise à niveau déployé par le client.
Le document énumère des mesures concrètes pour réduire les risques :
- Générer des documents d’architecture et de conception.
- Constituer une équipe de développement formée, qualifiée et digne de confiance.
- Créer des modèles de menace pour le produit logiciel.
- Définir et mettre en œuvre des plans de tests de sécurité.
- Définir des critères de mise en production et évaluer le produit au regard de ceux-ci.
- Établir des politiques et procédures d’assistance produit et de gestion des vulnérabilités.
- Évaluer les compétences des développeurs et leur compréhension du processus de développement sécurisé, puis leur attribuer des formations.
- Documenter et publier les procédures et processus de sécurité pour chaque version logicielle.
Comment sécuriser le code
Écrire du code sécurisé implique des procédures telles que les revues de code et les tests de sécurité, quel que soit le langage de programmation, même si certains, comme Rust, privilégient la sécurité par défaut.
Le guide souligne la fréquence des injections intentionnelles et non intentionnelles de code malveillant dans les attaques.
Les ingénieurs et les développeurs peuvent être compromis dans des situations apparemment anodines, comme l’insatisfaction ou l’influence extérieure. Le manque de formation peut également expliquer de graves défauts de conception, particulièrement difficiles à détecter et susceptibles d’entraîner des attaques zero-day qui peuvent rester non corrigées pendant des mois.
De plus, les programmeurs aiment implémenter des paramètres spéciaux et d’autres fonctionnalités de débogage pour faciliter le dépannage ou la configuration. Malheureusement, il n’est pas rare que ces « bidouilles » se retrouvent en production par souci de commodité, ou que quelqu’un oublie simplement de les supprimer après utilisation.
Le guide invite les équipes techniques à appliquer les mesures d’atténuation suivantes :
- Mettre en œuvre un processus bien équilibré et authentifié d’enregistrement du code source, avec notamment de bonnes pratiques pour les dépôts GIT et l’authentification multifacteur (MFA).
- Effectuer automatiquement des analyses statiques et dynamiques des vulnérabilités.
- Effectuer des compilations nocturnes avec des tests de sécurité et de régression.
- Mapper les fonctionnalités à des exigences telles que la restriction des paquets de développement et la suppression des dépendances inutilisées.
- Donner la priorité aux revues de code et examiner le code critique.
- Mettre en œuvre une formation au développement et à la programmation sécurisés.
- Renforcer l’environnement de développement au moyen de méthodes telles que le VPN, l’authentification multifacteur, le « jump host » et la modélisation des menaces pour chaque environnement.
Comment améliorer le processus de compilation
Qu’il s’agisse du développeur individuel ou de l’environnement de compilation de production, il est recommandé de valider la sécurité du logiciel avant sa livraison et sa distribution aux utilisateurs finaux. Les équipes peuvent exploiter différents outils et techniques. Par exemple :
- Mettre en œuvre des contrôles indirects tels que des analyses de vulnérabilités, des tests d’intrusion, des filigranes, la prévention des pertes de données (DLP), ainsi que des contrôles d’intégrité
- SBOMs (nomenclatures logicielles) et des signatures numériques pour valider les livraisons
- Cycles itératifs rapides (développement agile)
- Journaux d’accès pour tous les pipelines
- Chiffrer les secrets
- Principe du moindre privilège
- La segmentation du réseau
- Déploiement sur site
- Contrôle des versions
- Tests A/B dans les pipelines CI/CD
Bonnes pratiques pour le contrôle des versions
Le document fournit des recommandations pour protéger le code source.
Premièrement, l’accès et la validation commencent par de bons principes de gestion du code source (SCM) afin de suivre les modifications apportées à un dépôt de code source.
Les équipes de développement devraient également activer les notifications afin d’être alertées lorsqu’une nouvelle menace, version ou mise à jour est détectée. Les principales plateformes de gestion de versions, comme GitLab ou GitHub, proposent ces fonctionnalités, mais le guide recommande d’aller plus loin et de tenir « un journal de tous les développeurs et des composants qu’ils téléchargent ».
L’authentification multifacteur doit être activée « pour tout accès » au dépôt, et les équipes peuvent utiliser les branches Git de base pour maintenir l’organisation :
- Les développeurs travaillent dans la branche de développement.
- Après revue et approbation du code, les responsables promeuvent le logiciel vers une branche d’assurance qualité (QA).
- Les équipes QA testent le logiciel depuis la branche QA.
- S’il est approuvé, le contenu de la branche peut être fusionné dans la branche de production.
Le guide recommande de limiter l’accès à la branche de production à « un petit groupe de membres de l’équipe et responsables de la compilation » et de mettre en œuvre des procédures de verrouillage après chaque version afin de sécuriser les compilations.
Les développeurs devraient également signer les commits. Le guide ne le mentionne pas explicitement, mais certaines attaques reposent sur des clés volées pour pousser des commits. Dans ce cas, les modifications non autorisées seront attribuées à un utilisateur légitime.
Il n’est pas rare que les développeurs utilisent des clés temporaires pour configurer des environnements. S’ils ne suppriment pas les clés après utilisation, un attaquant pourrait les retrouver après avoir obtenu accès au serveur.
Une autre attaque peut consister à usurper l’identité d’un mainteneur légitime en créant un faux paquet et en configurant Git avec les informations du mainteneur (par exemple, par typosquatting).
Les développeurs peuvent signer les commits avec des clés GPG (Gnu Privacy Guard) ou des bibliothèques comme Gitsign. Ce n’est pas infaillible, mais cette couche de sécurité supplémentaire est relativement facile à mettre en place.
À lire ensuite : Principaux outils de gestion des vulnérabilités





