Test d’intrusion web : objectifs, méthodologie, tests en boite noire, grise et blanche

Face à des attaques de plus en plus nombreuses et élaborées, la sécurité des applications web est un enjeu majeur. En effet, la sécurité revêt aujourd’hui une importance capitale pour rassurer et fidéliser des clients, ou convertir des prospects. 

Il existe plusieurs moyens d’évaluer la sécurité d’une application web. Dans cet article, nous vous présentons l’approche « offensive » qui reste, selon nous, la plus efficace : les tests d’intrusion web (ou pentest web). Nous y détaillons les principes et objectifs ainsi que des use cases de tests d’intrusion en boite noire, grise et blanche sur diverses cibles.

En quoi consiste un test d’intrusion d’application web ?

Un test d’intrusion d’application web consiste à évaluer la sécurité d’une plateforme web (site vitrine, application SaaS, site e-commerce) via une mise en situation reproduisant les conditions d’une attaque réelle.

L’objectif est d’identifier toutes les vulnérabilités côté serveur et sur toutes les fonctionnalités et composantes de l’application web (front et backend, APIs, services tiers, etc.), de mesurer leurs impacts et de proposer des correctifs afin de renforcer la sécurité du système cible. 

Test d’intrusion web et tests de vulnérabilités : quelles différences et spécificités ?

Les tests d’intrusion et tests de vulnérabilités sont deux approches différentes, même si elles partagent certaines similitudes.

D’un côté, les tests de vulnérabilités reposent sur des scanners automatiques qui permettent d’identifier uniquement les failles les plus connues, répertoriés dans une base de données, sans toutefois les exploiter. De l’autre, un test d’intrusion web, ne se contente pas de failles techniques et de recherches automatisées, mais fait intervenir un ou plusieurs pentesters pour identifier des failles plus complexes dont des vulnérabilités logiques via des scénarios conçus sur mesure et adaptés à l’application testée.

En effet, il s’agit lors d’un test d’intrusion de se mettre dans la peau d’un attaquant interne ou externe (avec ou sans informations sur le système cible) pour évaluer la sécurité d’une application via des exploitations plus ou moins complexes de vulnérabilités (techniques et logiques), et ce à l’aide de scripts manuels. Cela permet non seulement d’éliminer les faux positifs mais également de mieux éprouver la sécurité d’une application web via l’évaluation des impacts réels des failles identifiées.

De plus, à la suite de l’identification d’une vulnérabilité, il est important de la creuser pour voir si cette dernière ne peut pas servir comme pivot pour la découverte d’une autre faille, car, très souvent, plusieurs vulnérabilités sont exploitées afin de réussir à obtenir un accès ; ce qui est impossible avec un scanner automatique.

Rapport de tests d’intrusion et présentation des résultats

Les résultats des tests sont documentés dans un rapport complet qui détaille la méthodologie, les vulnérabilités techniques et logiques identifiées, leurs impacts, les scénarios d’exploitation, ainsi que des recommandations de correction. Ce rapport est présenté par les pentesters afin d’échanger sur les résultats du test d’intrusion.  Enfin, une phase de contre audit peut être réalisée afin de valider la bonne implémentation des corrections et l’absence d’effets de bords.

Périmètre d’un test d’intrusion web

Un test d’intrusion est une opération sur-mesure. De fait, il est possible de tester toutes les fonctionnalités d’une application web ou de se focaliser sur les pans les plus à risque, en fonction du besoin identifié.

Lors d’un test d’intrusion web, l’objectif des pentesters sera de trouver les vulnérabilités les plus critiques telles que répertoriées par l’OWASP et d’autres référentiels de sécurité.

Ainsi, les tests couvrent (liste non exhaustive) :

  • Les serveurs avec l’identification de services mal sécurisés, des logiciels non à jour, d’erreurs de configuration, etc.
  • La recherche de failles logiques liées aux workflows de l’application
  • Les vulnérabilités les plus courantes des applications web : injections (SQL, XSS, SSTI, etc.), défaut de contrôle d’accès (IDORs, possibilité d’élévation de privilèges, etc.), les problèmes dans la gestion de l’authentification et des sessions, l’utilisation de composants tiers vulnérables, etc.
  • Les vulnérabilités inhérentes aux APIs REST, GraphQL, etc.

Pour plus d’informations, vous pouvez consulter nos articles qui explorent les vulnérabilités et attaques les plus courantes sur les applications web et les failles inhérentes aux APIs.

Test d’intrusion en boite noire d’un site e-commerce

Un test d’intrusion en boite noire est l’approche où un pentester possède le moins d’informations sur l’application cible. En effet, aucun compte ni d’informations techniques ne sont fournis afin de se rapprocher le plus possible des conditions d’une attaque externe.

Dans un projet en boite noire, nous faisons face à 2 cas possibles :

  • Il y a seulement une interface de connexion au site. L’objectif pour un pentester sera d’obtenir un accès sur la plateforme ciblée. Il peut y arriver en exploitant des vulnérabilités de type SQLi, un manque de contrôle d’accès, un mot de passe trivial, etc.
  • La cible des tests est un site e-commerce. C’est un cas un peu particulier de projet en boite noire où l’on se rapproche de la boite grise. En effet, n’importe quel utilisateur peut créer un compte et ainsi avoir accès à des fonctionnalités supplémentaires.

Prenons l’exemple d’un pentest en boite noire d’un site de vente en ligne de vêtements pour vous présenter notre méthodologie. Avant toute chose, face aux faibles nombres d’informations, nous allons chercher à avoir une meilleure connaissance de la plateforme.

Recherche open source (OSINT)

La recherche open source (OSINT) consiste à récupérer des informations exposées sur le web sur le périmètre de l’audit. Cette phase est importante car elle peut orienter la recherche de vulnérabilités et faciliter leur découverte.

Parmi ces ressources exposées, il est possible que certaines contiennent des informations sensibles, qui ne devraient pas être divulguées publiquement.

L’illustration parfaite est la découverte lors d’un audit, d’un répertoire GitHub, accessible publiquement, contenant le code source de l’application. Ce code source ne respectait pas les meilleures pratiques de sécurité car le mot de passe d’un administrateur y était présent en dur. Ainsi, une rapide recherche a permis la compromission d’un compte administrateur.

Ces recherches peuvent aller plus loin, et permettre par exemple de récupérer des bases de données contenant des identifiants de connexion qui auraient fuité ces dernières années. L’objectif étant de chercher de potentiels identifiants valides en rapport avec le périmètre audité.

Recherche des technologies

La connaissance des frameworks utilisés peut être utile pour orienter les tests et trouver des vulnérabilités. Un outil pour obtenir ce type d’information est Wappalyzer.

L’outil va se charger d’analyser les requêtes passant par notre navigateur à la recherche d’éléments techniques. Il possède une base de données large pour identifier les plugins, les outils de monitoring ou de gestion de contenus, etc. Il se base par exemple sur les en-têtes dans la réponse du serveur.

On peut aussi obtenir les versions des outils en question et nous allons donc chercher des vulnérabilités connues d’une version précise.

Un cas courant lors d’un audit, est que Wappalyzer nous remonte l’utilisation de Magento. C’est un framework reconnu pour les sites e-commerce. Avec cette connaissance, nous pouvons avoir le code source, car Magento possède une version open-source, et aussi récupérer le schéma GraphQL.

Recherche de fichiers

Avec ces nouvelles connaissances sur les technologies utilisées, nous pouvons effectuer une recherche de fichiers plus précise.

Des outils comme feroxbuster permettent de découvrir les fichiers présents sur le serveur. Il faut des dictionnaires de noms de fichiers et de répertoires pertinents pour ne pas manquer des données sensibles. Il arrive que des fichiers ne servant pas au fonctionnement de l’application soient encore accessibles. On peut penser à des fichiers de logs où l’on pourrait retrouver des mots de passe utilisateur, ou encore à des sauvegardes du code source. Des dictionnaires liés aux technologies sont aussi utilisés pour plus d’efficacité.

Recherche de vulnérabilités

Il est fréquent que les sites e-commerce que nous auditons utilisent des frameworks reconnus et matures en termes de sécurité tels que Magento cité précédemment.

Lors d’un test d’intrusion de site e-commerce, nous allons créer un compte pour accéder à plus de fonctionnalités comme la modification des informations personnelles. Dans un second temps, nous créerons un autre compte pour tester les problèmes de droits entre les utilisateurs.

Tests de droits

La création de comptes est un point d’attention pour nous, car si cette fonctionnalité n’est pas correctement implémentée cela peut mener à un vol de compte ou à une fuite d’informations techniques.

Nous pouvons nous appuyer sur un cas réel pour illustrer cela. Lors de la création d’un compte sur la plateforme, avec un email déjà existant, le serveur a révélé l’identifiant unique du compte lié à cet email.

Sur l’interface web, seul un message indiquant « Adresse email déjà utilisée » était affiché, mais la réponse du serveur contenait l’identifiant unique lié à l’adresse email.

Cette information semble anodine mais elle a été déterminante dans l’exploitation d’une seconde vulnérabilité.

L’application utilisait un endpoint donnant un jeton à l’utilisateur faisant la requête pour ensuite accéder à toutes les requêtes du schéma GraphQL. Cet endpoint était vulnérable aux IDORs. En mettant dans la requête l’identifiant de notre compte, le serveur renvoyait un token permettant de s’authentifier sur le GraphQL. En changeant cet identifiant par celui que l’on a fait fuiter auparavant, on pouvait voler le jeton de l’utilisateur ciblé et ainsi faire les requêtes avec son compte.

Dans ce cas, nous pouvions récupérer ses informations personnelles.

Tests de la brique de paiement

Les sites e-commerce intègrent une fonctionnalité critique : le paiement. Il est assez fréquent que des solutions sécurisées soient utilisées. En général, nous ne testons pas celles-ci directement.

Les tests vont porter sur la manière dont la solution de paiement a été intégrée à l’application. Nous recherchons donc des vulnérabilités logiques liées à la mauvaise implémentation des solutions de paiement.

Pour ce faire, il s’agit de manipuler les paramètres des requêtes. La vulnérabilité la plus évidente à tester est la modification du prix d’un article. Il peut arriver que la valeur de l’article soit passée en paramètre de la requête. Un auditeur peut alors changer le prix et payer moins cher voire ne pas payer du tout et quand même recevoir le produit.

Autres failles logiques

Un autre problème de logique concerne la quantité commandée d’un produit. C’est un cas que nous avons déjà rencontré lors d’un projet.

Le paramètre gérant la quantité que l’utilisateur veut mettre dans son panier acceptait une valeur décimale. En mettant une quantité égale à 0.5, le prix était alors réduit de moitié bien que la facture indiquait que le produit avait été commandé avec une quantité de 1. 

Un autre test assez simple à réaliser est d’effectuer un paiement avec une carte de tests. En effet, les développeurs peuvent utiliser des cartes de tests fournis (donc publiques) par les éditeurs de logiciel. Ces cartes sont généralement utilisées sur des environnements de développement, mais il est possible que cela soit activé en production.

Par ailleurs, la meilleure configuration pour tester l’implémentation du système de paiement est d’avoir accès au back-office de la plateforme, mais cela correspond à un test en boite grise.

Test d’intrusion en boite grise d’une application SaaS

Un audit de sécurité en boite grise possède la particularité que des comptes sur la plateforme vont être fournis aux testeurs. Cela permet d’être bien plus exhaustif qu’un audit en boite noire, car toutes les fonctionnalités sont accessibles pour le pentester.

Prenons l’exemple d’un pentest en boite grise d’une application SaaS qui gère les plannings des collaborateurs d’une entreprise.

Il est très courant qu’une application SaaS offre différents types de compte. Une application très basique présenterait seulement 3 rôles distincts : « collaborateur », « administrateur », « super_administrateur ». La grande majorité des employés d’une organisation posséderait un compte « collaborateur » avec lequel ils pourraient modifier leur calendrier de façon individuel, les managers pourraient voir et modifier les calendriers de leur équipe. Enfin, les comptes de type « super administrateur » ne seraient disponibles que pour les employés de l’éditeur du logiciel et le compte aurait accès à toutes les organisations de la plateforme.

Contrôle de droits

Le contrôle de droits est une tâche très importante à effectuer, car l’impact d’un manque de contrôle d’accès s’avère souvent élevé, permettant à un attaquant de récupérer des données sensibles ou d’élever ses privilèges. Il faut une bonne compréhension de l’application pour déterminer les erreurs faites par les développeurs sur les droits concernant chaque requête. Un scanner de vulnérabilités ne peut pas déterminer les mauvaises implémentations des permissions.

Pour plus d’informations sur les tests de droits, vous pouvez consulter notre article sur les failles IDOR (Insecure Direct Object Reference).

Pour reprendre le cas réel d’un test d’intrusion, nous avons pu élever nos privilèges en passant du rôle « collaborateur » à « super administrateur », ce qui est une vulnérabilité critique. Cela signifie que n’importe quel employé d’une entreprise cliente de l’application SaaS pouvait impacter toutes les autres organisations clientes.

Nous avons identifié ce problème lors de tests de droits. Un compte « administrateur » et et un compte « collaborateur » nous avaient été fournis. Nous avons d’abord fait la requête légitime de changement de rôle avec un compte « administrateur », puis nous avons rejoué la requête avec un « collaborateur ». La réponse de l’application était identique signifiant qu’un compte avec le plus bas niveau de privilège pouvait élever son niveau de droit.

PATCH /auth/organization /06fa370/ HTTP/2
Host: backend.target.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/112.0
Accept: application/json, text/plain, */*
Accept-Language: fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Content-Type: application/json
Authorization: JWT tokenCollaborateur
Referer: https://app.target.com/
Content-Length: 68
Origin: https://app.target.com
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
Te: trailers

{"id":"06fa3703-8640-4559-9256-3464bb1e67ab","organization_role":"administrateur"}

Réponse :

HTTP/2 200 OK
Date: Thu, 13 Apr 2023 09:34:26 GMT
Content-Type: application/json
Content-Length: 330
Server: nginx
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Referrer-Policy: same-origin
Cross-Origin-Opener-Policy: same-origin
Vary: Origin
Access-Control-Allow-Origin: *
{"id":"06fa370","user":"85b17b88-6008 ","organization":"69a9fcf8-490d","is_test":true,"is_principal":true,"organization_role":"administrateur”}

La criticité de la vulnérabilité a pu être augmentée en passant super administrateur de la plateforme. Il est possible d’essayer plusieurs valeurs pour le paramètre « organization_role ». Dans le cas de ce pentest, la valeur que l’on cherchait était « root », ce qui est une valeur assez courante pour ce type de paramètre.

Le plus simple reste d’avoir le code source pour connaître directement la valeur attendue, mais nous verrons cela plus tard.

Failles d’injection XSS (Cross-site Scripting)

Un autre type de vulnérabilité que l’on peut trouver est les failles de type XSS (injection de code JavaScript). Il arrive que l’accès à une plateforme d’administration nous soit accordé dans le cadre d’un projet en boîte grise. C’est un avantage pour détecter les XSS qui serait en aveugle sans cela.

Ce sont des XSS qui sont déclenchés sur une autre plateforme que celle que nous avons à auditer. Elles peuvent ne pas être déclenchées en navigant sur l’application principale. L’accès au backoffice nous permet alors de ne pas manquer ce type de vulnérabilité. Si nous n’avons pas cet accès, nous allons utiliser des payloads spécifiques pour la détection de blind XSS. Un outil comme XSSHunter est très utile dans ce cas-là. C’est un service web qui va être exposé pour que la charge utile de la XSS puisse faire une requête à ce serveur.

Ainsi, nous allons savoir quand le code JavaScript aura été exécuté, la provenance de la requête, etc. Des payloads déjà faites se trouvent sur XSSHunter pour par exemple prendre une capture d’écran du navigateur de la victime.

Si nous n’avons pas accès au backoffice, il arrive que l’appel au code injecté se déclenche plusieurs jours après les tests. Un outil comme XSSHunter va nous permettre de détecter une telle vulnérabilité et d’en connaître l’origine.

Test d’intrusion en boite blanche

Un audit de sécurité en boîte blanche induit l’accès au code source pour les pentesters. Ils ont ainsi accès au développement fait par le client. Cela apporte différents avantages :

  • La possibilité de se concentrer sur le développement fait spécialement pour l’application. Dans le cas d’un site fait avec Magento, nous passerons plus rapidement sur les fonctionnalités natives de Magento, car il y a moins de chance de trouver des vulnérabilités sur ce noyau ; étant donné qu’il est open-source il est probable qu’il soit régulièrement étudié par des chercheurs en sécurité.
  • Une meilleure compréhension de l’application. Nous avons accès à toutes les opérations faites par le serveur, et du traitement effectué sur les entrées utilisateurs de l’application.
  • Une meilleure efficacité et exhaustivité. Nous pouvons voir tous les endpoints de l’application. Il arrive que certaines routes ne soient pas accessibles depuis l’interface, car elles ne sont plus utilisées ou alors seulement faites pour les développeurs. Il est quand même possible de les trouver sans le code source avec des outils comme Feroxbsuter (cité précédemment). En boîte blanche, nous sommes sûrs de ne pas en manquer.

Ce sont les meilleures conditions pour trouver le plus de vulnérabilités et assurer que la plateforme est sécurisée.

Recherche de vulnérabilités dans le code

Le code source peut nous permettre d’identifier rapidement des vulnérabilités comme des XSS. Suivant le framework utilisé, certaines fonctions peuvent amener à des injections de code JavaScript sous la condition qu’une entrée utilisateur soit utilisée par la fonction vulnérable.

Nous allons illustrer cela. Il peut arriver qu’un développeur veuille qu’un élément soit directement rendu au format HTML, mais cela pose un problème de sécurité si l’utilisateur peut contrôler le contenu de cet élément.

Dans Angular (un framework TypeScript), une fonction potentiellement problématique est « byPassSecurityTrustHtml() ».

Une recherche avec l’outil grep va nous permettre rapidement trouver toutes les occurrences de la fonction dangereuse ou alors simplement avec un éditeur de texte comme VSCode.

La recherche va nous remonter un morceau de code comme le suivant :

ngAfterViewInit(): void {
    this.elem = this.sanitizer.bypassSecurityTrustHtml(this.elem);
  }

Une compréhension globale du code va nous permettre de savoir si la variable « elem » est contrôlable par un attaquant ou non. Si c’est le cas, il faut arriver à retrouver dans l’application où ce composant est utilisé pour confirmer la vulnérabilité.

Également, des problèmes de droit peuvent aussi être détectés en analysant le code. Il n’est pas évident de les trouver en regardant seulement les sources. Il est plus simple de trouver un problème de droit avec une matrice de droit de façon classique puis de trouver la ligne responsable de ce problème. Une fois le pattern identifié, il n’y a plus qu’à le rechercher pour être sûr de déterminer tous les endroits où le problème pourrait apparaître. L’exhaustivité est alors plus rapide à atteindre avec cette méthode.

Semgrep

Semgrep est un outil qui va se baser sur la recherche d’expressions régulières comme on pourrait le faire avec grep. Là où l’outil est plus puissant qu’un simple grep est qu’il existe déjà une base de données d’expression régulière permettant de détecter de patterns dangereux suivants le langage de programmation employé. L’outil peut aller encore plus loin, car dans certains cas, il peut détecter si les variables sont contrôlables par un utilisateur en allant chercher dans d’autres fichiers à travers le répertoire.

Voilà un exemple d’un élément remonté par Semgrep :

python.django.security.audit.xss.direct-use-of-httpresponse.direct-use-of httpresponse

Detected data rendered directly to the end user via 'HttpResponse' or a similar object. This bypasses Django's built-in cross-site scripting (XSS) defenses and could result in an XSS vulnerability. Use Django's template engine to safely render HTML.  
      Details: https://sg.run/EknN

         24┆ return HttpResponse(json.dumps({ 'status': 'ERROR', 'error': str(e) }), content_type='text/html')

Une potentielle XSS est détectée à cause de l’emploi de HttpResponse avec un content_type « text/html ». Chaque élément de sécurité est classifié avec une criticité et un niveau de confiance de détection.

Cependant, les outils tels que Semgrep détectent de nombreux faux positifs. Il convient lors de l’audit de vérifier manuellement les résultats de ces outils afin d’identifier les vulnérabilités exploitables par un attaquant.

Auteur : Julien BRACON – Pentester @Vaadata