Meilleures pratiques pour une chaîne d’approvisionnement logicielle sécurisée

L’open source est partout. Il se trouve dans de nombreux codebase protégé et de nombreux projets de la communauté. Pour les organisations et les individus, la question aujourd’hui n’est pas de savoir si vous utilisez ou non du code open source, mais de quel code open source vous vous servez, et en quelle quantité.

Si vous n’êtes pas au courant de ce qui se trouve dans votre chaîne d’approvisionnement logicielle, une vulnérabilité en amont située dans l’une de vos dépendances peut être fatale, vous rendant ainsi, vous et vos clients, vulnérables à une potentielle compromission. Dans ce document, nous allons approfondir ce que signifie le terme « chaîne d’approvisionnement logicielle », pourquoi cela est important et de quelle manière vous pouvez aider à sécuriser la chaîne d’approvisionnement de votre projet avec les meilleures pratiques.

L'état de l'Octoverse 2020 - Open SourceL'état de l'Octoverse 2020 - Open Source

Les dépendances

Le terme chaîne d’approvisionnement logicielle est utilisé pour faire référence à tout ce qui va dans votre logiciel et de là où il provient. Il s’agit des dépendances et des propriétés de vos dépendances dont votre chaîne d’approvisionnement logicielle dépend. Une dépendance est ce que votre logiciel doit exécuter. Il peut s’agir de code, de fichiers binaires ou d’autres composants, et de leur provenance, par exemple un référentiel ou un gestionnaire de package.

Elle inclut qui a écrit le code, quand il a été contribué, comment il a été examiné pour les problèmes de sécurité, les vulnérabilités connues, les versions prises en charge, les informations de licence et tout ce qui y touche à tout moment du processus.

Votre chaîne d’approvisionnement englobe également d’autres parties de votre pile au-delà d’une application unique. Il s’agit par exemple de scripts de génération et d’empaquetage ou du logiciel qui exécute l’infrastructure sur laquelle votre application s’appuie.

Vulnérabilités

Aujourd’hui, les dépendances logicielles sont omniprésentes. Il est très courant que vos projets utilisent des centaines de dépendances open source pour les fonctionnalités que vous n’avez pas besoin d’écrire vous-même. Cela peut signifier que vous n’avez pas écrit la majorité du code de votre application vous-même.

L'État de l'Octoverse 2020 - DépendancesL'État de l'Octoverse 2020 - Dépendances

Les vulnérabilités possibles dans vos dépendances tierces ou open source sont probablement des dépendances que vous ne pouvez pas contrôler aussi étroitement que le code que vous écrivez vous-même. Cela peut créer des risques de sécurité potentiels dans votre chaîne d’approvisionnement.

Si l’une de ces dépendances souffre d’une vulnérabilité, il y a de grandes chances pour que vous en souffriez aussi. Cela peut être effrayant car l’une de vos dépendances peut changer que vous n’en ayez conscience. Même si une vulnérabilité existe dans une dépendance aujourd’hui, mais n’est pas encore exploitable, elle peut être l’être à l’avenir.

La possibilité de tirer profit du travail de milliers de développeurs open source et d’auteurs de bibliothèque signifie que des milliers d’étrangers peuvent contribuer directement à votre code de production. Via la chaîne d’approvisionnement logicielle, votre produit est affecté par des vulnérabilités non corrigées, des erreurs involontaires ou même des attaques malveillantes contre les dépendances.

Compromission de la chaîne d’approvisionnement

La définition traditionnelle d’une chaîne d’approvisionnement provient de l’industrie manufacturière. Il s’agit de la chaîne formée par tous les processus nécessaires pour fabriquer et fournir quelque chose. Cette chaîne part de la planification, passe l’approvisionnement de matériaux, la fabrication et se termine par la vente. Une chaîne d’approvisionnement logicielle est similaire, sauf à la place des matériaux, ion utilise du code. Au lieu de fabriquer, on développe. Au lieu de creuser le minerai du sol, le code est sourcé auprès de fournisseurs commerciaux ou open source, et, en général, le code open source provient de référentiels. L’ajout de code à partir d’un référentiel signifie que votre produit est dépendant de ce code.

Par exemple, une attaque par la chaîne d’approvisionnement logicielle se produit lorsque du code malveillant est ajouté délibérément à une dépendance, par le biais de la chaîne d’approvisionnement de cette dépendance pour distribuer le code à ses victimes. Les attaques par la chaîne d’approvisionnement sont réelles. Il existe de nombreuses méthodes pour attaquer une chaîne d’approvisionnement, de l’insertion directe de code malveillant en tant que nouvelle contributeur, en passant par le détournement du compte d’un contributeur sans que d’autres personnes s’en aperçoive. Il est même possible de compromettre une clé de signature pour distribuer des logiciels qui ne font pas officiellement partie de la dépendance.

Une attaque de chaîne d’approvisionnement logicielle est rarement une fin en soi, il s’agit plutôt d’une opportunité pour un attaquant d’insérer des programmes malveillants ou de mettre une porte dérobée pour un accès futur.

The State of the Octoverse 2020 - Vulnerability LifecycleThe State of the Octoverse 2020 - Cycle de vie des vulnérabilités

Logiciels non mis à jour

Aujourd’hui, l’utilisation de code open source est importante et ne devrait pas diminuer pour le moment. Étant donné que nous n’arrêterons pas d’utiliser des logiciels open source, la menace pour la sécurité de la chaîne d’approvisionnement provient principalement des logiciels non corrigés. Sachant cela, comment pouvez-vous gérer le risque qu'une dépendance de votre projet ait une vulnérabilité ?

  • Connaître ce qui se trouve dans votre environnement. Cela nécessite de découvrir vos dépendances ainsi que toutes les dépendances transitives afin de comprendre les risques liés à ces dépendances, tels que les vulnérabilités ou les restrictions de gestion des licences.
  • Gérer vos dépendances. Lorsqu’une nouvelle faille de sécurité est détectée, vous devez déterminer si vous êtes impacté et, le cas échéant, mettre à jour vers la dernière version et appliquer le dernier correctif de sécurité disponible. Il est particulièrement important de passer en revue les modifications qui introduisent de nouvelles dépendances ou d’auditer régulièrement les dépendances plus anciennes.
  • Surveiller votre chaîne d’approvisionnement. Il s’agit d’auditer les contrôles que vous avez en place pour gérer vos dépendances. Cela vous aidera à appliquer des conditions plus restrictives pour que vos dépendances soient respectées.

L'état de l'Octoverse 2020 - AvertissementsL'état de l'Octoverse 2020 - Avertissements

Nous aborderons différents outils et techniques fournis par NuGet et GitHub que vous pouvez utiliser dès aujourd’hui pour résoudre les risques potentiels au sein de votre projet.

Savoir ce qui se trouve dans votre environnement

Packages avec des vulnérabilités connues

Consommateur de paquets 📦 | Auteur de paquets 📦🖊

.NET 8 et Visual Studio 17.8 ont ajouté NuGetAudit, qui avertira à propos des packages directement référencés avec des vulnérabilités connues pendant le processus de restauration. .NET 9 et Visual Studio 17.12 ont également modifié la valeur par défaut pour avertir concernant les packages transitifs.

NuGetAudit nécessite une source pour fournir une base de données de vulnérabilités connues. Par conséquent, si vous n’utilisez pas nuget.org comme source de paquet, vous devriez l’ajouter comme source d’audit.

Au moment où NuGet vous avertit, la vulnérabilité est déjà connue publiquement. Les attaquants peuvent utiliser cette divulgation publique pour développer des attaques contre les cibles qui n’ont pas corrigé leurs applications. Par conséquent, lorsque vous recevez un avertissement indiquant qu’un package que votre projet utilise présente une vulnérabilité connue, vous devez rapidement agir.

Graphe des dépendances NuGet

Consommateur de paquets

Vous pouvez afficher vos dépendances NuGet dans votre projet en consultant directement le fichier projet respectif.

Il se trouve généralement à l’un des deux emplacement suivants :

Selon la méthode que vous utilisez pour gérer vos dépendances NuGet, vous pouvez également utiliser Visual Studio pour visualiser directement vos dépendances dans l'Explorateur de solutions ou dans le Gestionnaire de packages NuGet.

Pour les environnements CLI, vous pouvez utiliser la commande pour répertorier les dépendances de votre projet ou de votre solution. Vous pouvez également utiliser la dotnet nuget why commande pour comprendre pourquoi les packages transitifs (ceux qui ne sont pas directement référencés par votre projet) sont inclus dans le graphique de package de votre projet.

Pour plus d’informations sur la gestion des dépendances NuGet, consultez la documentation suivante.

Graphique des dépendances de GitHub

Consommateur de paquet | Auteur de paquet

Vous pouvez utiliser le graphe des dépendances de GitHub pour afficher les packages dont dépend votre projet et les référentiels qui dépendent de celui-ci. Ce graphe peut vous permettre de voir l’ensemble des vulnérabilités détectées dans les dépendances du projet.

Pour plus d’informations sur les dépendances des dépôts GitHub, consultez la documentation suivante.

Version des dépendances

Consommateur de package | Auteur de package

Pour garantir une chaîne d’approvisionnement de dépendances sécurisée, vous devez vous assurer que tous vos outils et de dépendances sont régulièrement mis à jour vers la dernière version stable, car ils incluent souvent les dernières fonctionnalités et correctifs de sécurité aux vulnérabilités connues. Les dépendances comprennent le code dont vous dépendez, les fichiers binaires que vous consommez, les outils dont vous vous utilisez ainsi que d’autres composants. Cela peut inclure :

Gérer les dépendances

Dépendances NuGet déconseillées et vulnérables

Consommateur de paquets 📦 | Auteur de paquets 📦🖊

Vous pouvez utiliser l’interface en ligne de commande dotnet pour répertorier les dépendances connues pour être obsolètes ou vulnérables qui pourraient se trouver dans votre projet ou solution. Vous pouvez utiliser la commande dotnet list package --deprecated ou dotnet list package --vulnerable pour obtenir une liste de toute fonction obsolète ou vulnérabilité connue. NuGetAudit peut vous avertir des dépendances vulnérables connues, activé par défaut lorsqu’une source fournit une base de données de vulnérabilités.

Dépendances GitHub vulnérables

Consommateur de package | Auteur de package

Si votre projet est hébergé sur GitHub, vous pouvez tirer profit de GitHub Security pour rechercher des failles de sécurité et des erreurs dans votre projet. Dependabot les corrigera en ouvrant une pull request sur votre base de code.

Intercepter les dépendances vulnérables avant leur introduction est l'un des objectifs du mouvement « Shift Left ». La possibilité d’avoir des informations sur les dépendances, comme leur licence, leurs dépendances transitives et l’âge des dépendances par exemple, vous aident à atteindre ce but.

Pour plus d’informations sur les alertes et les mises à jour de Dependabot, consultez la documentation suivante.

Configuration de NuGet

Consommateur de paquets 📦

Ajoutez un nuget.config fichier à la racine de votre dépôt de projet. Cette pratique est considérée comme une bonne pratique, car elle favorise la répétabilité et garantit que différents utilisateurs ont la même configuration NuGet. Nous vous recommandons d’ajouter des clear éléments pour vous assurer qu’aucune configuration spécifique de l’utilisateur ou de l’ordinateur n’est appliquée. En savoir plus sur la façon dont les paramètres sont appliqués.

Par exemple:

<configuration>
  <packageSources>
    <clear />
    <add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
  </packageSources>
  <packageSourceMapping>
    <clear />
  </packageSourceMapping>
</configuration>

Tip

Si votre organisation bloque l’accès à api.nuget.org, envisagez de demander à l’administrateur réseau d’autoriser https://data.nuget.org/v3/index.json et de le configurer en tant que source d’audit pour NuGet Audit. Ce point de terminaison sert uniquement les données de vulnérabilité, et non les packages, de sorte qu’il peut être autorisé même lorsqu’il api.nuget.org est bloqué.

Canaux NuGet

Consommateur de paquets 📦

Utilisez des sources de paquets en qui vous avez confiance. Lorsque vous utilisez plusieurs flux sources NuGet privés et publics, un package peut être téléchargé à partir de l’un de ces flux. Pour vous assurer que votre compilation est prévisible et protégée contre les attaques connues telles que la confusion de dépendances, il est une bonne pratique de savoir de quel(s) flux proviennent vos packages. Vous pouvez utiliser un flux unique ou un flux privé avec des capacités en amont de protection.

Pour plus d’informations à propos de la sécurisation des flux de paquets, consultez 3 façons d’atténuer les risques lors de l’utilisation de flux de paquets privés.

Lorsque vous utilisez un flux privé, consultez les meilleures pratiques de sécurité pour gérer les identifiants.

Stratégies de confiance client

Consommateur de paquets 📦

Il existe des politiques auxquelles vous pouvez adhérer, nécessitant que les packages que vous utilisez soient signés. Cela vous permet d’approuver un auteur de package, dès lors qu’il est signé par l'auteur, ou d’approuver un package s’il appartient à un utilisateur ou un compte spécifique signé à la fois par le référentiel et NuGet.org.

Pour configurer des stratégies de confiance client, voir la documentation suivante.

Fichier de verrouillage

Consommateur de paquets 📦

Les fichiers de verrouillage stockent le hachage du contenu de votre package. Si le code de hachage de contenu d’un package que vous souhaitez installer correspond au fichier de verrouillage, il garantit la reproductibilité du package.

Pour activer les fichiers de verrouillage, consultez la documentation suivante.

Mappage de source du package

Consommateur de paquets 📦

Le mappage de source de package vous permet de déclarer de manière centralisée la source à partir de laquelle chaque package de votre solution doit être restauré dans votre fichier nuget.config.

Pour activer le mappage de source de package, veuillez consulter la documentation suivante.

Sécuriser les ordinateurs

Permissions du répertoire

Consommateur de paquets 📦

Sur Windows, Mac et certaines distributions Linux, les répertoires de base de compte d’utilisateur sont privés par défaut. Toutefois, certaines distributions Linux rendent par défaut les répertoires utilisateur lisibles par d’autres comptes sur le même ordinateur. En outre, il existe plusieurs options de configuration pour rediriger le dossier de packages globaux NuGet et le cache HTTP vers des emplacements différents de ceux par défaut. Les solutions, projets et référentiels peuvent également être créés en dehors du répertoire de base de l’utilisateur.

Si vous utilisez des packages qui ne se trouvent pas sur nuget.org, si un autre compte sur l’ordinateur peut lire les packages globaux NuGet ou les répertoires de cache HTTP, ou le répertoire de sortie de build du projet, ces packages peuvent être divulgués à des personnes qui ne sont pas censées avoir accès à ces packages.

Sur Linux, dotnet nuget update source modifiera les autorisations du fichier nuget.config pour qu'il soit lisible uniquement par le propriétaire du fichier. Toutefois, si vous modifiez le fichier nuget.config d’une autre façon et que le fichier se trouve dans un emplacement où d’autres comptes peuvent le lire, il peut y avoir une divulgation d'informations sur l’URL source du package ou les informations d’identification de la source du package. Vous devez vous assurer qu’aucun fichier nuget.config ne peut être lu par d’autres utilisateurs du même ordinateur.

Solutions dans le répertoire des téléchargements

Consommateur de paquets 📦

Des précautions supplémentaires doivent être prises si vous travaillez sur des solutions ou des projets dans votre répertoire de téléchargements. NuGet accumulera les paramètres à partir de plusieurs fichiers de configuration, et MSBuild importera généralement Directory.Build.props, Directory.NuGet.props, Directory.Build.targets, et potentiellement d'autres fichiers, depuis tout répertoire parent jusqu'à la racine du système de fichiers.

Le dossier des téléchargements présente un risque supplémentaire, car il s’agit généralement de l’emplacement par défaut auquel les navigateurs web téléchargent les fichiers d’Internet

Agents de build

Consommateur de paquets 📦

Les agents de build (agents CI) qui ne sont pas réinitialisés à un état initial après chaque build présentent plusieurs risques qui doivent être pris en compte.

Pour en savoir plus sur les méthodes sécurisées de gestion des informations d'identification, consultez la documentation sur l’utilisation de packages à partir des flux authentifiés.

Pour en savoir plus sur la modification des répertoires dans lesquels NuGet stocke des données, consultez la documentation sur la gestion des packages globaux, du cache et des dossiers temporaires. Ces répertoires doivent être configurés sur un répertoire que l’agent CI nettoie après chaque build.

Notez que tous les packages utilisés par votre projet peuvent être laissés dans le répertoire de sortie de build de votre projet. Si votre projet utilise des packages de sources authentifiées, d’autres utilisateurs du même agent CI peuvent obtenir un accès non autorisé aux assemblys de package. Par conséquent, vous devez également nettoyer votre référentiel à la fin de votre build, même lorsque la build échoue ou est annulée.

Surveiller votre chaîne d’approvisionnement

Analyse des secrets GitHub

Auteur de pack

GitHub analyse les dépôts à la recherche de clés API NuGet pour prévenir l'utilisation frauduleuse de secrets commis par inadvertance.

Pour en savoir plus sur l’analyse des secrets, consultez À propos de l’analyse des secrets.

Signature de paquet par l'auteur

📦🖊 Auteur de package

La signature de l'auteur permet à celui-ci d'apposer son identité sur un package et au consommateur de vérifier qu'il provient bien de cet auteur. Cela vous protège contre la falsification de contenu et sert de source unique de vérité sur l’origine et l’authenticité du package. Lorsque vous combinez des stratégies de confiance client, vous pouvez vérifier qu’un package provient d’un auteur spécifique.

Pour signer un package en tant qu'auteur, consultez la section Signer un package.

Compilations reproductibles

📦🖊 Auteur du paquet

Les générations reproductibles créent des fichiers binaires identiques octet-pour-octet à chaque fois que vous le générez. Ces fichiers contiennent des liens de code source et des métadonnées du compilateur qui permettent au consommateur de package de recréer directement le fichier binaire et de vérifier que l’environnement de génération n’a pas été compromis.

Pour en savoir plus sur les assemblages reproductibles, consultez Production de paquets avec Source Link et les spécifications de Validation des assemblages reproductibles.

Authentification à 2 facteurs (2FA)

Auteur de paquet

Tous les comptes de nuget.org ont l'A2F activée. L'ajout d'une couche de sécurité supplémentaire lorsque vous vous connectez à votre compte GitHub ou à votre compte NuGet.org.

Réservation du préfixe d’ID de paquet

Auteur de paquet

Pour protéger l’identité de vos packages, vous pouvez réserver un préfixe d’ID de package avec votre espace de noms respectif pour associer un propriétaire correspondant si votre préfixe d’ID de package répond aux critères spécifiés.

Pour en savoir plus sur la réservation de préfixes d’ID, consultez Réservation de préfixe d'identifiant de package.

Dépréciation et retrait d’un package vulnérable

📦🖊Auteur du package

Pour protéger l’écosystème de package .NET, faites de votre mieux pour déprécier et retirer votre package de la liste lorsque vous avez connaissance d’une vulnérabilité dans un package que vous avez créé. Cela le masquera aux utilisateurs qui recherchent des packages. Si vous consommez un package déconseillé et retiré de la liste, vous devez éviter d’utiliser ce package.

Pour savoir comment déprécier et désinscrire un package, consultez la documentation suivante sur la dépréciation et le désinscription des packages.

Considérez également la possibilité de signaler les problèmes connus à la base de données GitHub Advisories.

Résumé

Votre chaîne d’approvisionnement logicielle représente tout ce qui passe ou affecte votre code. Même si les compromissions de la chaîne d’approvisionnement sont réelles et de plus en plus communes, elles restent encore rares. Ainsi, la chose la plus importante que vous pouvez faire est de protéger votre chaîne d’approvisionnement en connaissant vos dépendances et en les gérant , et en surveillant votre chaîne d’approvisionnement.

Vous avez appris les différentes méthodes proposées par NuGet et GitHub qui sont disponibles aujourd'hui pour visualiser, gérer et surveiller plus efficacement votre chaîne logistique.

Pour plus d’informations à propos de la sécurisation des logiciels à l'échelle mondiale, consultez « The State of the Octoverse 2020 » Rapport de sécurité .