Maison >développement back-end >Golang >Comprendre les vulnérabilités d'injection de commandes dans Go

Comprendre les vulnérabilités d'injection de commandes dans Go

DDD
DDDoriginal
2024-11-26 00:49:14644parcourir

Les développeurs Go peuvent avoir besoin d'utiliser des commandes système pour divers scénarios, tels que la manipulation d'images, où ils doivent traiter ou redimensionner des images ou exécuter des commandes système pour gérer des ressources ou collecter des métriques ou des journaux.

À d’autres moments, vous construisez peut-être un nouveau système dans Go qui doit s’interfacer avec les systèmes existants. Cette interface s'appuie sur l'exécution de commandes système et le traitement de leur sortie.

Dans les deux cas, il est essentiel de suivre les conventions de codage sécurisé lors de la génération de commandes système, car cela pourrait conduire à une vulnérabilité de sécurité connue sous le nom d'injection de commandes.

Qu’est-ce que l’injection de commandes ?

L'injection de commandes est une vulnérabilité de sécurité lorsqu'une application transmet des données dangereuses fournies par l'utilisateur (telles que les entrées d'un formulaire Web) à un shell système. Cette faiblesse permet à un attaquant d'exécuter des commandes arbitraires sur le système d'exploitation hôte sous le même utilisateur de l'application.

Dans Go, une injection de commande implique souvent l'utilisation du package os/exec pour générer des commandes système.

Considérez l'exemple de code Go suivant :

func handler(req *http.Request) {
  cmdName := req.URL.Query()["cmd"][0]
  cmd := exec.Command(cmdName)
  cmd.Run()
}

Dans cet extrait de code, le cmdName est extrait directement des paramètres de requête de la requête et utilisé pour construire une commande qui est exécutée sur le serveur. Il s'agit d'un exemple classique de vulnérabilité d'injection de commande, car un attaquant peut manipuler la valeur de la chaîne de requête cmd pour exécuter n'importe quelle commande de son choix, compromettant potentiellement le serveur.

Un attaquant pourrait créer une requête avec une commande malveillante, telle que :

http://example.com/execute?cmd=rm%20-rf%20/

Pourquoi l’injection commandée est-elle dangereuse ? L'injection de commandes est dangereuse car elle permet aux attaquants d'exécuter des commandes arbitraires sur le serveur, ce qui peut entraîner de graves conséquences, notamment :

  • Violation de données : les attaquants peuvent accéder aux données sensibles stockées sur le serveur. Imaginez-les accéder à des fichiers de configuration tels que config.toml et d'autres qui répertorient les ressources et les informations d'identification.
  • Compromission du système : les attaquants peuvent prendre le contrôle du serveur, conduisant ainsi à une exploitation ultérieure. Cela prend souvent la forme de mouvements latéraux au sein d'un système compromis et d'actions de découverte d'autres serveurs qui pourraient être compromis.
  • Perturbation du service : les attaquants peuvent exécuter des commandes qui perturbent les services, provoquant des temps d'arrêt. En fait, cela pourrait directement se traduire par des pertes financières et des risques commerciaux dus à une attaque par déni de service.

L'impact d'une attaque réussie par injection de commandes peut être dévastateur, affectant non seulement le système compromis, mais également la réputation de l'organisation et la confiance des clients.

Exécution de processus vulnérables et injection de commandes dans Go

Les développeurs Go, connus pour leur préférence pour la simplicité et les performances, peuvent choisir d'intégrer des commandes système pour exploiter les capacités de ces utilitaires. Cette approche leur permet de se concentrer sur la création d’applications robustes sans réinventer la roue. Cependant, cette intégration comporte son lot de défis, notamment en termes de sécurité.

Pour illustrer un scénario plus réaliste, considérons une application Go qui traite les fichiers image à l'aide d'un utilitaire de ligne de commande tel que convert.

Nous explorons une application Go conçue pour gérer les demandes de redimensionnement d'images. L'application utilise le framework Web Gin pour définir un point de terminaison POST, /cloudpawnery/image, qui traite le redimensionnement de l'image en fonction des entrées de l'utilisateur. Ce point de terminaison accepte des paramètres tels que tenantID, fileID et fileSize à partir de la chaîne de requête. Le paramètre fileSize est facultatif et sa valeur par défaut est "200" s'il n'est pas fourni.

L'extrait de code suivant démontre une implémentation vulnérable dans Go.

func handler(req *http.Request) {
  cmdName := req.URL.Query()["cmd"][0]
  cmd := exec.Command(cmdName)
  cmd.Run()
}

La fonction downloadAndResize construit une chaîne de commande pour redimensionner l'image à l'aide de convert et l'exécute à l'aide de exec.CommandContext.

Comment la fonction downloadAndResize construit-elle une chaîne de commande ? Il prend cette entrée en utilisant fileSize fourni par l'utilisateur. Cette chaîne est ensuite exécutée, permettant potentiellement à un attaquant d'injecter des commandes malveillantes. Pour atténuer ce risque, les développeurs Go doivent valider et nettoyer toutes les entrées utilisateur, utiliser des commandes paramétrées et tirer parti de pratiques de sécurité qui gèrent en toute sécurité l'exécution des commandes.

Atténuation des vulnérabilités d’injection de commandes

Dans le développement Go, comme dans tout autre langage, il est primordial de garantir que votre code est sécurisé contre les vulnérabilités d’injection de commandes. L'injection de commandes se produit lorsqu'un attaquant peut exécuter des commandes arbitraires sur l'hôte, ce qui peut entraîner un accès non autorisé, des violations de données et d'autres problèmes de sécurité graves.

Explorons quelques bonnes pratiques pour atténuer ces risques.

Validation et assainissement des entrées

L'une des étapes fondamentales pour empêcher l'injection de commandes est une validation et un assainissement rigoureux des entrées. Dans l'exemple fourni, la fonction downloadAndResize construit une chaîne de commande à l'aide d'entrées fournies par l'utilisateur telles que fileSize. Si ces entrées ne sont pas correctement validées, un attaquant pourrait injecter des commandes malveillantes.

Voici comment améliorer la validation des entrées :

  1. Entrées de la liste verte : définissez un ensemble de valeurs acceptables pour les entrées telles que fileSize. Par exemple, n'autorisez que les valeurs numériques qui se situent dans une plage raisonnable.
  2. Désinfecter les entrées : supprimez ou échappez tous les caractères potentiellement dangereux des entrées utilisateur. Cela peut inclure des métacaractères shell tels que ;, |, &, etc. Il est préférable de coder en dur la commande et de ne pas autoriser les entrées de l'utilisateur à la contrôler.
  3. Utilisez des types stricts : convertissez les entrées dans le type de données attendu dès que possible. Par exemple, convertissez fileSize en entier et validez sa plage.

Voici un exemple de la façon dont vous pourriez mettre en œuvre ces pratiques :

func handler(req *http.Request) {
  cmdName := req.URL.Query()["cmd"][0]
  cmd := exec.Command(cmdName)
  cmd.Run()
}

 Même encore, nous pouvons faire beaucoup mieux pour sécuriser le code Go contre l'injection de commandes. Continuez à lire !

Utilisation d'API ou de bibliothèques sécurisées au lieu de commandes système

Une autre stratégie efficace consiste à éviter d'exécuter directement les commandes système autant que possible. Au lieu de cela, exploitez des API ou des bibliothèques sécurisées qui fournissent les fonctionnalités requises sans exposer votre application aux risques d’injection de commandes.

Par exemple, si votre application doit manipuler des images, envisagez d'utiliser une bibliothèque Go comme github.com/disintegration/imaging au lieu d'appeler une commande externe comme convert depuis la bibliothèque logicielle ImageMagick. Cette approche encapsule la fonctionnalité dans l'environnement de type sécurisé de Go, réduisant ainsi la surface d'attaque.

http://example.com/execute?cmd=rm%20-rf%20/

En utilisant des bibliothèques telles que l'imagerie dans Go, vous éliminez le besoin de construire et d'exécuter des commandes shell, atténuant ainsi le risque d'injection de commandes. Néanmoins, dans certaines bibliothèques et écosystèmes linguistiques, il est possible que le package tiers soit un simple wrapper autour de l'exécution de commandes, il est donc obligatoire de revoir le code pour de telles opérations sensibles.

Refactoriser la fonction vulnérable downloadAndResize pour empêcher l'injection

Dans l'exemple précédent, nous avons démontré une application Go potentiellement vulnérable qui utilise la fonction exec.CommandContext pour exécuter des commandes shell. Cette approche peut conduire à des vulnérabilités d’injection de commandes, comme nous l’avons noté.

Essayons de refactoriser la fonction downloadAndResize pour garantir que les entrées de l'utilisateur ne conduisent pas à l'exécution arbitraire de commandes.

Un moyen efficace d'empêcher l'injection de commandes consiste à éviter de construire des chaînes de commandes shell directement à partir de l'entrée de l'utilisateur. Au lieu de cela, nous pouvons utiliser la fonction exec.Command avec des arguments séparés, ce qui permet de transmettre en toute sécurité les entrées de l'utilisateur en tant que paramètres à la commande sans appeler le shell et sans permettre aux utilisateurs de contrôler la commande réelle.

Voici une version refactorisée de la fonction downloadAndResize qui corrige la vulnérabilité d'injection de commande :

func handler(req *http.Request) {
  cmdName := req.URL.Query()["cmd"][0]
  cmd := exec.Command(cmdName)
  cmd.Run()
}

Dans ce refactor, nous avons séparé la commande de ses arguments. En utilisant exec.CommandContext avec des arguments séparés, nous évitons d'avoir à construire une chaîne de commande shell. Cette méthode garantit que les entrées de l'utilisateur sont traitées comme des données plutôt que comme du code exécutable, réduisant considérablement le risque d'injection de commandes.

Nous avons également supprimé le besoin d’invocation du shell. Le code refactorisé n'appelle pas le shell (sh -c), qui est un vecteur courant pour l'injection de commandes. Au lieu de cela, il appelle directement l'utilitaire de conversion avec les arguments spécifiés.

Tirer parti de Snyk pour la sécurité du code

Snyk Code est un puissant outil d'analyse statique qui aide les développeurs à identifier et à corriger les vulnérabilités de leur base de code. Il s'intègre parfaitement à votre IDE et à votre flux de développement, fournissant des commentaires en temps réel sur les problèmes de sécurité potentiels.

Comment Snyk peut aider à identifier les vulnérabilités d'injection de commandes dans Go

Dans l'exemple Go fourni, la fonction downloadAndResize construit une commande shell à l'aide de l'entrée fournie par l'utilisateur :

http://example.com/execute?cmd=rm%20-rf%20/

Ce code est vulnérable à l'injection de commandes car il intègre directement la saisie de l'utilisateur dans la chaîne de commande.

Et si votre équipe comptait des développeurs qui n'étaient pas au courant des vulnérabilités d'injection de commandes ?

Seriez-vous facilement en mesure d'identifier le flux d'appels d'analyse statique inter-fichiers lors d'une revue de code pour trouver cette vulnérabilité d'injection de commandes ?

C'est là qu'intervient Snyk.

Découvrez comment la sécurité des applications devient simple grâce à l'extension Snyk Code qui met en évidence le code vulnérable en temps réel dans l'éditeur VS Code :

Understanding command injection vulnerabilities in Go
Snyk peut vous aider à identifier de telles vulnérabilités en analysant votre code Go et en signalant les cas où les entrées utilisateur sont utilisées de manière dangereuse dans les commandes shell. Snyk vous montre de véritables commits effectués par d'autres projets open source qui ont atténué cette vulnérabilité spécifique afin que vous obteniez plusieurs références de code comme exemples de ce à quoi « ça ressemble ».

Plus encore, si vous cliquez sur l'onglet VUE D'ENSEMBLE DU PROBLÈME, vous obtenez un aperçu plus détaillé et les meilleures pratiques pour la prévention de l'injection de commandes. Cet onglet fournit des informations détaillées et des recommandations sur la manière d'atténuer ces risques. Il est disponible directement dans la vue IDE pendant que vous codez et peut suivre ces actions sans changement de contexte coûteux :

Understanding command injection vulnerabilities in Go
Pour en savoir plus sur la façon de sécuriser votre code contre de telles vulnérabilités, envisagez d'installer l'extension Snyk Code IDE et de connecter vos projets Git pour identifier et résoudre les problèmes de sécurité dans vos applications Go. Vous pouvez le faire facilement et gratuitement en vous inscrivant pour commencer à analyser votre code à la recherche de vulnérabilités.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn