Encore un Cas d'Utilisation de Modèles d'Exclusion dans les Dépôts Distants : Attaque par Substitution d’Espace de Noms (ou « Confusion de Dépendance »)

Exclude Patterns in Remote Repositories with JFrog Artifactory to avoid Namespace Shadowing attacks

Mise à jour : 1er juin 2021. Vous avez demandé, nous avons répondu ! Une protection encore plus simple contre les attaques par confusion de dépendance ! Lire la suite — Aller Au-Delà des Modèles d’Exclusion : Dépôts Sécurisés Avec Résolution Prioritaire.


TL;DR

Le registre npm est vulnérable aux attaques par substitution d'espaces de noms de la chaîne d'approvisionnement, également connu sous le nom d'attaques par « Confusion de Dépendance ». Assurez-vous de créer des packages npm scopés et de forcer les modèles d’exclusion.

Obsession de Longue Date avec les Modèles d’Exclusion

Je me souviens de la première formation client sur JFrog que j'ai dispensée en février 2012. Cette diapositive était celle avec laquelle j'expliquais l'importance de définir des modèles d'exclusion sur vos dépôts (quand on voit la diapositive, on sait qu'on est en 2012, n'est-ce pas ? Et puis, Ant était une chose.) :

Common Configuration Include and Exclude Patterns with JFrog Artifactory

Voici toute l'histoire : Votre entreprise, Acme, a installé JFrog Artifactory. Il dispose de l'ensemble habituel de dépôts distants (qui relaient divers dépôts centraux comme Maven Central), de dépôts locaux (qui hébergent les artefacts internes de votre entreprise) et d'un dépôt virtuel (qui regroupe les dépôts locaux et distants sous une seule URL), ce qui simplifie la configuration de votre outil de build (en 2012, nous parlerions de Maven, bien sûr).

Je leur ai dit, imaginez que vous travaillez sur un projet très secret appelé Secret Almo. Les coordonnées de l’artefact sont org.acme:secret-almo:1.0, et vous ne voulez pas que vos concurrents le sachent. Mais que se passe-t-il si l’un de vos collègues ajoute accidentellement org.acme:secret-almo:1.1 en tant que dépendance ou toute autre version inexistante de cette bibliothèque et exécute un build ? Voici ce qui va se passer :

  1. La requête arrive dans le dépôt virtuel d’Artifactory, qui (comme c’est toujours le cas) vérifie d’abord les dépôts locaux. Si votre collègue n’a pas commis l’erreur et a utilisé 1.0 comme version, la résolution s’arrêterait là et l’artefact correct serait récupéré. Mais 1.1 est introuvable, alors Artifactory continue de chercher.
  2. Artifactory examine les dépôts distants, qui font partie du dépôt virtuel, un par un, en envoyant la requête d’URL contenant le nom de votre projet secret aux dépôts tiers externes !

« Non ! » ai-je crié. « Quelle horrible négligence de la confidentialité ! Que se passe-t-il si quelqu’un voit les requêtes et découvre le Secret Almo !?! » Ce qui était un moyen approprié de motiver nos utilisateurs à utiliser des modèles d’exclusion. Était-ce vraiment un si grand danger ? J'ai des doutes, mais ça a aidé.

Nous martelons ce message à nos clients et utilisateurs depuis 2009 : Ariel Seftel en 2015 – « Définissez un modèle d’exclusion sur les dépôts distants pour empêcher Artifactory d'y rechercher des packages dont vous savez qu’ils ne peuvent pas s'y trouver », Shani Levy en 2015 à nouveau , cette fois spécifiquement sur la sécurité : « Gérez la sécurité et boostez les performances avec des modèles d’exclusion » et encore une fois, Rami Honing en 2016 – « modifiez… des modèles d'exclusion pour appliquer des stratégies de sécurité.

Le plus ancien guide utilisateur encore existant est Artifactory 2, écrit par les co-fondateurs Yoav Landman et Fred Simon en 2009, et devinez quoi ? C’est très clair :

Il est extrêmement important d’utiliser des modèles d'inclusion et d'exclusion pour les dépôts. Ceci est particulièrement important pour les dépôts distants aux fins suivantes :

  1. Éviter de rechercher des artefacts distants sur des dépôts qui ne contiendront jamais ces artefacts ou qui ne contiennent qu'une gamme limitée d'identifiants de groupe.
  2. Ne pas divulguer des informations commerciales sensibles qui peuvent être dérivées de vos requêtes d'artefacts à quiconque peut intercepter ces dernières, y compris les propriétaires du dépôt distant lui-même.

De toute évidence, la documentation actuelle insiste également là-dessus :

Meilleures pratiques utilisant un modèle d’exclusion pour les dépôts distants, pour éviter les risques de sécurité

Pour éviter d’exposer des informations commerciales sensibles comme décrit ci-dessus, nous vous recommandons vivement les meilleures pratiques suivantes :

  • La liste des dépôts distants utilisés dans une organisation doit être gérée sous un dépôt virtuel unique vers lequel sont dirigées toutes les requêtes
  • Tous les artefacts internes doivent être spécifiés dans le champ Modèle d'exclusion du dépôt virtuel (ou de chaque dépôt distant) à l’aide de caractères génériques pour encapsuler la spécification la plus large possible des artefacts internes.

Vous l'avez compris, nous sommes très attachés aux Modèles d’Exclusion. Mais pourquoi ? Est-ce vraiment parce que nous avons peur que quelqu’un de Sonatype (responsables de Maven Central) ou GitHub (responsable du Registre npm) aille examiner les journaux et découvrir Secret Almo ?! C'est vrai, mais pas seulement. Bienvenue dans la tempête parfaite…

du Circonflexe, du Bazar et du Dépôt Virtuel

Retournons dans les bureaux (aujourd'hui probablement virtuels) d’Acme, où le travail sur le Secret Almo est toujours en cours. Regardons une autre composante du projet, pas secrète du tout, peut-être une bibliothèque, almo-common-utils. Sa source pourrait même être accessible au public, si, par exemple, il s'agit d'un bundle qui fait partie des produits ou applications Web d’Acme accessibles au public, il est écrit en Node et JFrog Artifactory dispose désormais d’un ensemble de dépôts npm distants (utilisant le Registre npm comme relais), locaux (pour le partage de modules en interne) et virtuels.

Réfléchissez à ce qui suit :

  1. le Registre npm est un bazar (selon les termes de Raymond). Tout le monde peut publier une bibliothèque npm non scopée et l’appeler comme il le souhaite par ex., « almo-common-utils » (sauf s’il y a un conflit de nom).
  2. Il n’existe aucun package nommé « almo-common-utils » dans le registre npm (enfin, parce qu'il s'agit d'une bibliothèque d’entreprise interne), donc il n’y a pas de conflit de nom.
  3. La plupart des dépendances npm déclarées à l’aide d’une plage par un tilde ou un circonflexe (caret) pour demander la dernière versioncompatible, telle que définie dans la norme de Versioning Sémantique et sa mise en œuvre avec npm.

La seule information dont un attaquant a besoin pour tenter d’attaquer une organisation non protégée est l’existence d’almo-common-utils, la version principale de la bibliothèque en cours d’utilisation (disons qu’ils savent que la version 3 est largement utilisée dans l’organisation) et le contenu du code source.

Il peut cloner et modifier la source, en y intégrant un logiciel malveillant, mais en conservant la compatibilité avec le code d’origine, et la télécharger dans le Registre npm en tant que secret-almo:3.99.99, parce que personne de l'en empêchera

Regardons maintenant travailler la résolution d'Artifactory sans le modèle d’exclusion lorsque secret-almo:^3.0.0 est demandé :

  1. Recherchez les derniers secret-almo compatibles dans les dépôts locaux. Trouvé 3.2.4.
  2. Recherchez le dernier secret-almo compatible dans le dépôt distant proxy npm-registry. Trouvé 3.99.99.
  3. Le faux secret-almo du registre npm gagne et la chaîne d’approvisionnement est piratée.

Rappelez-vous que j’ai crié « Nix ! » Il s’agit d’un double non. Et d'un ouille.

Mais c’est là qu’un développeur Node.js expérimenté se lèverait et dirait…

Et les packages scopés !

Souvenez-nous que j'ai affirmé que n’importe qui peut télécharger n’importe quoi dans le Registre npm. Eh bien, pas tout à fait. Si vous créez une organisation dans le Registre npm, un espace de noms vous sera attribué, vers lequel seuls les membres de votre organisation peuvent télécharger (c’est ce que npm appelle les packages scopés publics). Cela vous évite-t-il l’attaque par Substitution d'Espace de Noms ? Oui, si c'est bien fait.

Tout d’abord, la société doit créer l’organisation et réserver l’espace de noms, car comme tout dans le Registre npm, ils sont à prendre. Si votre organisation ne l’a pas réservé, une attaque plus sophistiquée pourrait toujours réussir : maintenant, l’attaquant doit espérer qu’un développeur inexpérimenté trouvera un package avec un scope familier dans le Registre npm (« hey, regarde, il y a un @acme/almo-common-utils ici, il est sûrement à nous ») et décider de l’utiliser. En outre, même les membres de l’organisation officielle peuvent toujours être négligents et publier des packages non scopés.

La solution ? Vous la connaissez maintenant…

Deux règles simples pour éviter une attaque par Substitution d'Espace de Noms (ou « Confusion de Dépendance »)

  1. Publiez uniquement des packages scopés ! Enregistrez une organisation officielle pour votre entreprise dans le Registre npm. Publiez toujours uniquement des packages scopés publics. Par ailleurs, cela simplifie également les modèles d’exclusion (voir la règle suivante), car maintenant, il vous suffit d'exclure .npm/@acme/*, pour exclure tous les packages de la recherche dans les dépôts distants.
  2. Utilisez des modèles d’exclusion sur vos dépôts distants ! Vous savez pertinemment que almo-common-utils ne serait jamais trouvé dans le Registre npm ? Dites-le à votre gestionnaire de dépôts ! Ajoutez vos dépendances privées dans les modèles d'exclusion et protégez-vous d’une attaque sérieuse (et assez intelligente) de la chaîne d’approvisionnement. c’est tellement facile que ne pas le faire serait réellement une négligence.

Nous allons finir avec…

la FAQ de Votre Avocat du Diable

Q : Les attaques par Substitution d'Espace de Noms (ou ou « Confusion de Dépendance ») constituent-elles un problème de sécurité uniquement si j’utilise Artifactory ?

R : Tout gestionnaire de dépôts qui permet une combinaison de dépôts locaux et relayés sous une seule URL peut être attaqué de la même manière.  La réponse est donc non, il ne s'agit pas d'un problème de sécurité lié à Artifactory. On peut inclure Sonatype Nexus, et d’autres. Ce n’est pas parce qu’ils présentent des failles, car ils fonctionnent précisément comme prévu. Et tous ont et recommandent fortement l’utilisation de meilleures pratiques similaires aux modèles d'exclusion (par exemple, les Règles de Routage dans Sonatype Nexus).

Q : Pourquoi les utilisateurs n’utilisent-ils pas de packages scopés publics ? N’est-ce pas la voie à suivre ?

R : C’est clairement la voie à suivre. Mais npm n'a introduit les packages scopés que dans la version 2 et ce n'est pas aussi courant dans le secteur que cela devrait l'être (du moins à l'heure actuelle). Mais vous ? Vous êtes à la page, alors vous les utilisez, non ?

Q : Pourquoi le Registre npm n’impose-t-il pas des packages scopés par des propriétaires vérifiés pour éviter les attaques par substitution d’espace de noms ?

R : C’est une très bonne question.