Vigilant Lida: automatisation des tests de sécurité

Bonjour, chers lecteurs. Je m'appelle Victor Burov, je suis développeur chez ISPsystem. Dans le dernier article, j'ai parlé de l' outil de création d'autotests , aujourd'hui je partagerai mon expérience dans l'automatisation des tests de sécurité.



Au début, les vulnérabilités des produits ont été recherchées par un employé distinct. Les tests manuels ont pris beaucoup de temps et ne garantissaient pas que toutes les vulnérabilités seraient trouvées. Après avoir vérifié les lois de base des tests, nous sommes arrivés à la conclusion qu'il peut être automatisé. Ensuite, nous avons décidé d'écrire un utilitaire qui facilitera la vie du testeur, lui fera gagner du temps et vous permettra de vérifier les produits après chaque changement. Puisque le testeur s'appelait Lida, nous avons nommé la nouvelle application en son honneur. En général, dans notre entreprise, il est devenu une tradition d'appeler les outils de test par les noms des testeurs.

Après avoir analysé les utilitaires de recherche de vulnérabilités, je suis arrivé à la conclusion qu'ils ont tous besoin de spécifier les fonctions à appeler et les paramètres utilisés. Nous avons de nouveau décidé de profiter de l'interface unifiée et formulé les exigences pour Lida.

Conditions de démarrage:


  1. Construisez automatiquement des listes de fonctions.
  2. Options de saisie semi-automatique.
  3. Faire des requĂŞtes API.
  4. Analyse de la sortie des données après l'exécution des fonctions.
  5. Recherchez les vulnérabilités dans les données.
  6. Formation de rapports.
  7. Paramètres flexibles.

Réaliser tout cela n'a pas été facile.

Implémentation


Contourner les formulaires et les listes


Pour trouver des vulnérabilités dans une fonction, elle doit être exécutée en passant les paramètres nécessaires. Notre interface est construite sur la base de listes et de formulaires, vous pouvez donc automatiser la collecte de données en traitant des documents xml qui décrivent la structure des éléments de l'interface.

J'ai décidé de démarrer l'exploration à partir du menu principal, en rentrant récursivement dans toutes les listes imbriquées. «Lida» ouvre la liste du premier niveau. En règle générale, il possède plusieurs boutons qui invoquent certaines fonctions.

Si le bouton ouvre le formulaire, le résultat de l'appel sera un document xml avec des nœuds contenant des informations sur les champs: nom, validateur, plage de valeurs valides. Sur la base de ces informations, des valeurs de champ sont générées. Par exemple, un nombre sera généré pour int. S'il n'y a pas de validateur, une chaîne aléatoire est générée. Après avoir rempli tous les champs du formulaire, une demande est envoyée.

Si la fonction est une liste, elle sera ouverte et les fonctions associées aux boutons seront appelées pour ses éléments.

Lors de la vérification des listes, un problème survient - toutes les listes doivent avoir un ensemble d'enregistrements qui garantissent que tous les boutons de la liste sont cliquables.

Recherche d'injection SQL


L'injection SQL est probablement l'un des problèmes les plus courants pour les applications, y compris la nôtre. De nombreux appels de fonction génèrent diverses requêtes SGBD. Une erreur se produit lorsque des paramètres provenant de l'extérieur sont substitués «tels quels» dans le corps de la demande. Les conséquences de telles erreurs peuvent être tristes: de la réception non autorisée de données à la suppression de tableaux.

Pour démarrer la recherche d'injections SQL, j'ai organisé la sortie de toutes les requêtes SQL vers un fichier. Une fois la fonction exécutée, l'application recherche les valeurs des paramètres passés dans les requêtes SQL résultantes.

Vous pouvez utiliser le journal du serveur SQL lui-même. Mais dans notre cas, il n'y a qu'une seule méthode pour exécuter des requêtes et y ajouter la journalisation n'a pas été difficile. Grâce à cela, nous savons exactement quel défi a généré telle ou telle demande.

Lorsque la valeur du paramètre transmis est trouvée, l'utilitaire transmet une valeur contenant un guillemet simple à ce paramètre. Si la citation se trouve dans la même séquence, le paramètre n'est pas échappé - nous avons trouvé une place pour l'injection SQL.

Analyse des appels système


Un problème similaire se produit lorsque nous effectuons des appels système. J'ai décidé de les rechercher avec strace et j'ai sélectionné les paramètres de lancement optimaux pour cela. Exemple de démarrage d'ISPmanager:

strace -f -s 1024 -e trace=file,process bin/core ispmgr 

Comme pour les injections SQL, Lida exécute une fonction et analyse la sortie strace pour trouver les valeurs des paramètres passés dans les fonctions open, unlink, rmdir, chmod chown, chflags, mknod, mkfifo, fcntl, symlink, link, execve, mkdir .

Si le paramètre est trouvé, l'utilitaire lui transmet une valeur contenant, par exemple, un chemin d'accès avec une transition vers le répertoire ci-dessus. S'il se présente tel quel, une vulnérabilité potentielle est détectée.

L'analyse de la fonction execve s'est avérée très utile. Il vous permet de déterminer dans quelle fonction les arguments pour exécuter les fichiers exécutables ne sont pas échappés. Cette erreur est très coûteuse, car grâce à elle, vous pouvez obtenir un accès root au serveur simplement en changeant le mot de passe.

Lorsque les utilisateurs trouvent une vulnérabilité dans nos produits, l'entreprise verse une récompense en espèces, dont le montant dépend de la catégorie de vulnérabilité. Cette approche peut être moins coûteuse que la recherche d'erreurs par vous-même (le testeur peut ne pas trouver l'erreur et obtenir un salaire).

Un autre test intéressant: vérifier l'ordre d'appeler les fonctions stat et autres. Souvent, l'accès est d'abord vérifié par stat, puis par des actions dangereuses, ce qui laisse la possibilité de substitution. Mais nous n'avons pas automatisé cela.

Vérification de l'accès aux objets étrangers


Nous vérifions l'accès aux objets étrangers sous l'utilisateur pour les entités d'un autre utilisateur et administrateur. Dans ce mode, nous vérifions la possibilité de lire, modifier et visualiser les listes d'éléments d'un utilisateur étranger.

Lida contourne toutes les fonctions disponibles au nom du propriétaire ou de l'administrateur et se souvient de leurs éléments. Ensuite, il appelle les mêmes fonctions avec des éléments provenant d'un autre utilisateur. Dans une situation idéale, la réponse devrait être une erreur telle que Accès ou Manqué. Si une telle erreur n'est pas reçue, il est donc très probable que vous puissiez lire les données de l'utilisateur de quelqu'un d'autre.

Dans certains cas, l'absence d'erreur ne signifie pas que vous pouvez accéder directement aux objets d'autres utilisateurs. Au début de ces fonctions, nous ajoutons une vérification des autorisations des éléments. Cela vérifie non seulement la sécurité, mais également l'exactitude des réponses du serveur.

Validation API


La validation de notre API est un bonus supplémentaire de vérification des fonctions pour les vulnérabilités. En analysant les rapports sur le travail de Lida, nous avons appris à renvoyer les types d'erreurs corrects, ce qui a rendu notre API plus pratique et logique. En conséquence, comme avec le magnétophone, nous avons reçu non seulement un contrôle de sécurité, mais aussi une fois de plus vérifié la cohérence de notre API.

Des difficultés


Faux positifs


L'utilitaire peut fonctionner avec tous nos produits, par conséquent, il vérifie de nombreuses fonctions différentes. Fondamentalement, les faux positifs sont apparus dans le mode de vérification de l'accès aux objets étrangers. Cela est dû aux caractéristiques des boutons et des fonctions.

Les faux positifs étaient le plus gros problème de Lida. Il semblait qu'il était complètement débogué, mais lors de la vérification sur différents panneaux, de nouveaux faux positifs sont apparus. En conséquence, il y a eu plusieurs étapes de leur correction.

Création d'entité


La plupart des actions du panneau sont effectuées sur n'importe quelle entité (nom de domaine, base de données, etc.). Pour atteindre une automatisation maximale, Lida a dû créer ces entités automatiquement. Mais en pratique, cela s'est avéré difficile à mettre en œuvre. Parfois, la validation est effectuée dans le code, il n'est donc pas toujours possible de remplacer automatiquement une valeur de paramètre. La deuxième raison est les entités dépendantes. Par exemple, pour créer une boîte aux lettres, vous devez créer un domaine de messagerie.

Par conséquent, nous avons décidé de ne pas lutter pour une automatisation complète. Avant de commencer, le testeur crée des entités manuellement et prend un instantané de la machine, car les entités seront modifiées après vérification. Cela vous permet de ne pas ignorer la vérification d'un groupe de fonctions en cas de création infructueuse d'une entité.

Appel de fonctions destructrices


Presque chaque liste a des fonctions pour supprimer ou désactiver une entité. Si vous les exécutez en séquence, l'entité sera supprimée avant d'exécuter d'autres fonctions. Je définis de telles fonctions et j'exécute après d'autres. Ajout d'une clé qui interdit l'exécution de telles fonctions.

Certaines fonctions redémarrent le serveur. Ils doivent être suivis et ajoutés à la liste des ignorés.

En raison de la nature de la logique de fonctionnement, certaines fonctions redémarrent le panneau. Pendant les tests de sécurité, cela entraîne le démarrage du panneau sans tracer les requêtes SQL ou strace - une vérification supplémentaire n'a plus de sens. Vous devez suivre cela et redémarrer le panneau en mode trace.

Vérification des paramètres dépendants


Sur les formulaires, il existe des champs de saisie de texte, des cases à cocher, des listes déroulantes, dont les valeurs dépendent de la disponibilité des valeurs des autres champs. Chaque valeur du champ dépendant peut avoir une section de code distincte, par conséquent, les parties lorsqu'elles peuvent rester non vérifiées.

Pour résoudre ce problème, j'ai ajouté des algorithmes pour analyser les champs dépendants et vérifier toutes les combinaisons de contrôles dépendants.

Vérification des fonctionnalités non disponibles dans l'interface


Les fonctions de service ne sont pas disponibles pour la transition, mais peuvent contenir des vulnérabilités. Pour les identifier et les vérifier, nous avons une fonction spéciale qui renvoie une liste de toutes les fonctions enregistrées. Nous comparons cette liste avec la liste des fonctions testées. Il n'y a pas de métadonnées pour les fonctions de service, il est donc impossible de vérifier les paramètres traités à l'intérieur. Pour vérifier ces fonctions, je leur transmets nos paramètres standard elid, plid et autres.

Conclusion


Nous avons inclus Lida dans chaque construction de nuit à Jenkins. Sur la base des résultats de son travail, un rapport de vérification est généré, des informations sur la fonction suspecte y sont affichées avec tous les paramètres.

La tâche clôturée par le développeur est désormais vérifiée non seulement par le testeur, mais aussi par Lida. Le testeur traite le rapport reçu: copie les paramètres de la fonction suspecte dans le navigateur et analyse le comportement et le panneau de journalisation. Si la vulnérabilité est confirmée, l'erreur est consignée auprès du développeur.

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


All Articles