Aucune chaîne d'approvisionnement logiciel n'est plus forte que son maillon le plus faible. La connexion continue et les mises à jour régulières des logiciels modernes a considérablement élargi leur chaîne d'approvisionnement et, par la même occasion, les risques de sécurité.
Les stratégies d’attaques employées par les cybercriminels
Une attaque de la chaîne d'approvisionnement logiciel peut prendre plusieurs formes, notamment lorsque des acteurs malveillants s'attaquent à des composants logiciels tiers. Ces derniers n’étant pas créés et maintenus par le fabricant principal du logiciel et se trouvant dans un registre centralisé. Les cybercriminels exploitent les défauts de conception et les faiblesses de ces composants tiers pour introduire du code malveillant (soit directement dans la source consommée, soit indirectement, par le biais d'une contrainte de l'arbre de dépendances). Ils peuvent alors accéder aux systèmes internes et aux utilisateurs finaux. Les sources centralisées ne sont pas les seules à être vulnérables : les sources décentralisées de composants tiers peuvent aussi être attaquées. Avec, par exemple, une attaque par flux d'événements sur un portefeuille de crypto-monnaies.
Tout comme l'attaque d'un cloud public permet aux acteurs malveillants de frapper plusieurs entreprises à la fois, le fait de cibler une chaîne d'approvisionnement de logiciel leur permet de compromettre un large éventail d’entreprises en une seule fois.
Ces attaques ne sont pas un phénomène récent, mais elles présentent des risques croissants. En effet, afin de maintenir un rythme de développement rapide, les développeurs de logiciels ne codent plus eux-mêmes les fonctionnalités mais assemblent les applications en combinant code propriétaire et code en open source. Ainsi, les dépôts de code sont souvent constitués non seulement de code propriétaire mais aussi de packages open source, de containers, d'infrastructures en tant que code (IaC) et même de configurations de construction. Chacun de ces éléments constitue un vecteur d'attaque potentiel dans la chaîne d'approvisionnement des logiciels.
Les développeurs sont les premiers défenseurs de la sécurité des logiciels
La première étape consiste à se défendre contre les attaques par confusion de dépendances : un processus par lequel un logiciel malveillant est déployé au sein du réseau d'une entreprise en remplaçant des packages utilisés à titre privé par des packages publics malveillants qui utilisent le même nom. Dans la chaîne d'approvisionnement logiciel, les packages open source sont automatiquement récupérés par les développeurs, à l'aide de gestionnaires de packages et d'outils de construction. Si ces derniers ne sont pas configurés pour récupérer uniquement les packages du registre privé, des packages portant le même nom peuvent être récupérés dans un dépôt de code public. Le cybercriminel n’aura alors plus qu’à analyser le dépôt public d'une entreprise à la recherche de noms de packages privés et télécharger un package malveillant portant un nom identique. Les processus de construction automatisés feront le reste et téléchargeront le package malveillant au lieu du package prévu, créé en interne.
Pour éviter cette attaque, les développeurs doivent utiliser la portée des espaces de nom (ou “namespaces”) dans leur travail. La portée des packages verrouillent l'espace de nom du package et l'associent à un utilisateur ou à une entreprise spécifique, ce qui empêche sa substitution. Une autre tactique consiste à utiliser une configuration spécifique au dépôt et définir explicitement le registre en amont, afin de donner aux gestionnaires de package comme pip et npm des indications explicites pour qu'ils ne consultent pas le registre public pour trouver une version plus récente du package et qu'ils ne tirent pas accidentellement un package malveillant.
Une autre mesure que les développeurs devraient prendre est de désactiver les commandes d'installation arbitraires des packages open source. Par défaut, certains gestionnaires permettent à tout package en cours d'installation ou de désinstallation d'exécuter des commandes arbitraires, exposant ainsi les entreprises aux attaques de typosquattage et aux mécanismes de porte dérobée cachés. La solution consiste à s'assurer que les packages sont rigoureusement contrôlés avant leur installation et ne sont pas ajoutés au hasard ou par le biais d'un copier-coller peu sûr. L'authentification à deux facteurs est également cruciale. 2FA est un moyen simple de protéger les comptes qui accèdent aux registres et aux écosystèmes, mais en janvier 2020, moins de 10 % des développeurs sur npmjs avaient 2FA activé. Il est vital que tous les développeurs activent cette fonctionnalité car dans la communauté open source, la sécurité des uns impacte celles des autres.
La sécurité est une préoccupation importante lorsque l'on collabore ouvertement et que l'on s'engage dans un logiciel open source, car cela augmente le risque de fuite ou de partage accidentel d'informations confidentielles. Pour éviter cette exposition potentielle des données, les développeurs doivent éviter de stocker d'informations sensibles dans un référentiel, dans la configuration ou le code. Et ils devraient également éviter de publier des packages ou des images Docker contenant des informations potentiellement sensibles.
Les chaînes d'approvisionnement logiciel permettent le développement rapide, mais cette vitesse comporte des risques. Les composants logiciels tiers sont des vecteurs d'attaque attrayants pour les acteurs malveillants et, sans un plan de protection minutieux, les développeurs peuvent mettre en danger leurs entreprises. En identifiant et en corrigeant les faiblesses de la chaîne d'approvisionnement, et en adoptant des bonnes pratiques en matière de sécurité, les développeurs peuvent se protéger eux-mêmes ainsi que la communauté des développeurs.