Comment utiliser correctement l'analyse statique

De plus en plus de gens parlent de l'analyse statique pour rechercher les vulnérabilités comme étape nécessaire du développement. Cependant, beaucoup parlent des problèmes de l'analyse statique. Nous en avons beaucoup parlé lors des Positive Hack Days , et sur la base des résultats de ces discussions, nous avons déjà écrit sur le fonctionnement de l' analyseur statique. Si vous avez essayé un outil sérieux, vous pourriez être effrayé par de longs rapports avec des recommandations déroutantes, des difficultés de configuration de l'outil et des faux positifs. Une analyse statique est-elle donc toujours nécessaire?

Notre expérience suggère ce qui est nécessaire. Et bon nombre des problèmes qui se posent lorsque vous regardez l'outil pour la première fois, il est tout à fait possible de les résoudre. J'essaierai de vous dire ce que l'utilisateur peut faire et à quoi devrait ressembler l'analyseur pour que son utilisation soit utile et n'introduise pas "un autre outil inutile dont le personnel de sécurité a besoin".


À propos de l'analyse statique


Nous avons donc déjà parlé des limites théoriques de l'analyse statique. Par exemple, une analyse statique approfondie tente de résoudre des problèmes de complexité exponentielle. Par conséquent, chaque outil recherche un compromis entre le temps qu'il faut, les ressources dépensées, le nombre de vulnérabilités trouvées et le nombre de faux positifs.

Pourquoi avons-nous besoin d'une analyse approfondie? Tout IDE trouve très rapidement des erreurs, parfois même liées à la sécurité - quels sont généralement les problèmes exponentiels? Un exemple classique est l'injection SQL (et toute autre injection, comme XSS, RCE et similaires), qui passe par plusieurs fonctions (c'est-à-dire que la lecture des données de l'utilisateur et l'exécution de la requête se produisent dans différentes fonctions). Sa recherche nécessite une analyse interprocédurale du flux de données, ce qui est une tâche de complexité exponentielle. D'accord, sans rechercher de telles vulnérabilités, l'analyse ne peut pas être considérée comme approfondie. Pour la même raison, vous devez analyser le code dans son intégralité, et non en partie - sinon des vulnérabilités interprocédurales pourraient être manquées.

Ces dernières années, j'ai acquis beaucoup d'expérience dans la communication avec les clients (potentiels) de divers analyseurs statiques. En particulier, nous discutons des revendications sur les outils en fonction des résultats de la première utilisation (pilote). La plupart des revendications découlent d'une manière ou d'une autre des limites théoriques de la technologie. De plus, les outils peuvent tout simplement ne pas avoir les fonctionnalités dont l'utilisateur a besoin. Cependant, à mon avis, les analyseurs peuvent se déplacer (et se déplacent) vers l'utilisateur en termes de résolution des problèmes indiqués ci-dessous. Mais vous devez également pouvoir utiliser des analyseurs, niveler les conséquences des mêmes problèmes - il s'avère que ce n'est pas si difficile. Allons dans l'ordre.

Vous pouvez imaginer une situation de modèle: vous décidez d'essayer la technologie en action ou choisissez un analyseur statique - passez un pilote. Bien sûr, vous ne faites pas confiance aux cas de test du fournisseur et vous voulez essayer d'analyser votre code (en même temps, vous pouvez trouver de vraies vulnérabilités et les corriger). Vous disposez d'un programme d'installation ou d'une machine virtuelle terminée avec un système pendant une courte période.

Exécuter l'analyse


Vous devez d'abord exécuter l'analyse. Vous accédez à l'interface, et tout semble clair: téléchargez l'archive avec le code source dans le formulaire et cliquez sur «analyser». Mais non: vous obtenez plusieurs formulaires avec des champs différents qui doivent être remplis d'une manière ou d'une autre. Il est nécessaire de spécifier les langages de programmation, certains paramètres de l'analyseur, de sélectionner les packages de vulnérabilités (comment savez-vous ce qui en fait partie?), Etc. Vous passez ce test et l'analyse commence. Ah, non - une erreur d'analyse. "Le format ne répond pas aux exigences", "Un assemblage de code est requis pour cette langue", "Les fichiers à scanner n'ont pas été trouvés" ... Si vous n'avez pas écrit ce code vous-même, vous devrez toujours vous adresser aux développeurs pour obtenir de l'aide.


Le développeur remet le code source pour les tests

Une attention particulière est accordée aux exigences du code du bâtiment. La plupart des analyseurs pour un certain nombre de langages nécessitent que le code soit collecté lors de l'analyse (langages JVM - Java, Scala, Kotlin et similaires, C / C ++, Objective-C, C #). Vous comprenez à quel point c'est pénible: reproduire l'environnement d'un grand projet pour l'assemblage sur une nouvelle machine. En revanche, ces exigences sont justifiées, elles découlent de la technologie d'analyse et des spécificités de ces langages.

Comment les analyseurs résolvent-ils ces problèmes? Tout d'abord, ils rendent le lancement de l'analyse aussi automatisé que possible. Idéalement, il suffit de télécharger un fichier de n'importe quel format, et l'analyseur lui-même doit comprendre quelles langues sont là, comment essayer de construire et comment définir le reste des paramètres par défaut afin que les résultats soient aussi complets que possible. Il est clair qu'il est impossible de tout prévoir - cependant, vous pouvez essayer de gérer la plupart des cas.

Les exigences d'assemblage doivent être rendues aussi souples que possible. Par exemple, pour les langages JVM, vous n'avez pas besoin d'exiger l'assemblage pendant l'analyse - demandez simplement de charger les artefacts, c'est-à-dire le code assemblé avec les sources (ce qui est beaucoup plus simple). Pour Xcode, dans le cas d'Objective-C, l'assemblage peut être automatisé pour la plupart des cas. S'il n'a pas été possible de collecter le code, l'analyseur peut essayer d'effectuer une analyse partielle. Ses résultats ne seront pas aussi complets, mais c'est mieux que pas de résultats du tout. Il est également pratique que le module d'analyse puisse être placé sur la machine pour le développeur, où l'assemblage de code est déjà configuré, tandis que l'architecture doit permettre aux autres modules et à la partie d'interface d'être transférés sur une autre machine.

Enfin, l'analyseur doit mettre en avant les exigences de format les plus souples et traiter lui-même les fichiers d'entrée. Une archive avec du code source, des archives imbriquées, une archive d'un référentiel, un lien vers un référentiel, une archive d'un produit, un fichier exécutable d'un produit - c'est bien si l'analyseur prend en charge tout cela.

Cependant, n'oubliez pas que l'analyseur n'a pas d'intelligence artificielle et ne peut pas tout prévoir. Par conséquent, si des erreurs se produisent, vous devez vous familiariser avec le manuel - il y a beaucoup de choses utiles dans la préparation du code pour l'analyse. Eh bien, tout ce travail de lancement d'une analyse lors de la mise en œuvre de l'analyseur n'est effectué qu'une seule fois pour chaque base de code. Le plus souvent, l'analyseur est généralement intégré au cycle CI, c'est-à-dire qu'il n'y aura pas de problème avec l'assemblage.

Processus d'analyse


D'accord, l'analyse a commencé. Une heure passe - aucun résultat. La barre de progression se situe quelque part au milieu, il n'est pas clair avec quel pourcentage et quelle prévision est terminée. La deuxième heure passe - les progrès ont progressé de 99% et sont restés suspendus pendant une demi-heure. La troisième heure s'écoule et l'analyseur se bloque, signalant un manque de RAM. Ou se bloque encore une heure et se termine. Vous pouvez vous attendre à ce que l'analyse passe à la même vitesse que votre style de contrôle, et ici les attentes seront très différentes de la réalité.


Oui, un bon analyseur statique peut consommer beaucoup de ressources, j'ai souligné l'une des raisons ci-dessus: trouver des vulnérabilités complexes est une tâche exponentiellement difficile. Donc, plus il y a de ressources et plus de temps, meilleurs seront les résultats (avec un bon moteur, bien sûr). Il est vraiment difficile de prédire à la fois le temps d'analyse et les ressources nécessaires - le temps de fonctionnement des algorithmes d'analyse statique dépend fortement des constructions de langage, de la complexité du code, de la profondeur des appels - de caractéristiques difficiles à calculer à l'avance.

Le problème des ressources est un mal nécessaire. Vous devez faire attention à l'allocation des ressources nécessaires, attendre patiemment la fin de l'analyse et comprendre également que personne ne peut prédire avec précision les ressources nécessaires à l'analyseur, même avec une base de code donnée, et vous devez être prêt à modifier ces paramètres. De plus, les paramètres requis peuvent changer même sans mettre à jour la base de code - en raison de la mise à jour de l'analyseur.

Néanmoins, l'analyseur peut aider un peu avec ce problème. Il est capable de séparer la partie gourmande en ressources (moteurs) et l'interface en différentes machines. Cela vous permettra de ne pas charger les machines avec des programmes inutiles qui ralentiront leur travail, tandis qu'il sera possible d'utiliser l'interface système pour toute charge de travail sur les analyses (par exemple, pour afficher et modifier les résultats). Cela facilitera également la mise à l'échelle sans réinstaller tout le système (nous élevons l'analyseur sur une nouvelle machine virtuelle, spécifions l'IP de la machine principale - et le tour est joué).

De plus, l'analyseur peut vous permettre de choisir la profondeur de l'analyse, de désactiver les contrôles lourds, d'utiliser l'analyse incrémentielle (dans laquelle tout le code n'est pas vérifié, mais seulement modifié). Ces éléments doivent être utilisés avec beaucoup de précaution, car ils peuvent grandement affecter les résultats de l'analyse. Si vous utilisez une telle fonctionnalité, il est recommandé d'effectuer une analyse complète à certains intervalles.

Résultats d'analyse


Passons aux résultats de l'analyse (pendant longtemps, nous y sommes allés). Vous attendez le nombre de vulnérabilités dans la fenêtre de l'analyseur avec inquiétude, et vous êtes très surpris de le voir. 156 critiques, 1260 moyennes et 3210 faibles. Vous allez sur la page des résultats et vous noyez dans le nombre de problèmes trouvés. Vous téléchargez un rapport pdf et vous voyez plusieurs milliers de pages de texte. Devinez ce que le développeur de code dira quand il verra une telle toile?


Le gardien de sécurité transmet un rapport de vulnérabilité au développeur

Mais essayons toujours de voir les résultats, donnez-lui une chance. Après avoir soigneusement examiné des dizaines d'occurrences, vous commencez à comprendre pourquoi il y a tant de vulnérabilités. Plusieurs vulnérabilités semblent vraiment sérieuses, vous comprenez qu'elles doivent être corrigées. Cependant, immédiatement, vous trouvez une douzaine de faux. Et aussi - un grand nombre de vulnérabilités dans le code des bibliothèques. Vous ne corrigerez pas les bibliothèques! Et puis vous comprenez combien de temps vous passerez à analyser les résultats. Et cette procédure doit être répétée tous les jours, toutes les semaines, ou au moins à chaque libération. (En fait non).

Pour commencer, les faux positifs peuvent être compris de manières très différentes. Quelqu'un ne considérera pas uniquement les fausses vulnérabilités critiques qui peuvent être exploitées dès maintenant. Quelqu'un ne considérera que les fausses erreurs explicites de l'analyseur. Cela dépend beaucoup de ce que vous voulez de l'outil. Nous vous recommandons de prendre en compte presque toutes les occurrences, car même une vulnérabilité de bas niveau qui ne peut pas être exploitée actuellement peut devenir un problème sérieux demain, par exemple, en raison de changements dans le code et de conditions externes.

Ok, vous devez regarder toutes les entrées, mais cela représente toujours une énorme quantité de travail. Et ici, les analyseurs peuvent très bien aider. La fonction la plus importante de l'analyseur est la capacité de suivre les vulnérabilités entre les analyses d'un projet, tout en gardant une trace de celui-ci est résistant aux petits changements qui sont standard pour le développement de code. Cela supprime le problème qu'une longue analyse des vulnérabilités doit être répétée: la première fois que vous passez plus de temps, supprimant les faux positifs et modifiant la criticité des occurrences, mais vous n'aurez alors qu'à examiner les nouvelles vulnérabilités, qui seront plusieurs fois plus petites.

Bien, mais est-il nécessaire de revoir toutes les vulnérabilités pour la première fois? Nous vous recommandons de le faire, mais en règle générale, ce n'est pas nécessaire. Tout d'abord, les analyseurs vous permettent de filtrer les résultats par répertoires et fichiers: par exemple, lorsque vous démarrez une analyse, vous pouvez immédiatement exclure tous les composants, bibliothèques, code de test de l'analyse. Cela affectera la vitesse d'analyse. Deuxièmement, les analyseurs vous permettent de filtrer les résultats par vulnérabilités, c'est-à-dire que lorsque vous démarrez l'analyse, vous pouvez limiter l'ensemble des vulnérabilités. Enfin, en plus de la criticité, l'analyseur peut produire quelque chose comme la probabilité d'une fausse vulnérabilité (c'est-à-dire sa confiance dans cette vulnérabilité). En utilisant cette métrique, vous pouvez filtrer les résultats.

Par ailleurs, il convient de noter la technologie d'analyse de composition logicielle (elle commence maintenant à être prise en charge par un nombre croissant d'instruments à différents niveaux). La technologie vous permet de détecter l'utilisation de bibliothèques dans votre code, de déterminer les noms et les versions, d'afficher les vulnérabilités connues, ainsi que les licences. Cette technologie peut séparer le code de la bibliothèque du vôtre, qui peut également filtrer les résultats.

Il s'avère que vous pouvez traiter le problème des résultats d'analyse abondants, et ce n'est pas très difficile. Et bien que la première visualisation des résultats puisse en effet prendre un certain temps, alors lorsque vous la numérisez, elle sera dépensée de moins en moins. Cependant, je note à nouveau que vous devez faire attention à tout filtrage des résultats - vous pouvez ignorer la vulnérabilité. Même si la bibliothèque est connue, cela ne signifie pas qu'elle ne comporte aucune vulnérabilité. Si maintenant cette vulnérabilité est mal détectée (c'est-à-dire que l'outil affiche beaucoup de faux positifs pour cette vulnérabilité), et que vous la désactivez, lors de la mise à jour de l'analyseur, vous pouvez ignorer la vraie vulnérabilité.

Vérifiez l'analyseur


Compris avec un gros rapport et des faux positifs. Mais vous voulez aller plus loin - pour vous assurer que l'analyseur trouve les vulnérabilités dont vous êtes sûr (vous auriez pu les poser intentionnellement ou trouver un autre outil).


Pour commencer, il est important de comprendre que l'analyseur n'a pas pu trouver la vulnérabilité pour diverses raisons. La chose la plus simple est que l'analyse a été mal configurée (vous devez faire attention aux messages d'erreur). Mais du point de vue de la technologie d'analyse, les raisons peuvent être différentes. Un analyseur statique se compose de deux composants importants: un moteur (il contient toute la complexité algorithmique et les mathématiques) et une base de règles de recherche de vulnérabilité. Une situation est lorsque le moteur vous permet de trouver une vulnérabilité de cette classe, mais il n'y a aucune vulnérabilité dans la base de règles. Dans ce cas, l'ajout d'une règle n'est généralement pas difficile. Une situation complètement différente, si le moteur, en principe, ne prend pas en charge de telles vulnérabilités - ici, la révision peut être très importante. J'ai donné un exemple au début de l'article: l'injection SQL ne peut jamais être trouvée sans algorithmes d'analyse de flux de données.

Un analyseur statique doit implémenter un ensemble d'algorithmes dans le moteur qui couvre les classes de vulnérabilités disponibles pour un langage de programmation donné (analyse du flux de contrôle, flux de données, analyse d'intervalle, etc.). Un point important est la possibilité d'ajouter vos propres règles de recherche de vulnérabilités à l'outil - cela éliminera la première raison de manquer une vulnérabilité.

Ainsi, si vous n'avez pas trouvé de vulnérabilité existante dans les résultats de l'analyse, vous devez d'abord déterminer la raison du saut - généralement un fournisseur peut vous aider. Si la raison se trouve dans la base de règles ou dans la configuration d'analyse, la situation peut être assez facilement éliminée. La chose la plus importante est d'évaluer la profondeur de l'analyse, c'est-à-dire ce qui, en principe, vous permet de rechercher le moteur.

Compétences


Après avoir lu l'article à cet endroit, nous pouvons supposer que pour travailler avec l'outil, une expertise approfondie du développeur est nécessaire, car vous devez comprendre quelles réponses sont fausses et lesquelles sont vraies. À mon avis, tout dépend de la façon dont se comporte l'instrument. S'il fournit des fonctionnalités pratiques et compréhensibles, des descriptions compréhensibles des vulnérabilités avec des exemples, des liens et des recommandations dans différentes langues, si l'outil affiche des traces de vulnérabilités liées à l'analyse du flux de données, vous n'aurez pas besoin d'avoir une expertise approfondie du développeur avec une compréhension de toutes les subtilités du langage de programmation et cadres. Cependant, il devrait y avoir un minimum de fond dans le développement afin de lire le code.

Intégration dans le processus de développement



À la fin de l'article, nous abordons brièvement l'une des questions les plus importantes de l'utilisation de l'outil, et nous l'examinerons en détail dans les articles suivants. Supposons que vous décidiez d'utiliser un analyseur statique. Cependant, vous avez un processus de développement établi, à la fois technologique et organisationnel, et vous ne voulez pas le changer (personne ne le donnera).

L'outil doit avoir une interface non graphique complète (par exemple, CLI ou API REST), avec laquelle vous pouvez intégrer l'analyseur dans n'importe lequel de vos processus. C'est bien si l'analyseur a des intégrations prêtes à l'emploi avec divers composants: plug-ins pour les IDE ou les systèmes de build, intégrations avec les systèmes de contrôle de version, plug-ins pour les serveurs CI / CD (Jenkins, TeamCity), intégration avec les systèmes de gestion de projet (JIRA) ou travailler avec les utilisateurs ( Active Directory).

L'intégration de l'analyse statique dans le processus de développement (le soi-disant SDLC) est le moyen le plus efficace de l'utiliser si le processus est bien établi et que tous les participants sont d'accord et savent pourquoi cela est nécessaire. Une analyse constante du code après des modifications ou des mises à jour de l'analyseur vous permettra de trouver les vulnérabilités le plus tôt possible. La séparation des rôles des développeurs et des spécialistes de la sécurité de l'information, une indication claire des exigences de la sécurité de l'information et de l'intégration douce dans le processus actuel (par exemple, au début - la nature consultative du système) vous permettra d'utiliser l'outil sans douleur et utilement. Cependant, personne n'a annulé l'utilisation manuelle de l'outil, si votre modèle de développement n'implique pas un processus similaire.

Résumé


L'article contient des recommandations de base pour commencer à utiliser un analyseur statique. Un bon analyseur fonctionne un ordre de grandeur mieux que n'importe quel vérificateur léger; il recherche des problèmes d'une complexité fondamentalement différente. Par conséquent, il est nécessaire de prendre en compte les fonctionnalités de l'analyse statique en tant que technologie, mais en même temps, choisissez un outil spécifique afin que sa fonctionnalité lisse au maximum toutes ces fonctionnalités.

Source: https://habr.com/ru/post/fr424255/


All Articles