Maison >développement back-end >Golang >Comprendre les vulnérabilités d'injection de commandes dans Go
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.
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 :
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.
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.
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.
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 :
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 !
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.
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.
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.
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 :
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 :
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!