Bogues JavaScript en abondance dans l’écosystème Node.js – détectés automatiquement – Naked Security

Voici un article intéressant de la récente conférence USENIX 2022 : Mining Node.js Vulnérabilités via Object Dependence Graph et Query.

Nous allons tricher un peu ici en ne creusant pas et en n’expliquant pas la recherche de base présentée par les auteurs de l’article (certaines mathématiques et la connaissance de la notation sémantique opérationnelle sont souhaitables lors de sa lecture), qui est une méthode pour le statique analyse du code source qu’ils appellent ODGEN, abréviation de Générateur de graphique de dépendance d’objet.

Au lieu de cela, nous voulons nous concentrer sur les implications de ce qu’ils ont pu découvrir dans l’écosystème JavaScript Node Package Manager (NPM), en grande partie automatiquement, en utilisant leurs outils ODGEN dans la vie réelle.

Un fait important ici est, comme nous l’avons mentionné ci-dessus, que leurs outils sont destinés à ce qu’on appelle analyse statique.

C’est là que vous visez à examiner le code source pour les erreurs de codage probables (ou réelles) et les failles de sécurité sans l’exécuter du tout.

Le tester en l’exécutant est un processus beaucoup plus long qui prend généralement plus de temps à mettre en place et plus longtemps à faire.

Comme vous pouvez l’imaginer, cependant, ce qu’on appelle analyse dynamique – en fait, la construction du logiciel afin que vous puissiez l’exécuter et l’exposer à des données réelles de manière contrôlée – donne généralement des résultats beaucoup plus approfondis, et est beaucoup plus susceptible d’exposer des bogues mystérieux et dangereux que de simplement “le regarder attentivement et deviner comment cela fonctionne .” “.

Mais l’analyse dynamique prend non seulement du temps, mais est également difficile à bien faire.

Par cela, nous voulons vraiment dire que les tests de logiciels sont dynamiques très facile à mal faire, même si vous passez une éternité à la tâche, car il est facile de se retrouver avec un nombre impressionnant de tests qui ne sont pourtant pas aussi variés que vous le pensiez, et que votre logiciel est presque certain de réussir, quoi qu’il arrive. Les tests dynamiques de logiciels finissent parfois par ressembler à un enseignant qui pose les mêmes questions d’examen année après année, de sorte que les étudiants qui se sont entièrement concentrés sur la pratique des «dissertations antérieures» finissent par faire aussi bien que les étudiants qui maîtrisent véritablement le sujet.

Un réseau hétéroclite de dépendances de la chaîne d’approvisionnement

Dans les énormes écosystèmes de code source logiciel d’aujourd’hui, dont les référentiels open source mondiaux tels que NPM, PyPI, PHP Packagist et RubyGems sont des exemples bien connus, de nombreux produits logiciels s’appuient sur de vastes collections de packages d’autres personnes, formant un réseau d’approvisionnement complexe et hétérogène. dépendances en chaîne.

Implicite dans ces dépendances, comme vous pouvez l’imaginer, est une dépendance sur chaque suite de tests dynamiques fournie par chaque paquet sous-jacent – et ces tests individuels ne tiennent généralement pas (en fait, ne peuvent pas) prendre en compte la façon dont tous les paquets interagiront lorsqu’ils sont combinés pour former votre propre application unique.

Ainsi, bien que l’analyse statique en elle-même ne soit pas vraiment adéquate, elle reste un excellent point de départ pour analyser les référentiels de logiciels à la recherche de trous flagrants, notamment parce que l’analyse statique peut être effectuée “hors ligne”.

En particulier, vous pouvez analyser régulièrement et systématiquement tous les packages de code source que vous utilisez, sans avoir besoin de les intégrer dans des programmes en cours d’exécution, et sans avoir besoin de proposer des scripts de test crédibles qui obligent ces programmes à s’exécuter de différentes manières réalistes.

Vous pouvez même analyser des référentiels de logiciels entiers, y compris des packages que vous n’aurez peut-être jamais besoin d’utiliser, afin de secouer le code (ou d’identifier les auteurs) dont vous n’êtes pas enclin à faire confiance au logiciel avant même de l’essayer.

Mieux encore, certains types d’analyse statique peuvent être utilisés pour rechercher dans tous vos logiciels des bogues causés par des erreurs de programmation similaires que vous venez de trouver via une analyse dynamique (ou qui ont été signalées via un système de primes de bogues) dans une seule partie d’un seul logiciel produit.

Par exemple, imaginez un rapport de bogue du monde réel venu de la nature basé sur un endroit spécifique de votre code où vous avez utilisé un style de codage qui a provoqué un use-after-free erreur de mémoire.

UN use-after-free est le moment où vous êtes certain d’en avoir fini avec un certain bloc de mémoire et de le rendre pour qu’il puisse être utilisé ailleurs, mais ensuite oubliez qu’il ne vous appartient plus et continuez à l’utiliser quand même. Comme rentrer accidentellement du travail à votre ancienne adresse des mois après avoir déménagé, juste par habitude, et vous demander pourquoi il y a une voiture bizarre dans l’allée.

Si quelqu’un a copié et collé ce code bogué dans d’autres composants logiciels du référentiel de votre entreprise, vous pourrez peut-être le trouver avec une recherche de texte, en supposant que la structure globale du code a été conservée et que les commentaires et les noms de variable n’ont pas été Ça n’a pas trop changé.

Mais si d’autres programmeurs suivaient simplement le même idiome de codage, peut-être même en réécrivant le code défectueux dans un langage de programmation différent (dans le jargon, de sorte qu’il était lexicalement différent)…

… alors la recherche de texte serait presque inutile.

Ne serait-ce pas pratique ?

Ne serait-il pas pratique de pouvoir rechercher de manière statique dans toute votre base de code les erreurs de programmation existantes, en vous basant non pas sur des chaînes de texte, mais plutôt sur des fonctionnalités telles que le flux de code et les dépendances de données ?

Eh bien, dans l’article USENIX dont nous discutons ici, les auteurs ont tenté de créer un outil d’analyse statique qui combine un certain nombre de caractéristiques de code différentes dans une représentation compacte indiquant “comment le code transforme ses entrées en sorties, et quelles autres parties du code arrivent à influencer les résultats.

Le processus est basé sur les graphiques de dépendance d’objet mentionnés ci-dessus.

Extrêmement simplifiée, l’idée est d’étiqueter le code source de manière statique afin que vous puissiez dire quelles combinaisons de code et de données (objets) utilisées à un moment donné peuvent affecter les objets qui seront utilisés plus tard.

Ensuite, il devrait être possible de rechercher des comportements de code connus comme étant mauvais – sentdans le jargon – sans avoir réellement besoin de tester le logiciel dans une exécution en direct, et sans avoir besoin de se fier uniquement à la correspondance de texte dans la source.

En d’autres termes, vous pourrez peut-être détecter si le codeur A a produit un bogue similaire à celui que vous venez de trouver du codeur B, que A ait littéralement copié le code de B, suivi les conseils erronés de B ou simplement choisi les mêmes mauvaises habitudes de travail. comme B

En gros, une bonne analyse statique du code, malgré le fait qu’elle ne surveille jamais le logiciel en cours d’exécution dans la vie réelle, peut aider à identifier une mauvaise programmation dès le début, avant d’injecter dans votre propre projet des bogues qui pourraient être subtils (ou rares) assez dans la vraie vie pour qu’ils n’apparaissent jamais, même lors de tests en direct approfondis et rigoureux.

Et c’est l’histoire que nous avons voulu vous raconter au départ.

300 000 colis ont été traités

Les auteurs de l’article ont appliqué leur système ODGEN à 300 000 packages JavaScript du référentiel NPM pour filtrer ceux que leur système suggéré pourrait contenir des vulnérabilités.

Parmi ceux-ci, ils ont conservé des packages avec plus de 1000 téléchargements hebdomadaires (il semble qu’ils n’aient pas eu le temps de traiter tous les résultats) et ont déterminé par un examen plus approfondi les packages dans lesquels ils pensaient avoir découvert un bogue exploitable.

Dans ceux-ci, ils ont découvert 180 bogues de sécurité nuisibles, dont 80 vulnérabilités d’injection de commande (c’est là que des données non fiables peuvent être transmises dans des commandes système pour obtenir des résultats indésirables, y compris généralement l’exécution de code à distance), et 14 autres bogues d’exécution de code.

Parmi ceux-ci, 27 ont finalement reçu des numéros CVE, les reconnaissant comme des failles de sécurité “officielles”.

Malheureusement, tous ces CVE datent de 2019 et 2020, car la partie pratique du travail dans cet article a été réalisée il y a plus de deux ans, mais elle n’a été rédigée que maintenant.

Néanmoins, même si vous travaillez dans un environnement moins raréfié que ne le semblent les universitaires (pour la plupart des intervenants actifs en cybersécurité, lutter contre les cybercriminels d’aujourd’hui signifie terminer toutes les recherches que vous avez effectuées dès que possible afin de pouvoir les utiliser immédiatement)…

… si vous recherchez des sujets de recherche pour lutter contre les attaques de la chaîne d’approvisionnement dans les référentiels de logiciels à grande échelle d’aujourd’hui, ne négligez pas l’analyse de code statique.

La vie dans le vieux chien encore

L’analyse statique est tombée en disgrâce ces dernières années, notamment parce que les langages dynamiques populaires comme JavaScript rendent le traitement statique extrêmement difficile.

Par exemple, une variable JavaScript peut être un entier à un moment donné, puis se voir «ajouter» une chaîne de texte parfaitement légalement bien qu’incorrectement, la transformant ainsi en une chaîne de texte, et pourrait plus tard se retrouver comme un autre type d’objet.

Et une chaîne de texte générée dynamiquement peut se transformer comme par magie en un nouveau programme JavaScript, compilé et exécuté au moment de l’exécution, introduisant ainsi un comportement (et des bogues) qui n’existaient même pas lorsque l’analyse statique a été effectuée.

Mais cet article suggère que, même pour les langages dynamiques, une analyse statique régulière des référentiels sur lesquels vous comptez peut toujours vous aider énormément.

Les outils statiques peuvent non seulement trouver des bogues latents dans le code que vous utilisez déjà, même en JavaScript, mais aussi vous aider à juger de la qualité sous-jacente du code dans tous les packages que vous envisagez d’adopter.


EN SAVOIR PLUS SUR LA PRÉVENTION DES ATTAQUES DE LA CHAÎNE D’APPROVISIONNEMENT

Ce podcast présente un expert Sophos Chester Wisniewskichercheur principal chez Sophos, et il regorge de conseils utiles et pratiques pour faire face aux attaques de la chaîne d’approvisionnement, basés sur les leçons que nous pouvons tirer des attaques géantes du passé, telles que Kaseya et SolarWinds.

Si aucun lecteur audio n’apparaît ci-dessus, écoutez directement sur Soundcloud.
Vous pouvez également lire l’intégralité du podcast sous forme de transcription complète.


.

Leave a Comment

Your email address will not be published. Required fields are marked *