Pentest Web : objectifs, méthodologie et exemples d’exploitation en boite noire, grise et blanche

Pentest Web : objectifs, méthodologie et exemples d’exploitation en boite noire, grise et blanche

Les applications web occupent aujourd’hui une place centrale dans les systèmes d’information. Plateformes SaaS, espaces clients, outils métiers, applications bancaires, services e-commerce ou interfaces d’administration concentrent des fonctionnalités et des données parfois particulièrement sensibles.

Dans le même temps, leur architecture s’est considérablement complexifiée. Une application moderne ne se résume plus à quelques pages web communiquant avec une base de données. Elle peut reposer sur un front-end JavaScript, plusieurs APIs, des services cloud, des mécanismes SSO, des composants tiers, des systèmes de paiement, des WebSockets, des fonctions serverless ou encore des modèles de langage capables d’interagir avec d’autres services.

Cette complexité augmente mécaniquement la surface d’attaque. Une vulnérabilité peut provenir d’une erreur de développement classique, comme une injection SQL ou une XSS, mais également d’un contrôle d’autorisation incomplet, d’un workflow métier détournable, d’une API insuffisamment protégée, d’une mauvaise configuration d’un mécanisme OAuth ou de l’interaction entre plusieurs faiblesses qui, prises isolément, paraissent relativement limitées.

Le pentest web consiste à reproduire, dans un cadre contrôlé, les techniques susceptibles d’être utilisées par un attaquant afin d’identifier ces faiblesses avant qu’elles ne puissent être exploitées dans des conditions réelles.

Dans cet article, nous détaillons le fonctionnement d’un pentest d’application web, les principales surfaces étudiées, les vulnérabilités recherchées, les différences entre les approches boite noire, grise et blanche, la méthodologie suivie par les pentesters ainsi que les outils et livrables associés à ce type d’audit.

Guide complet sur le pentest web

Qu’est-ce qu’un pentest web ?

Définition d’un pentest d’application web

Un pentest d’application web est une évaluation de sécurité consistant à simuler des attaques réalistes contre une application afin d’identifier les vulnérabilités susceptibles d’être exploitées par un attaquant.

Le périmètre dépasse généralement les seules pages visibles depuis le navigateur. Une application web moderne peut reposer sur un front-end JavaScript, des APIs REST ou GraphQL, un back-end applicatif, des mécanismes d’authentification externes, plusieurs bases de données, des services cloud, des systèmes de stockage et différentes intégrations avec des services tiers.

Le rôle du pentester est d’analyser la manière dont ces composants communiquent et de rechercher les hypothèses de sécurité pouvant être détournées.

Une fonctionnalité peut par exemple contrôler correctement les valeurs saisies dans son interface graphique tout en acceptant des données différentes lorsqu’une requête est directement envoyée à son API. Un bouton réservé aux administrateurs peut être caché côté front-end tandis que l’endpoint associé ne vérifie pas les permissions côté serveur. Un service d’import d’image peut sembler anodin mais permettre au serveur d’effectuer une requête vers une ressource interne normalement inaccessible depuis Internet.

C’est précisément ce décalage entre le comportement attendu par les concepteurs et le comportement réellement accessible à un utilisateur malveillant que cherche à mettre en évidence un pentest.

Les auditeurs utilisent pour cela des outils spécialisés, mais une grande partie du travail repose sur l’analyse manuelle. Les outils facilitent l’interception des communications, la découverte de ressources ou la recherche de certains patterns. Ils ne remplacent pas la compréhension du contexte, de la logique métier ou des relations existant entre plusieurs vulnérabilités.

Quels sont les objectifs d’un pentest d’application web ?

L’objectif principal consiste à déterminer ce qu’un attaquant pourrait réellement obtenir en exploitant les faiblesses d’une application. Cela peut aller de l’accès à une donnée appartenant à un autre utilisateur jusqu’à la prise de contrôle d’un compte administrateur, l’exécution de commandes sur un serveur ou l’accès à d’autres composants du système d’information.

Le pentest permet également d’évaluer l’efficacité des contrôles de sécurité existants. Un mécanisme peut être correctement conçu dans son fonctionnement nominal mais présenter des faiblesses lorsqu’un utilisateur modifie l’ordre des opérations, appelle directement une API ou utilise un parcours alternatif. Cette analyse est particulièrement importante pour les contrôles d’accès, les workflows de récupération de compte, le MFA ou les opérations financières.

Un autre objectif essentiel consiste à identifier les chaînes d’exploitation. Les attaques réelles ne reposent pas toujours sur une vulnérabilité critique unique. Une fuite d’information peut révéler un identifiant interne. Cet identifiant peut ensuite être utilisé pour exploiter une faiblesse de contrôle d’accès. L’accès obtenu peut à son tour révéler un token ou une fonctionnalité supplémentaire permettant d’augmenter progressivement le niveau de compromission.

Le pentest permet précisément d’analyser ces interactions et d’évaluer le niveau de risque final plutôt que chaque vulnérabilité indépendamment.

Pentest web et scan de vulnérabilités : quelles différences ?

Un scan de vulnérabilités repose essentiellement sur des mécanismes automatisés. Il permet de rechercher rapidement des signatures connues, des composants obsolètes, certaines mauvaises configurations, des CVE ou des comportements caractéristiques de vulnérabilités techniques.

Cette automatisation est précieuse lorsqu’il faut surveiller fréquemment un grand nombre d’actifs. Elle présente cependant une limite importante : la compréhension du contexte applicatif.

Un scanner peut identifier qu’un endpoint accepte un identifiant, mais il lui sera beaucoup plus difficile de comprendre que cet identifiant correspond au contrat d’un autre client que l’utilisateur courant ne devrait jamais pouvoir consulter. De la même manière, un outil peut difficilement comprendre qu’un coupon promotionnel peut être appliqué plusieurs fois, qu’un processus d’approbation peut être contourné ou qu’une fonctionnalité accessible à un utilisateur standard lui permet indirectement d’obtenir des droits administratifs.

Le pentester cherche donc à comprendre la logique de l’application, à manipuler les paramètres et à valider l’exploitabilité des comportements observés. Les deux approches sont complémentaires : le scan apporte rapidité et couverture automatisée ; le pentest apporte compréhension, contextualisation et validation des scénarios d’attaque.

Pentest web et revue de code : quelles différences ?

La différence entre pentest et revue de code ne peut pas être réduite à la présence ou non du code source.

Une revue de code de sécurité consiste à analyser directement l’implémentation afin d’identifier des pratiques dangereuses, des fonctions sensibles, des contrôles manquants ou des erreurs de développement.

Le pentest adopte davantage une logique orientée attaque. L’auditeur cherche à déterminer comment une faiblesse peut être atteinte puis exploitée dans l’application réellement déployée.

En boite noire et en boite grise, cette analyse repose principalement sur le comportement observable depuis l’extérieur. En boite blanche, le code source devient au contraire une source d’information permettant d’orienter les tests dynamiques. Un auditeur peut par exemple identifier un traitement dangereux dans le code, déterminer quelles données l’alimentent puis construire une requête permettant de démontrer la vulnérabilité sur l’application en fonctionnement.

La revue de code et le pentest white box présentent donc des zones de recouvrement, mais leur finalité demeure différente. La revue de code cherche d’abord les faiblesses de l’implémentation ; le pentest white box utilise la visibilité interne pour accélérer et approfondir la construction de scénarios d’attaque démontrables.

Quelle est la surface d’attaque d’une application web moderne ?

Comprendre la surface d’attaque constitue une étape indispensable avant de rechercher des vulnérabilités. Une application ne doit pas être considérée comme une entité unique : elle est composée de plusieurs couches susceptibles de présenter leurs propres faiblesses et surtout d’interagir les unes avec les autres.

Interface web et logique côté client

Le navigateur exécute une quantité croissante de logique applicative. Les frameworks JavaScript gèrent l’affichage, les routes, une partie de la validation, le stockage temporaire d’informations et les communications avec les APIs.

Le pentester analyse donc les scripts JavaScript, le DOM, les données présentes dans le stockage local, les mécanismes de communication entre fenêtres ou frames ainsi que les protections appliquées aux contenus dynamiques.

Il garde cependant un principe essentiel en tête : une protection uniquement appliquée côté client ne constitue pas un contrôle de sécurité fiable. Un attaquant peut reproduire directement les requêtes HTTP sans utiliser l’interface graphique, supprimer des champs, en ajouter, modifier les valeurs ou appeler des fonctions qui ne sont pas exposées dans l’interface.

Back-end et APIs

Le back-end applique la logique métier, traite les données et communique avec les systèmes internes. Il constitue donc une partie critique de la surface d’attaque.

Les APIs sont particulièrement importantes car elles exposent souvent directement les opérations métier nécessaires au front-end ou aux applications mobiles. Le pentester cherche à cartographier ces interfaces et à comprendre comment elles appliquent les contrôles d’authentification, d’autorisation et de validation des données.

Il s’intéresse également aux interactions internes : appels entre microservices, webhooks, files de messages, services de génération de documents, connecteurs vers des bases de données ou fonctions serverless. Une fonctionnalité ne doit pas être considérée comme sûre sous prétexte qu’elle n’est pas visible depuis Internet si l’application publique peut l’atteindre indirectement.

Services tiers et composants externes

Une application dépend généralement de nombreux composants qui ne sont pas développés directement par l’organisation. Solutions de paiement, fournisseurs d’identité, outils de support, plateformes d’envoi d’e-mails, bibliothèques JavaScript, CDN ou APIs partenaires participent tous au fonctionnement de l’application.

L’audit ne consiste pas à attaquer ces fournisseurs lorsqu’ils ne font pas partie du périmètre. Il s’intéresse en revanche à la manière dont l’application leur fait confiance.

Un webhook insuffisamment authentifié, une réponse d’API tierce réutilisée sans validation ou une bibliothèque cliente chargée depuis une origine externe peuvent modifier profondément le risque sans qu’aucune vulnérabilité ne se trouve dans le code métier principal.

Infrastructure et environnement d’hébergement

Certaines vulnérabilités apparaissent à la frontière entre l’application et son infrastructure. Interfaces d’administration exposées, bucket cloud public, fichiers de sauvegarde, mode debug, répertoire .git, reverse proxy mal configuré ou headers révélant des informations sensibles peuvent faciliter une compromission.

Même dans un pentest principalement applicatif, ces éléments ne peuvent donc pas être complètement ignorés lorsqu’ils influencent directement la sécurité de la cible. L’objectif n’est pas de transformer systématiquement l’audit en pentest d’infrastructure, mais de comprendre les composants qui participent réellement à l’exposition de l’application.

Que teste-t-on lors d’un pentest web ?

Le contenu d’un pentest d’application web varie en fonction de l’architecture, des fonctionnalités et des risques métier. Il existe néanmoins plusieurs domaines qui font l’objet d’une attention particulière dans la majorité des audits.

Authentification et récupération de compte

L’authentification détermine qui peut accéder à l’application. Une faiblesse à ce niveau peut permettre de prendre le contrôle d’un compte sans avoir à exploiter le reste de l’application.

Le pentester étudie donc l’ensemble du cycle de vie de l’identité et pas uniquement le formulaire de connexion : création de compte, connexion, MFA, changement de mot de passe, modification de l’adresse e-mail, récupération de compte, sessions persistantes et mécanismes SSO éventuels.

Énumération des comptes et attaques par mot de passe

Une différence entre :

Unknown user

et :

Incorrect password

permet de déterminer directement si un compte existe.

Les différences peuvent être plus discrètes. Le message peut être identique tandis que le code HTTP, la taille de la réponse, une redirection ou le temps de traitement diffère. Une application qui calcule un hash de mot de passe uniquement lorsque l’utilisateur existe peut par exemple présenter une différence de timing exploitable.

L’auditeur examine ensuite les protections contre les tentatives répétées. Il vérifie si le rate limiting est appliqué de manière cohérente sur le formulaire principal, l’API, l’application mobile éventuelle et les différents workflows permettant de vérifier un mot de passe.

Le but n’est pas nécessairement d’effectuer une attaque massive. Quelques requêtes contrôlées permettent souvent de comprendre si la protection est liée à l’adresse IP, au compte, à la session ou à plusieurs de ces éléments, et si des endpoints alternatifs permettent de contourner les limitations.

Réinitialisation et récupération de compte

Le mécanisme « mot de passe oublié » constitue un chemin alternatif vers le compte. Il doit donc présenter des garanties de sécurité comparables à celles du processus d’authentification classique.

Le pentester analyse la génération du token, sa durée de vie, son unicité et son invalidation. Il vérifie également qu’il est correctement lié au compte concerné et ne peut pas être utilisé plusieurs fois.

Une requête peut par exemple prendre la forme suivante :

POST /api/password/reset HTTP/2
Host: app.example.com
Content-Type: application/json

{
  "token": "3bddf54f...",
  "new_password": "NewPassword123!"
}

L’analyse ne s’arrête pas au caractère aléatoire du token. L’auditeur teste ce qui se produit lorsqu’un nouveau token est demandé, lorsque le mot de passe est modifié par un autre moyen ou lorsqu’un token déjà utilisé est rejoué.

Il observe également la façon dont les liens sont générés. Une application qui construit une URL de réinitialisation à partir d’un header Host ou X-Forwarded-Host insuffisamment contrôlé peut, dans certains scénarios, envoyer un lien contenant un domaine contrôlé par l’attaquant.

Le changement d’adresse e-mail mérite la même attention car cette adresse sert très souvent à récupérer le compte. Si le workflow de changement d’adresse est moins protégé que le changement de mot de passe, il peut devenir la voie la plus simple vers une prise de contrôle du compte.

Authentification multifacteur

La présence d’un MFA ne garantit pas automatiquement que le processus complet soit sécurisé.

Prenons une authentification composée de :

POST /api/login

puis :

POST /api/mfa/verify

Après la première étape, le serveur peut déjà créer une session temporaire contenant l’identité de l’utilisateur. Le pentester vérifie alors si cette session permet d’accéder à certaines fonctions avant la validation du second facteur.

Il teste également les parcours alternatifs : récupération du MFA, codes de secours, modification du numéro associé, enregistrement d’un nouvel appareil ou désactivation du second facteur.

Une authentification multifacteur robuste sur le parcours principal peut perdre une grande partie de son efficacité si un workflow secondaire permet de contourner cette vérification.

OAuth 2.0 et OpenID Connect

OAuth 2.0 et OpenID Connect sont largement utilisés pour le SSO et la délégation d’accès. OAuth est principalement destiné à déléguer des permissions tandis qu’OpenID Connect ajoute une couche d’identité permettant à une application de savoir quel utilisateur s’est authentifié.

Cette distinction a des conséquences directes sur les tests : un access token OAuth n’est pas automatiquement une preuve d’identité et un ID Token OpenID Connect ne doit être accepté que dans le contexte pour lequel il a été émis.

Cartographie du flux OAuth/OIDC

Avant de rechercher une vulnérabilité, l’auditeur reconstitue précisément le flux.

Une requête peut ressembler à :

GET /authorize?client_id=web-client&redirect_uri=https%3A%2F%2Fapp.example.com%2Fcallback&response_type=code&scope=openid%20profile%20email&state=8e22c... HTTP/2
Host: id.example.com

Le pentester identifie le client, le fournisseur d’identité, le redirect_uri, les scopes, le type de réponse ainsi que la présence éventuelle de state, nonce et PKCE. Il observe ensuite l’échange du code d’autorisation et la manière dont les tokens obtenus sont consommés par l’application.

Cette cartographie permet d’éviter une erreur fréquente en audit : tester des paramètres isolément sans comprendre quelle partie du flux leur fait confiance et à quel moment.

Validation des redirect URI

Le redirect_uri détermine l’adresse vers laquelle l’utilisateur sera renvoyé après l’autorisation. Une validation trop permissive peut permettre de rediriger le navigateur vers une destination contrôlée par un attaquant et d’exposer un code d’autorisation ou un token.

Le RFC 9700 recommande une comparaison exacte des URI préenregistrées, en dehors du cas spécifique de certains ports localhost pour applications natives. Il déconseille également les open redirectors sur les composants OAuth.

Le pentester peut donc comparer des variations telles que :

https://app.example.com/callback
https://app.example.com/callback/
https://app.example.com.evil.example/callback
https://app.example.com/callback?next=https://evil.example

Il vérifie également si le callback légitime contient lui-même une fonctionnalité de redirection ouverte. Une validation correcte du domaine par l’Authorization Server peut être rendue inutile si l’URL autorisée redirige ensuite arbitrairement le navigateur.

state, nonce et PKCE

state permet notamment de relier une réponse OAuth au navigateur ayant initié la demande. En OpenID Connect, nonce lie un ID Token à une transaction donnée et contribue à limiter certains scénarios de rejeu et de confusion de sessions.

PKCE ajoute un secret éphémère créé par le client. Le client envoie d’abord un code_challenge, puis doit présenter le code_verifier correspondant au moment de l’échange du code d’autorisation.

Le pentester ne vérifie pas uniquement que ces valeurs existent. Il cherche à déterminer si elles sont réellement validées, si elles sont transactionnelles, si elles sont correctement liées à la session et si le serveur refuse une tentative de downgrade de PKCE.

La méthode S256 est attendue pour éviter d’exposer directement le verifier dans la requête d’autorisation. Le RFC 9700 impose PKCE aux clients publics utilisant l’Authorization Code Grant et le recommande également aux clients confidentiels.

Validation des tokens, audiences et scopes

Un ID Token ou un access token ne doit pas être accepté simplement parce que sa signature est valide.

L’application doit également vérifier qu’il a été émis par le bon fournisseur, pour la bonne audience, qu’il n’est pas expiré et qu’il possède les propriétés attendues.

Un token légitimement émis pour l’application A ne doit pas pouvoir être utilisé auprès de l’application B uniquement parce que les deux services font confiance au même fournisseur d’identité.

Le pentester analyse également les scopes. Un token de lecture seule ne doit pas permettre une action d’écriture, et une API doit vérifier elle-même que le token qui lui est présenté est destiné à cette ressource et à cette action. Le principe du moindre privilège doit être appliqué au token lui-même, pas seulement à l’utilisateur dans l’interface.

Refresh tokens et rejeu

Les refresh tokens permettent d’obtenir de nouveaux access tokens sans demander une nouvelle authentification complète à l’utilisateur. Leur durée de vie est donc souvent plus longue et leur compromission peut avoir un impact important.

Le pentester vérifie ce qui se passe après une déconnexion, un changement de mot de passe ou une révocation de session. Il observe également si le refresh token peut être utilisé plusieurs fois et si une rotation est mise en place.

Pour les clients publics, le RFC 9700 demande que les refresh tokens soient liés à l’émetteur ou protégés par une rotation permettant de détecter leur rejeu. L’objectif est d’éviter qu’un token volé puisse être utilisé parallèlement au token légitime sans que l’anomalie soit détectée.

SAML et SSO

SAML reste très présent dans les environnements professionnels. Son fonctionnement repose sur l’échange de messages XML entre un Identity Provider et un Service Provider. Les assertions peuvent contenir l’identité de l’utilisateur, ses attributs et des informations sur le contexte d’authentification.

La complexité de XML Signature et la multiplicité des champs de contexte rendent les erreurs d’implémentation particulièrement sensibles. Lors d’un pentest web, l’auditeur ne se contente donc pas de vérifier qu’une signature apparaît dans le document : il analyse précisément ce qui est signé, ce qui est consommé par l’application et dans quel contexte l’assertion est acceptée.

Validation de la signature et XML Signature Wrapping

Le Service Provider doit s’assurer que l’assertion utilisée pour construire la session est exactement celle dont la signature a été validée.

Dans un scénario de XML Signature Wrapping, un document peut contenir un élément légitimement signé et un second élément contrôlé par l’attaquant. Si la bibliothèque de validation vérifie correctement le premier élément mais que la logique métier sélectionne ensuite le second, la vérification cryptographique n’apporte plus la garantie attendue.

Le pentester analyse donc la structure du XML, les références de signature et les règles de sélection des assertions. Il vérifie aussi que le schéma XML est strictement validé et que les éléments inattendus ou dupliqués ne sont pas tolérés de manière ambiguë.

Audience, Destination, Recipient et InResponseTo

Une assertion SAML valide n’est pas valable pour n’importe quel Service Provider.

Le champ Audience doit correspondre au service attendu. Destination et Recipient permettent de vérifier que la réponse et l’assertion sont dirigées vers le bon endpoint. Lorsqu’un flux SP-initiated est utilisé, InResponseTo permet de relier la réponse à la demande d’authentification ayant déclenché le processus.

Le pentester vérifie donc si une assertion destinée à une autre application peut être rejouée, si un endpoint alternatif accepte la même réponse ou si la corrélation avec la requête initiale est absente.

Ce type de problème est particulièrement important dans les environnements où un même Identity Provider dessert de nombreuses applications internes et SaaS. Une assertion signée par un fournisseur de confiance ne doit jamais être considérée comme universellement valide.

Rejeu, temporalité et fédération multi-SP

Les assertions SAML contiennent généralement des contraintes temporelles comme NotBefore et NotOnOrAfter. L’application doit en tenir compte avec une tolérance d’horloge raisonnable, sans pour autant accepter indéfiniment une assertion ancienne.

Le pentester vérifie également si une même assertion peut être réutilisée plusieurs fois dans un contexte où elle devrait être à usage unique ou étroitement liée à une transaction.

Dans les fédérations complexes, il observe enfin la manière dont les attributs et rôles sont mappés entre l’Identity Provider et le Service Provider. Une valeur d’attribut mal contrôlée peut parfois produire une escalade de privilèges sans aucune faiblesse cryptographique : la signature est parfaitement valide, mais le mapping transforme une information insuffisamment fiable en rôle administrateur.

Gestion des sessions et JWT

Après l’authentification, l’application doit conserver l’identité de l’utilisateur pendant toute la session. Le pentester analyse la génération et l’invalidation des sessions ainsi que la protection des cookies.

Les attributs Secure, HttpOnly ou SameSite sont étudiés selon le contexte. L’auditeur vérifie également ce qui se passe après une déconnexion, un changement de mot de passe ou une modification des privilèges. Une ancienne session ne devrait pas nécessairement rester utilisable lorsque l’événement de sécurité impose sa révocation.

Les JWT nécessitent une analyse particulière. Un JWT est un format de token contenant des claims. Il peut être signé pour protéger son intégrité, mais la présence d’une signature ne suffit pas à rendre son utilisation sûre.

Validation cryptographique du JWT

Un JWT signé contient typiquement un header, un ensemble de claims et une signature.

L’auditeur vérifie d’abord que l’application refuse les tokens non signés et qu’elle n’accepte que les algorithmes explicitement attendus. Les anciennes vulnérabilités autour de alg: none ont rendu le sujet connu, mais la règle reste importante : le serveur ne doit pas laisser le token choisir arbitrairement la politique cryptographique avec laquelle il sera validé.

Une configuration sûre impose une liste fermée d’algorithmes acceptés et associe chaque type de clé au mécanisme attendu. Les bibliothèques récentes offrent généralement des protections, mais une mauvaise configuration peut réintroduire une confusion entre MAC et signature asymétrique.

Validation des claims

Après la vérification de la signature, l’application doit valider le contexte du token.

{
  "iss": "https://id.example.com",
  "aud": "customer-api",
  "sub": "user-4815",
  "exp": 1787662800,
  "nbf": 1787661000
}

iss doit correspondre à l’émetteur attendu. aud doit inclure le service qui reçoit le token. exp et nbf encadrent sa période de validité. Selon l’usage, d’autres claims comme jti, azp, scope ou des rôles applicatifs peuvent également influencer les décisions de sécurité.

Le pentester teste donc les erreurs de contexte : token d’une autre audience, token expiré, token émis par un autre tenant, valeurs de rôle incohérentes ou traitement différent entre plusieurs services.

Headers de clé et confusion de clés

Certains headers JOSE permettent de sélectionner ou de fournir des informations sur la clé utilisée : kid, jwk, jku, x5u ou x5c notamment.

Une application vulnérable peut faire confiance à une URL ou une clé indiquée directement par le token sans vérifier qu’elle appartient à un ensemble approuvé. Dans d’autres cas, une mauvaise gestion de kid peut conduire à sélectionner une clé inattendue.

Le pentester cherche donc à comprendre d’où vient réellement le matériel cryptographique et qui contrôle la décision de sélection. La bonne question n’est pas seulement « la signature est-elle valide ? », mais « valide selon quelle clé et pourquoi cette clé est-elle digne de confiance ? ».

Les confusions entre algorithmes asymétriques et MAC constituent une autre famille historique. Une clé publique destinée à vérifier une signature ne doit pas pouvoir être réinterprétée comme secret HMAC pour valider un token forgé.

Expiration, révocation et renouvellement

Les JWT sont souvent utilisés parce qu’ils permettent à un service de vérifier un token sans interroger une session centrale à chaque requête. Cette autonomie complique cependant la révocation immédiate.

Le pentester analyse donc le compromis entre durée de vie du token et mécanismes de révocation. Un access token très long augmente l’impact d’un vol ; un token court nécessite un mécanisme de renouvellement sécurisé.

L’auditeur vérifie si une déconnexion, un changement de mot de passe ou la désactivation d’un compte invalide effectivement les accès déjà délivrés. Selon l’architecture, cela peut reposer sur des listes de révocation, une version de session, un identifiant jti, des access tokens très courts ou des refresh tokens pouvant être révoqués.

Contrôles d’accès

L’authentification détermine l’identité de l’utilisateur. L’autorisation détermine ce qu’il est autorisé à faire.

Les contrôles d’accès sont donc testés sur pratiquement toutes les fonctionnalités sensibles.

Supposons qu’un utilisateur puisse récupérer son propre document :

GET /api/documents/4872 HTTP/2
Host: app.example.com
Authorization: Bearer <token_utilisateur_A>

Le pentester remplace 4872 par l’identifiant d’un document appartenant à un autre utilisateur.

Si le serveur retourne ce document sans vérifier la relation entre l’objet et la personne authentifiée, l’application présente une vulnérabilité de contrôle d’accès au niveau de l’objet.

La même logique est appliquée aux fonctions administratives, aux modifications de rôles et aux frontières entre différents tenants. Dans une application SaaS, l’isolement entre organisations est souvent l’un des contrôles les plus critiques du périmètre.

Logique métier

Les vulnérabilités de logique métier apparaissent lorsque des fonctionnalités légitimes peuvent être utilisées d’une manière qui n’avait pas été anticipée.

Une application e-commerce peut par exemple accepter une quantité décimale. Si une quantité 0.5 divise le prix par deux tandis que le processus de préparation considère toujours qu’un produit complet doit être expédié, aucun mécanisme technique classique n’est forcément « cassé ». La règle métier est simplement insuffisante.

D’autres scénarios peuvent concerner la réutilisation de coupons, le contournement d’une approbation, l’inversion de l’ordre des étapes, l’utilisation d’un statut intermédiaire ou l’exécution concurrente de plusieurs opérations.

Ces vulnérabilités nécessitent presque toujours une compréhension manuelle de l’application. Elles illustrent pourquoi une checklist de vulnérabilités connues ne suffit pas à représenter la profondeur d’un pentest.

APIs REST

Une API expose directement la logique métier et les données à travers des endpoints structurés.

Le pentester commence par cartographier les routes utilisées et recherche également les anciennes versions ou endpoints non documentés :

/api/v1/
/api/v2/
/api/internal/
/api/admin/

L’OWASP API Security Top 10 accorde une place centrale aux problèmes d’autorisation : BOLA, Broken Object Property Level Authorization et Broken Function Level Authorization figurent dans les cinq premières catégories.

Le pentester analyse donc les contrôles d’autorisation au niveau des objets et des fonctions, les propriétés pouvant être modifiées, les limitations de ressources et les workflows susceptibles d’être automatisés abusivement.

La mass assignment constitue un bon exemple. Une requête légitime peut contenir :

{
  "display_name": "Alice",
  "language": "fr"
}

Le pentester ajoute une propriété découverte ailleurs :

{
  "display_name": "Alice",
  "language": "fr",
  "role": "administrator"
}

Si l’API transmet automatiquement toutes les propriétés reçues à l’objet interne, une donnée qui ne devait jamais être modifiable peut devenir contrôlable par l’utilisateur.

L’auditeur s’intéresse aussi à la consommation de ressources. Un endpoint de génération de PDF, de recherche ou d’export peut être techniquement sécurisé mais exposé à une consommation disproportionnée si l’utilisateur contrôle le volume de données ou le nombre d’opérations coûteuses.

Enfin, l’API peut être exposée à des abus de flux métier : réservation massive de places, création automatisée de ressources rares, multiplication de demandes coûteuses ou contournement de limites qui ne sont pas directement liées à une vulnérabilité de code.

APIs GraphQL

GraphQL permet au client de spécifier directement les objets et propriétés qu’il souhaite récupérer. Cette flexibilité nécessite des tests spécifiques.

Le pentester cherche à comprendre le schéma à partir de l’introspection lorsqu’elle est disponible, mais également des requêtes envoyées par l’application, des erreurs et des fichiers JavaScript.

Les autorisations doivent ensuite être vérifiées au niveau des objets mais aussi des champs et des resolvers. Un utilisateur peut être autorisé à connaître le nom d’un collègue sans être autorisé à récupérer ses informations de facturation.

Une mutation telle que :

mutation {
  deleteDocument(id: "doc-8294") {
    success
  }
}

doit donc contrôler que l’utilisateur a réellement le droit de supprimer ce document particulier.

L’auditeur analyse également les aliases et le batching. Une seule requête HTTP peut contenir de multiples opérations logiques, ce qui peut rendre insuffisant un rate limiting appliqué uniquement au nombre de requêtes réseau.

Il examine enfin la profondeur et le coût des requêtes. Une requête très imbriquée peut provoquer un volume important d’appels à la base de données ou aux microservices, notamment lorsque les resolvers souffrent d’un problème N+1. L’enjeu de sécurité ne se limite donc pas au nombre de champs demandés, mais au coût réel de leur résolution côté serveur.

Fonctionnalités de paiement

Lorsqu’une application traite des transactions, le pentester s’intéresse surtout à la façon dont le workflow de paiement est intégré.

Une requête peut contenir :

{
  "product_id": 471,
  "quantity": 1,
  "unit_price": 129.90
}

Le simple fait que unit_price soit envoyé par le client n’est pas nécessairement une vulnérabilité. Le serveur peut parfaitement recalculer le prix à partir de sa propre base.

Le test consiste donc à modifier la valeur et à observer le comportement réel. La même logique s’applique aux coupons, frais de livraison, statuts de paiement, remboursements et webhooks envoyés par le prestataire de paiement.

Le pentester vérifie aussi les différences de temporalité : paiement accepté mais commande non encore finalisée, remboursement déclenché avant la mise à jour du statut, webhook rejouable ou opération de confirmation pouvant être appelée plusieurs fois.

Upload et traitement de fichiers

Une fonctionnalité d’upload crée une frontière entre des données entièrement contrôlées par l’utilisateur et un système chargé de les stocker puis éventuellement de les traiter.

L’auditeur cherche à comprendre comment le type est vérifié, où le fichier est enregistré, comment son nom est généré et comment il sera servi aux autres utilisateurs.

Une validation reposant uniquement sur l’extension ou le Content-Type fourni dans la requête peut être insuffisante. Le risque dépend ensuite de l’usage.

Un SVG servi directement dans le navigateur peut créer une surface XSS. Un document analysé par une bibliothèque vulnérable peut exposer le back-end. Un fichier stocké dans un répertoire exécutable peut, dans certaines architectures, devenir une voie vers une RCE. Un nom de fichier réutilisé sans normalisation peut également ouvrir la voie à un path traversal.

L’ensemble du cycle de vie doit donc être analysé : réception, validation, stockage, transformation, antivirus éventuel, téléchargement, rendu dans le navigateur et suppression.

WebSockets et communications temps réel

Les WebSockets maintiennent une connexion bidirectionnelle entre le navigateur et le serveur. Une fois cette connexion établie, chaque message doit continuer à faire l’objet de contrôles de sécurité.

Prenons :

{
  "action": "get_document",
  "document_id": "4821"
}

Le serveur doit vérifier que l’utilisateur possède réellement les droits sur 4821. Une connexion déjà authentifiée ne transforme pas chaque message ultérieur en opération implicitement autorisée.

L’auditeur s’intéresse également à l’établissement de la connexion. Lorsqu’un WebSocket utilise automatiquement les cookies de session sans vérifier correctement le header Origin, certaines configurations peuvent être exposées à du Cross-Site WebSocket Hijacking.

Il vérifie enfin les limites de taille, de fréquence et de complexité des messages ainsi que le comportement lors d’une révocation de session. Une connexion persistante ne devrait pas continuer indéfiniment à bénéficier de droits qui viennent d’être supprimés côté serveur.

Intégrations LLM et IA générative

Les applications web intègrent de plus en plus des assistants conversationnels, des systèmes RAG et des agents capables d’utiliser des outils.

Le pentest doit alors étendre son périmètre au-delà des vulnérabilités web traditionnelles. L’auditeur cherche notamment à savoir quelles données sont envoyées au modèle, quelles sources peuvent influencer son contexte et quelles actions peuvent être exécutées à partir de ses réponses.

Une prompt injection peut tenter de modifier le comportement du modèle. Une injection indirecte peut être contenue dans un document ou une page récupérée par un système RAG.

Lorsque le modèle peut envoyer un e-mail, modifier un ticket, interroger une base de données ou appeler une API, les conséquences deviennent beaucoup plus importantes. Le pentester analyse donc surtout les contrôles déterministes qui encadrent ces capacités : permissions, validation des paramètres, séparation des rôles, confirmations avant les actions sensibles et limitation des privilèges accordés aux outils.

La sortie du LLM doit également être considérée comme une donnée non fiable. Une réponse générée puis injectée directement dans du HTML, utilisée pour construire une requête ou transmise à un interpréteur peut transformer une faiblesse spécifique à l’IA en vulnérabilité applicative classique.

Principales vulnérabilités identifiées lors d’un pentest web

La liste suivante ne constitue pas une checklist exhaustive. Elle présente les grandes familles de vulnérabilités fréquemment étudiées lors d’un audit moderne et doit toujours être adaptée à la technologie, à l’architecture et au contexte métier de l’application.

L’OWASP Top 10 place les contrôles d’accès défaillants en première position et couvre également les mauvaises configurations de sécurité, les défaillances de supply chain logicielle, les problèmes cryptographiques, les injections, les erreurs de conception, les défaillances d’authentification, les problèmes d’intégrité logicielle ou des données, l’insuffisance de journalisation et la mauvaise gestion des conditions exceptionnelles.

Ce référentiel fournit une vision des grandes causes de risque, mais un pentest doit aller au-delà de ces dix catégories pour couvrir les surfaces spécifiques de l’application.

Contrôles d’accès défaillants, IDOR et BOLA

Une IDOR ou BOLA apparaît lorsqu’une application utilise un identifiant contrôlé par le client pour sélectionner un objet sans vérifier correctement que l’utilisateur courant est autorisé à y accéder.

Par exemple :

GET /api/projects/5731 HTTP/2
Host: app.example.com
Authorization: Bearer <token_A>

peut être modifié en :

GET /api/projects/5818 HTTP/2
Host: app.example.com
Authorization: Bearer <token_A>

Si 5818 appartient à un autre utilisateur mais que la réponse est tout de même retournée, l’autorisation est défaillante.

L’utilisation d’un UUID plutôt que d’un entier peut rendre l’identifiant plus difficile à deviner, mais ne corrige pas le problème. Un UUID peut être récupéré dans une réponse, un export, une notification, un lien partagé ou un autre endpoint. Le contrôle de sécurité doit donc être appliqué indépendamment de la prédictibilité de la référence.

Le pentester ne teste pas uniquement la lecture. Il modifie également les verbes HTTP, les identifiants imbriqués, les relations parent-enfant et les opérations de modification ou de suppression. Une API peut refuser GET /documents/B tout en acceptant DELETE /documents/B, ou vérifier l’organisation au niveau du projet sans vérifier que la pièce jointe appartient effectivement à ce projet.

Dans un environnement multi-tenant, la BOLA est particulièrement critique. Une seule omission de contrôle peut permettre de franchir la frontière logique entre deux clients et exposer des données appartenant à des organisations entièrement distinctes.

Broken Function Level Authorization

Une Broken Function Level Authorization permet à un utilisateur d’exécuter une fonctionnalité normalement réservée à un autre rôle.

Un utilisateur standard peut par exemple avoir accès à :

GET /api/users/218 HTTP/2

mais ne devrait pas pouvoir appeler :

DELETE /api/admin/users/218 HTTP/2

Masquer le bouton correspondant dans l’interface n’apporte aucune protection. Le contrôle doit être appliqué au niveau du serveur.

Le pentester recherche donc les routes administratives dans le JavaScript, les fichiers de documentation, les conventions de nommage, les réponses d’erreur et les appels effectués avec un compte privilégié. Il rejoue ensuite ces opérations avec des rôles moins privilégiés.

Les faiblesses peuvent également être plus subtiles qu’un simple endpoint /admin/. Une même route peut accepter un paramètre action, status ou role qui expose implicitement une fonction réservée à un autre profil.

Mass assignment et contrôle des propriétés

Le mass assignment apparaît lorsqu’un framework associe automatiquement les propriétés reçues dans une requête aux propriétés internes d’un objet sans liste explicite de champs modifiables.

Une propriété non visible dans l’interface peut ainsi devenir modifiable si l’API ne limite pas précisément les attributs autorisés.

Par exemple, une requête légitime peut être :

{
  "display_name": "Alice",
  "language": "fr"
}

Le pentester peut tester :

{
  "display_name": "Alice",
  "language": "fr",
  "role": "administrator",
  "is_verified": true
}

Si le back-end accepte directement les propriétés supplémentaires, une décision de sécurité normalement contrôlée par le serveur peut devenir manipulable par le client.

Le même problème existe en lecture. Une API qui sérialise l’intégralité de son modèle interne peut exposer des propriétés que l’interface n’affiche jamais : tokens de réinitialisation, indicateurs internes, identifiants techniques ou informations appartenant à un autre contexte. L’OWASP API Security Top 10 regroupe ces problèmes dans la catégorie Broken Object Property Level Authorization.

Injection SQL

Une injection SQL apparaît lorsqu’une donnée contrôlée par l’utilisateur influence directement la structure d’une requête au lieu d’être traitée comme une simple valeur.

Considérons :

SELECT id, name, price
FROM products
WHERE category = '<categorie>';

Si categorie est concaténée directement à la requête, un attaquant peut tenter d’injecter de la syntaxe SQL afin de modifier son comportement.

Le pentester cherche d’abord à comprendre le contexte : paramètre de chaîne, valeur numérique, clause ORDER BY, recherche plein texte, nom de colonne ou autre construction dynamique. Il adapte ensuite les tests à la technologie et observe les erreurs, différences de contenu, délais ou comportements conditionnels.

Une injection ne doit pas être évaluée uniquement selon le volume de données qu’elle permet de lire. Selon les permissions du compte de base de données et les fonctionnalités du SGBD, elle peut permettre de modifier des données, de contourner des contrôles métier, d’écrire des fichiers ou, dans certaines configurations, de contribuer à une exécution de commandes.

La remédiation repose en priorité sur des requêtes paramétrées ou des APIs qui séparent structure SQL et valeurs. Tenter de supprimer certains caractères ou mots-clés est fragile, car le problème ne vient pas d’un caractère précis mais du mélange entre données non fiables et syntaxe de requête.

Cross-Site Scripting (XSS)

Une XSS apparaît lorsqu’une donnée contrôlée par un attaquant est interprétée comme du contenu actif par le navigateur dans le contexte de l’application.

Elle peut être réfléchie, stockée ou liée exclusivement aux transformations effectuées dans le DOM.

Son impact ne doit pas être résumé au vol de cookies. Un cookie protégé par HttpOnly n’est par exemple pas directement lisible par JavaScript. Une XSS peut néanmoins permettre d’effectuer des actions avec la session de la victime, de lire des informations affichées dans l’interface, de récupérer certains tokens côté client, de modifier complètement le contenu de la page ou de réaliser un phishing particulièrement crédible au sein du domaine légitime.

Le pentester cherche donc à identifier le contexte exact d’injection : contenu HTML, attribut, URL, chaîne JavaScript, template côté client ou manipulation du DOM. La bonne protection dépend de ce contexte. Une donnée correctement encodée pour du HTML ne l’est pas nécessairement pour une chaîne JavaScript ou un attribut d’URL.

Il étudie également les transformations successives. Une donnée peut être assainie correctement à un premier endroit puis décodée, concaténée ou réinterprétée plus tard, ce qui peut conduire à des scénarios de mutation XSS ou de second ordre.

Cross-Site Request Forgery (CSRF)

Une CSRF consiste à provoquer depuis un autre site une action non souhaitée dans une application où la victime est déjà authentifiée.

Le navigateur peut automatiquement transmettre les cookies de session. Si l’application ne vérifie pas suffisamment l’origine de l’action, une opération sensible peut être exécutée à l’insu de l’utilisateur.

Le pentester identifie les actions qui reposent sur une authentification automatiquement jointe par le navigateur : changement d’adresse e-mail, ajout d’un utilisateur, modification de paramètres, validation de transactions ou désactivation de protections.

Il vérifie ensuite la présence et la robustesse des tokens anti-CSRF, les attributs SameSite, les contrôles sur Origin ou Referer lorsqu’ils sont utilisés et la possibilité de contourner ces protections via des méthodes alternatives, des types de contenu différents ou des endpoints historiques.

Une API utilisant exclusivement un bearer token transmis explicitement dans un header Authorization n’est généralement pas exposée au même scénario que des endpoints utilisant uniquement des cookies, mais l’architecture complète doit être observée avant de conclure.

Server-Side Request Forgery

Une SSRF apparaît lorsque l’utilisateur peut influencer une requête envoyée par le serveur.

Une fonctionnalité peut par exemple recevoir :

POST /api/import HTTP/2
Host: app.example.com
Content-Type: application/json

{
  "url": "https://images.example.org/photo.jpg"
}

Si la destination est insuffisamment contrôlée, l’attaquant peut tenter d’utiliser le serveur pour joindre une ressource interne.

Une SSRF peut ainsi fournir un accès indirect à des APIs internes, des interfaces d’administration, des services cloud, des endpoints de métadonnées ou d’autres ressources normalement protégées par leur absence d’exposition Internet.

L’analyse ne se limite pas aux URL explicitement saisies par l’utilisateur. Webhooks, convertisseurs de documents, fonctions de prévisualisation, import d’avatars, validateurs de liens, intégrations SSO ou récupérations de métadonnées peuvent tous provoquer des requêtes serveur.

La validation est délicate car une URL peut changer de destination à travers une redirection ou une nouvelle résolution DNS. Les différentes représentations d’adresses IPv4 et IPv6, les noms internes et certains schémas non HTTP doivent également être considérés selon la bibliothèque utilisée.

Server-Side Template Injection

Une SSTI apparaît lorsqu’une donnée utilisateur devient une partie du template lui-même au lieu d’être fournie comme une simple variable au moteur de rendu.

Prenons :

template = "Hello " + user_input
return render_template_string(template)

Une expression telle que :

{{7*7}}

peut, selon le moteur, être évaluée plutôt qu’affichée littéralement.

La découverte de cette évaluation n’implique pas automatiquement une RCE. Le pentester doit identifier le moteur utilisé, le langage d’expression, le contexte d’exécution, les objets accessibles et les mécanismes de sandbox éventuels.

Certains moteurs offrent uniquement des opérations limitées ; d’autres exposent des primitives permettant de remonter vers des objets plus puissants. L’impact doit donc être démontré progressivement et sans supposer qu’un payload générique fonctionnera dans tous les environnements.

La correction consiste à conserver le template statique et à injecter les données par les mécanismes de variables fournis par le moteur, plutôt qu’à concaténer des données non fiables dans le code du template.

Path Traversal et inclusion de fichiers

Les applications manipulent fréquemment des chemins de fichiers : téléchargement de documents, génération d’archives, lecture de templates, import/export, gestion d’images ou récupération de logs. Lorsqu’une partie du chemin est contrôlée par l’utilisateur, une validation insuffisante peut permettre de sortir du répertoire prévu.

Directory Traversal

Considérons un endpoint :

GET /download?file=invoice-2026.pdf HTTP/2
Host: app.example.com

Si le serveur construit directement un chemin comme /srv/app/files/ + file, le pentester vérifie si une valeur contenant des segments de remontée peut sortir de ce répertoire.

Un test conceptuel peut être :

../../../../etc/passwd

ou, sous Windows, une variante utilisant les séparateurs appropriés.

L’objectif n’est pas nécessairement de récupérer ce fichier précis. Il s’agit de démontrer que la résolution du chemin peut atteindre une ressource située en dehors de l’espace normalement autorisé.

Le pentester recherche également des points moins évidents : noms de fichiers dans un cookie, valeurs stockées en base puis réutilisées, paramètres d’export, templates de génération ou chemins transmis dans une API JSON.

Local File Inclusion et Remote File Inclusion

Le path traversal permet généralement de lire ou manipuler un chemin. Une inclusion de fichier va plus loin lorsque l’application transmet ce chemin à un mécanisme qui charge ou interprète le contenu.

Une fonctionnalité vulnérable peut par exemple conceptuellement faire :

include($_GET['page']);

Une Local File Inclusion vise alors un fichier présent sur le serveur. Selon l’environnement, l’impact peut rester limité à la divulgation de données ou évoluer vers une exécution de code si l’attaquant peut faire inclure un contenu qu’il contrôle.

Une Remote File Inclusion existe lorsque le mécanisme d’inclusion accepte une ressource distante. L’application peut alors charger du contenu depuis une URL contrôlée par l’attaquant. Cette possibilité dépend fortement de la technologie et de sa configuration ; elle ne doit donc pas être supposée par défaut.

Le pentester distingue soigneusement lecture de fichier, inclusion et exécution. Ces trois résultats ont des impacts différents et nécessitent des preuves distinctes.

Canonicalisation et contournements de validation

Les path traversals sont souvent liés à un problème de canonicalisation : plusieurs chaînes différentes peuvent désigner le même chemin une fois normalisées par le système de fichiers ou le framework.

Un filtre qui supprime simplement ../ peut être contourné si les transformations sont réalisées dans un ordre inattendu, si des encodages sont décodés après le filtrage ou si le système accepte plusieurs séparateurs.

Le pentester observe donc la chaîne complète : décodage URL, normalisation Unicode éventuelle, remplacement de caractères, résolution des segments . et .., ajout d’extensions et transformation en chemin absolu.

La correction la plus robuste consiste généralement à ne pas laisser le client choisir directement un chemin. Lorsque cela est nécessaire, l’application peut mapper un identifiant logique vers un fichier côté serveur et vérifier, après canonicalisation, que le chemin final reste strictement contenu dans un répertoire autorisé.

Désérialisation non sécurisée

La sérialisation transforme un objet ou une structure de données en représentation transportable ou stockable. La désérialisation reconstruit ensuite cette structure dans l’application.

Le risque apparaît lorsque des données contrôlées par un utilisateur sont transmises à un mécanisme capable de recréer des objets complexes et d’exécuter des comportements associés à leur construction ou à certaines méthodes spéciales.

Contrairement à une injection SQL ou à une injection de commandes, l’attaquant ne cherche pas toujours à insérer directement une chaîne interprétée comme du code. Il cherche parfois à construire un graphe d’objets qui déclenchera indirectement une opération dangereuse.

Identifier les formats et points de désérialisation

En black box, le pentester recherche des valeurs opaques dans les cookies, paramètres, messages ou corps de requête. Certaines signatures peuvent orienter l’analyse : données Java sérialisées, objets PHP, structures Python pickle, YAML typé ou formats propriétaires encodés en Base64.

Il vérifie ensuite si l’intégrité de la donnée est protégée. Une valeur sérialisée mais correctement signée avec une clé inaccessible au client peut réduire fortement la possibilité de la modifier, sans toutefois résoudre tous les risques si un attaquant peut influencer la donnée avant la signature ou compromettre une autre partie du workflow.

En white box, la recherche est plus directe : appels à pickle.loads, ObjectInputStream, unserialize, mécanismes YAML non sûrs, sérialiseurs .NET dangereux ou bibliothèques capables de matérialiser des types arbitraires constituent des points à examiner.

Gadgets, effets de bord et validation trop tardive

Une désérialisation dangereuse repose souvent sur des « gadgets » : classes ou méthodes déjà présentes dans l’application ou ses dépendances dont le comportement peut être combiné pour produire un effet indésirable.

Le point important est que cet effet peut se produire pendant la désérialisation elle-même. Vérifier le type de l’objet *après* l’appel au désérialiseur peut donc être trop tardif : le constructeur, un setter, un hook ou une méthode spéciale a peut-être déjà déclenché l’action sensible.

Le pentester cherche à déterminer non seulement si la donnée est modifiable, mais quelles classes sont disponibles, quels effets de bord elles présentent et quelles permissions possède le processus qui les exécute.

L’impact peut être un déni de service, une modification de données, une lecture de fichier, un appel réseau ou une RCE. Il doit être évalué à partir du graphe réellement disponible dans l’application et non d’une hypothèse générique.

Désérialisation en white box

En white box, l’auditeur peut suivre le chemin complet depuis l’entrée jusqu’au désérialiseur et identifier les garde-fous éventuels.

Il vérifie si une liste de types autorisés existe, si la bibliothèque est configurée en mode sûr et si l’application pourrait utiliser un format de données plus simple comme JSON pour transporter des structures sans reconstruire des objets arbitraires.

Lorsque la désérialisation native est indispensable, l’analyse porte également sur la signature préalable des données, la séparation des privilèges, la réduction des classes accessibles et l’isolation du composant qui effectue l’opération.

Exécution de code à distance (RCE)

Une RCE permet d’exécuter du code ou des commandes dans le contexte du système cible. Elle peut être la conséquence d’une injection de commandes, d’un upload dangereux, d’une SSTI, d’une désérialisation, d’un composant tiers vulnérable ou d’une chaîne plus complexe.

Compte tenu de son impact potentiel, son exploitation pendant un pentest doit être strictement contrôlée. Le but est de démontrer le risque avec le niveau d’action minimal nécessaire.

Une preuve peut se limiter à une commande inoffensive, à la création d’un marqueur temporaire dans un environnement de test ou à un callback réseau contrôlé, selon les règles d’engagement. Exécuter des commandes invasives, modifier la configuration ou parcourir inutilement les données augmente le risque sans améliorer nécessairement la démonstration.

Après validation, l’auditeur s’intéresse au contexte d’exécution : utilisateur système, secrets accessibles, réseau interne visible, conteneurisation, identités cloud et possibilités de pivot. Une RCE dans un conteneur fortement isolé n’a pas le même rayon d’impact qu’une RCE dans un service disposant d’un rôle cloud privilégié.

Race conditions

Une race condition apparaît lorsque plusieurs opérations exécutées simultanément créent un état qui ne pourrait pas exister lors d’un traitement strictement séquentiel.

Supposons un coupon utilisable une seule fois. Le serveur :

  1. vérifie que le coupon est disponible ;
  2. applique la réduction ;
  3. marque le coupon comme utilisé.

Deux requêtes reçues presque simultanément peuvent toutes les deux passer la première vérification avant que la troisième étape ne soit exécutée.

L’auditeur cherche donc à provoquer des traitements concurrents sur des opérations présentant un état sensible : coupons, paiements, votes, crédits, réservations, créations de comptes, changements de mot de passe ou modifications d’adresse e-mail.

Les race conditions modernes ne se limitent pas à deux appels identiques. Un workflow peut présenter un état transitoire entre deux endpoints différents. Par exemple, une première requête valide temporairement une opération avant qu’une seconde n’enregistre définitivement les droits. Un attaquant peut tenter d’exploiter cette fenêtre pour appeler une troisième fonction dans un état que les développeurs pensaient inaccessible.

La correction repose généralement sur des opérations atomiques, des verrous appropriés, des contraintes de base de données, des transactions ou une conception garantissant l’idempotence et la cohérence des états.

Mauvaises configurations CORS

CORS permet à certaines origines de lire les réponses d’une application depuis un navigateur malgré la Same-Origin Policy.

Une réponse telle que :

Access-Control-Allow-Origin: https://attacker.example
Access-Control-Allow-Credentials: true

peut devenir dangereuse si l’origine fournie par la requête est reflétée ou validée de manière trop permissive.

Le navigateur de la victime peut alors transmettre sa session et permettre au site attaquant de lire une réponse authentifiée.

Le pentester teste les sous-domaines, les suffixes, les origines null lorsque le contexte le justifie et les différentes variantes susceptibles de tromper une comparaison de chaîne naïve.

CORS ne doit cependant jamais être considéré comme un mécanisme d’autorisation serveur. Un client hors navigateur peut librement définir le header Origin. Les contrôles d’accès classiques doivent donc rester indépendants de CORS.

Web cache poisoning

Les CDN, reverse proxies et caches applicatifs accélèrent la distribution des réponses. Une web cache poisoning apparaît lorsque l’attaquant peut influencer une réponse qui sera ensuite stockée sous une clé partagée avec d’autres utilisateurs.

Le pentester cherche une entrée « unkeyed », c’est-à-dire une information qui modifie la réponse du back-end sans être prise en compte dans la clé de cache. Il peut s’agir d’un header, d’un paramètre ignoré par le cache ou d’une différence de normalisation entre composants.

Si l’application génère par exemple une URL absolue à partir d’un header non inclus dans la clé, l’attaquant peut tenter de faire mettre en cache une réponse contenant son domaine. Les visiteurs suivants recevront alors le contenu empoisonné tant que l’entrée de cache reste valide.

L’impact dépend fortement de ce qui peut être injecté : redirection, script, contenu HTML, ressource importée ou simple altération d’affichage. Le pentester doit toujours isoler ses tests afin d’éviter d’affecter des utilisateurs réels.

Web cache deception

La web cache deception poursuit un objectif différent. L’attaquant cherche à faire mettre en cache une réponse privée puis à la récupérer ultérieurement sans être authentifié.

Une URL comme :

/account/settings/avatar.css

peut être interprétée comme une page privée par le back-end mais comme une ressource statique cacheable par un composant intermédiaire.

Le scénario exploite donc une divergence d’interprétation du chemin entre plusieurs composants. La victime est amenée à visiter l’URL avec sa session ; le cache enregistre la réponse ; l’attaquant la demande ensuite sans être authentifié.

Le pentester étudie la normalisation des chemins, les extensions, les délimiteurs, les règles de cache et les headers comme Cache-Control. La correction repose sur des politiques de cache cohérentes et sur l’interdiction de mettre en cache les contenus privés, indépendamment de l’apparence de l’URL.

HTTP Request Smuggling

Les architectures web modernes utilisent fréquemment plusieurs composants HTTP successifs : CDN, load balancer, WAF, reverse proxy puis serveur applicatif. Une HTTP Request Smuggling apparaît lorsque ces composants ne délimitent pas les requêtes de la même manière.

Le résultat est une désynchronisation : une partie de la requête de l’attaquant peut être considérée par un composant comme appartenant au corps courant et par le composant suivant comme le début d’une nouvelle requête.

Pourquoi la désynchronisation apparaît

En HTTP/1, la longueur d’un message peut notamment être indiquée par Content-Length ou par Transfer-Encoding: chunked. Les spécifications encadrent les interactions entre ces mécanismes, mais les implémentations et les transformations réalisées par les proxies peuvent diverger.

Lorsque le front-end et le back-end ne prennent pas la même décision, des octets laissés « en attente » sur la connexion back-end peuvent être préfixés à la requête suivante.

Le problème n’est donc pas une injection classique dans la logique applicative : il se situe dans la manière dont plusieurs parseurs HTTP interprètent la frontière des messages.

CL.TE, TE.CL et HTTP/2 downgrading

Les classifications historiques CL.TE et TE.CL décrivent quel header est utilisé par le front-end et le back-end. Dans un cas, le front-end se fie à Content-Length tandis que le back-end suit Transfer-Encoding; dans l’autre, l’ordre est inversé.

Les environnements HTTP/2 modifient le paysage mais n’éliminent pas toujours le risque. HTTP/2 dispose d’un mécanisme de longueur plus robuste, mais de nombreuses architectures terminent HTTP/2 au niveau du front-end puis convertissent les requêtes vers HTTP/1 pour les systèmes back-end.

Cette opération de downgrading peut introduire de nouvelles ambiguïtés si les headers ou pseudo-headers HTTP/2 sont transformés de manière inattendue. Les recherches récentes sur le sujet incluent également des variantes de request splitting, de tunnelling et de désynchronisation côté client.

Impacts et précautions de test

Les impacts potentiels sont importants : contournement de contrôles appliqués uniquement par le front-end, empoisonnement de cache, capture ou perturbation de requêtes d’autres utilisateurs, accès à des routes internes ou corruption de la file de réponses.

Ces tests sont cependant plus risqués que de nombreux tests applicatifs classiques, car une désynchronisation peut affecter une connexion partagée et donc le trafic d’autres utilisateurs.

En production, l’auditeur doit privilégier des techniques de détection à faible impact, utiliser des marqueurs contrôlés et respecter strictement les règles d’engagement. La preuve d’une désynchronisation ne justifie pas automatiquement de poursuivre vers un scénario affectant des utilisateurs réels.

Host Header Injection

Certaines applications utilisent le header Host ou des headers transmis par un reverse proxy pour construire des URLs absolues.

Un workflow de récupération de mot de passe peut alors devenir vulnérable si cette valeur n’est pas correctement contrôlée.

Par exemple :

POST /forgot-password HTTP/1.1
Host: attacker.example

pourrait conduire l’application à générer :

https://attacker.example/reset?token=<secret>

La victime reçoit un e-mail provenant du service légitime, mais le lien transmet le token au domaine de l’attaquant.

Le pentester analyse également X-Forwarded-Host, Forwarded et d’autres headers de proxy, ainsi que les différences entre le host utilisé pour le routage et celui utilisé par le code applicatif.

La correction consiste généralement à configurer explicitement l’URL publique de l’application et à ne pas construire les liens sensibles à partir de données de requête non fiables.

Prototype Pollution

En JavaScript, la plupart des objets héritent de propriétés via une chaîne de prototypes. Une prototype pollution apparaît lorsqu’un attaquant parvient à ajouter ou modifier une propriété sur un prototype partagé au lieu de modifier seulement l’objet qu’il contrôle directement.

Cette vulnérabilité est particulière car la pollution elle-même n’est souvent qu’une primitive. L’impact dépend d’un second élément : un « gadget » qui lit la propriété polluée et l’utilise dans un contexte sensible.

Source de pollution et propriétés dangereuses

Les sources classiques se trouvent dans les fonctions qui fusionnent, copient ou construisent récursivement des objets à partir d’une entrée utilisateur. Des clés comme __proto__, constructor et prototype méritent une attention particulière selon l’implémentation.

Une charge conceptuelle peut être :

{
  "__proto__": {
    "isAdmin": true
  }
}

Si la fonction de fusion assigne naïvement cette structure, des objets créés ultérieurement peuvent hériter de isAdmin alors que cette propriété ne leur a jamais été explicitement attribuée.

Le pentester vérifie soigneusement que le comportement observé provient réellement du prototype et non d’une propriété normale du même objet.

Recherche de gadgets côté client et côté serveur

Une pollution n’a un impact que si une partie du code consomme la propriété d’une manière intéressante.

Côté client, un gadget peut utiliser une propriété héritée pour définir une URL de script, une option HTML, une configuration de sanitizer ou une chaîne transmise à un sink DOM. La pollution peut alors devenir une voie vers une DOM XSS.

Côté Node.js, un gadget serveur peut influencer des options passées à un processus enfant, un moteur de template, une bibliothèque HTTP ou un contrôle d’autorisation. Le contexte est cependant très dépendant des bibliothèques et versions réellement présentes.

Le pentester cherche donc d’abord les sources de pollution, puis suit les lectures de propriétés susceptibles d’être contrôlées indirectement. En white box, des recherches ciblées dans le code et les dépendances accélèrent fortement cette étape.

Pollution sans exploitation et validation de l’impact

Il est fréquent de pouvoir démontrer qu’une propriété apparaît sur Object.prototype sans trouver immédiatement un gadget exploitable.

Dans ce cas, il serait excessif de conclure automatiquement à une prise de contrôle ou une RCE. Le rapport doit distinguer clairement la primitive de pollution de son impact démontré.

La correction repose généralement sur l’utilisation d’objets sans prototype lorsqu’elle est adaptée, la validation stricte des clés, le rejet des propriétés dangereuses et l’emploi de fonctions de fusion ou bibliothèques corrigées. Les mises à jour de dépendances sont particulièrement importantes lorsque la source se trouve dans une bibliothèque tierce.

Mauvaises configurations et composants vulnérables

De nombreuses compromissions reposent sur des éléments plus simples : mode debug activé, interface d’administration exposée, credentials par défaut, fichier de sauvegarde accessible, bucket cloud public, erreurs très verbeuses ou composant non corrigé.

Ces problèmes peuvent sembler moins sophistiqués mais devenir déterminants lorsqu’ils fournissent l’information ou l’accès nécessaire à une chaîne d’exploitation plus importante.

Le pentester vérifie donc les headers, bannières, fichiers connus, endpoints de diagnostic, consoles d’administration, répertoires de versionnement et artefacts de déploiement. Il rapproche les versions identifiées des vulnérabilités publiques lorsque cela est possible, tout en évitant de conclure qu’une version est exploitable uniquement sur la base d’un numéro de version supposé.

Supply chain et intégrité des composants

L’OWASP Top 10:2025 introduit explicitement les Software Supply Chain Failures parmi les grandes catégories de risque. Pour une application web, la surface comprend les dépendances de développement, packages, images de conteneurs, pipelines CI/CD, artefacts de build et ressources chargées depuis des tiers.

Un pentest ponctuel ne remplace pas une stratégie complète de sécurité de la supply chain, mais certaines faiblesses sont observables pendant l’audit : dépendance obsolète exposée, package interne résolu depuis un registre public, JavaScript tiers chargé sans contrôle d’intégrité, artefact de build contenant des secrets ou endpoint de mise à jour non authentifié.

En white box, l’auditeur peut également examiner les manifests et lockfiles, la provenance des dépendances et certains scripts de build. L’objectif n’est pas de produire un inventaire SBOM exhaustif sauf si le périmètre le prévoit, mais d’identifier les scénarios où une compromission d’un composant ou du processus de livraison aurait un impact direct sur l’application.

Méthodologie d’un pentest d’application web

Un pentest professionnel suit une démarche structurée afin de couvrir le périmètre de manière cohérente, reproductible et proportionnée aux risques. Les phases ne sont pas toujours strictement linéaires : une information découverte pendant l’exploitation peut conduire l’auditeur à revenir à la cartographie ou à tester une nouvelle hypothèse.

La méthodologie fournit néanmoins un cadre commun et évite qu’un audit repose uniquement sur l’intuition ou sur une succession d’outils.

Cadrage et règles d’engagement

Avant les tests, le périmètre doit être défini précisément. Cette phase identifie les domaines, applications, APIs et environnements autorisés ainsi que les éventuelles restrictions.

Le cadrage précise les comptes mis à disposition, les rôles à tester, les données de test utilisables, les plages horaires éventuelles et les contacts à prévenir lorsqu’une vulnérabilité critique est découverte.

Certaines opérations peuvent nécessiter une validation particulière : modification de données réelles, exploitation d’une RCE, envoi massif de requêtes, interaction avec des services tiers, tests de déni de service, récupération de secrets ou utilisation de comptes appartenant à de vrais utilisateurs.

Les règles d’engagement définissent également les limites de la preuve. Un pentester n’a pas besoin d’exfiltrer une base complète pour démontrer une injection SQL ni de supprimer une ressource réelle pour prouver une BOLA en écriture. Cette discipline fait partie intégrante de la qualité d’un audit.

Reconnaissance

La reconnaissance permet de collecter les premières informations sur la cible.

Dans un scénario black box, l’auditeur peut rechercher des domaines et sous-domaines, technologies, dépôts publics, documents accessibles, anciennes versions de pages, fuites de credentials connues, entrées DNS ou informations techniques exposées.

Cette phase est parfois décrite comme passive, mais la frontière dépend des techniques utilisées. Consulter une source publique ne génère pas la même interaction avec la cible qu’énumérer activement des endpoints ou des services.

L’objectif n’est pas d’accumuler des informations sans finalité. Chaque élément doit servir à formuler des hypothèses : une technologie particulière suggère certains fichiers ; un sous-domaine historique peut héberger une ancienne API ; un dépôt public peut révéler un endpoint, un nom de rôle ou une intégration oubliée.

Énumération et cartographie

Une fois l’application accessible, le pentester cherche à comprendre son fonctionnement réel.

Il parcourt les fonctionnalités, analyse les échanges HTTP, identifie les endpoints d’API, les méthodes, les paramètres, les rôles et les différents parcours utilisateurs. Il observe également les changements d’état : création, validation, annulation, suppression, changement de propriétaire ou transitions de statut.

Il cherche les ressources non directement visibles : endpoints historiques, routes d’administration, documentation Swagger/OpenAPI, schémas GraphQL, fichiers JavaScript, source maps, anciennes versions, paramètres non exposés par l’interface ou fonctionnalités réservées à certains états de l’application.

Cette cartographie est centrale. Une vulnérabilité de contrôle d’accès ne peut être testée efficacement sans comprendre les relations entre utilisateurs, organisations et objets. Une faille de logique métier ne peut être identifiée sans savoir ce que le workflow est censé empêcher.

Analyse des vulnérabilités

L’auditeur teste ensuite les hypothèses formulées pendant la cartographie.

Certains contrôles sont automatisables : découverte de contenu, recherche de patterns, analyse de headers, certaines injections ou comparaison de réponses. Mais les manipulations manuelles restent centrales.

Le pentester modifie les paramètres, rejoue les requêtes avec plusieurs comptes, change l’ordre des opérations, supprime certains champs, en ajoute d’autres et observe les différences de comportement.

Il ne recherche pas uniquement des vulnérabilités connues. Il cherche surtout les incohérences entre ce que le système devrait autoriser et ce qu’il permet réellement.

Une différence de statut HTTP, une propriété supplémentaire dans une réponse ou une route accessible avec un rôle inattendu peut devenir le point de départ d’un scénario plus important.

Exploitation contrôlée

Une vulnérabilité doit généralement être validée afin de déterminer son impact réel.

L’objectif n’est jamais d’endommager le système. Pour une IDOR, accéder au document d’un second compte de test peut suffire. Pour une injection, démontrer la modification contrôlée du comportement de la requête peut suffire sans extraire massivement les données.

Le niveau d’exploitation dépend du contexte et des règles d’engagement. Une preuve technique doit être suffisamment forte pour éviter les faux positifs mais suffisamment limitée pour ne pas créer de risque inutile.

L’auditeur documente les prérequis, les actions effectuées et les résultats. Cette traçabilité est essentielle pour le rapport mais également pour pouvoir arrêter immédiatement un scénario si un comportement inattendu apparaît.

Chaînage des vulnérabilités

Cette étape est essentielle car plusieurs faiblesses peuvent se renforcer mutuellement.

Une fuite d’information considérée comme faible peut fournir une donnée nécessaire à l’exploitation d’une IDOR. Une SSRF peut permettre d’accéder à une interface interne qui présente elle-même une vulnérabilité. Un compte standard compromis peut devenir le point de départ d’une escalade vers un rôle administratif.

Le pentester réévalue donc régulièrement les findings à la lumière des nouvelles informations. Une vulnérabilité de sévérité moyenne prise isolément peut devenir critique lorsqu’elle fournit la primitive manquante pour un autre scénario.

Cette capacité à construire des chaînes d’exploitation est l’une des principales différences entre un pentest approfondi et un simple inventaire de faiblesses.

Post-exploitation

Lorsqu’une compromission est démontrée et que le périmètre l’autorise, le pentester analyse ce qu’un attaquant pourrait accomplir ensuite.

Une RCE peut révéler des credentials, des clés de service ou des secrets cloud. Une session administrateur peut fournir un accès à d’autres tenants. Une API interne découverte via SSRF peut donner accès à un réseau ou à des données non exposées publiquement.

L’objectif est de comprendre le rayon d’impact, pas de maximiser la compromission. L’auditeur privilégie les preuves minimales et évite les actions susceptibles d’altérer le service, de persister dans l’environnement ou d’accéder inutilement à des données réelles.

Selon le type de mission, certaines actions de post-exploitation peuvent être explicitement exclues. Dans ce cas, le rapport peut décrire l’impact potentiel sans le démontrer intégralement.

Reporting et remédiation

Le rapport doit transformer les résultats techniques en actions concrètes.

Une vulnérabilité doit être décrite avec son contexte, ses prérequis, son mode d’exploitation, son impact et la correction recommandée. Les éléments de preuve doivent permettre aux équipes de comprendre le problème et de le reproduire dans un environnement contrôlé.

Les recommandations doivent surtout traiter la cause. Une IDOR ne se corrige pas en remplaçant un identifiant numérique par un UUID ; elle se corrige en appliquant un contrôle d’autorisation serveur. Une injection SQL ne se corrige pas avec une blacklist de caractères mais en séparant les données de la structure de requête.

Lorsque plusieurs findings proviennent d’un même défaut architectural, le rapport doit le signaler. Corriger chaque endpoint indépendamment sans traiter le pattern qui a produit le problème risque de laisser d’autres occurrences actives.

Contre-test

Après la remédiation, un contre-test vérifie que le problème n’est plus exploitable.

L’auditeur ne se contente pas nécessairement de rejouer exactement le payload original. Il vérifie également que la cause du problème a été corrigée et que des variantes évidentes ne permettent pas de contourner la nouvelle protection.

Pour un contrôle d’accès, il teste par exemple plusieurs opérations et plusieurs rôles. Pour une validation d’URL, il vérifie les redirections et formats alternatifs pertinents. Pour une injection, il cherche à confirmer que les données sont désormais séparées de la syntaxe plutôt qu’à constater qu’un unique payload a été bloqué.

Le contre-test ferme le cycle de l’audit : identification, compréhension, correction puis validation.

Pentest web en boite noire

Le black box fournit à l’auditeur un niveau d’information initial minimal. Il se rapproche donc de la perspective d’un attaquant externe découvrant progressivement la cible sans code source, documentation interne ni comptes privilégiés fournis à l’avance.

Cela ne signifie pas que l’auditeur doit rester non authentifié. S’il est possible de créer publiquement un compte, cette création fait partie des possibilités dont dispose également un attaquant réel et reste donc parfaitement compatible avec une approche black box.

Reconnaissance et OSINT

Le pentester commence par collecter les informations accessibles publiquement.

Les sous-domaines, dépôts publics, anciennes URLs, documents indexés, enregistrements DNS ou informations provenant de fuites passées peuvent orienter l’audit.

Un dépôt Git oublié peut par exemple révéler un endpoint interne ou un secret toujours valide. Un ancien sous-domaine peut exposer une version obsolète de l’application. Une documentation publique peut mentionner une API que l’interface principale n’utilise plus.

L’OSINT n’est donc pas une phase isolée : les informations collectées alimentent directement les tests suivants.

Fingerprinting des technologies

Les headers, cookies, fichiers JavaScript, chemins de ressources et structures d’URL peuvent révéler les frameworks et composants utilisés.

Cette information permet d’adapter les recherches. Identifier un CMS, un framework JavaScript, un reverse proxy ou un fournisseur cloud ne signifie pas qu’il est vulnérable, mais fournit des indices sur l’architecture et les fonctionnalités susceptibles d’exister.

Le pentester reste prudent avec la version. Des bannières peuvent être modifiées, des composants backportés ou des reverse proxies masquer le serveur réel. Un numéro apparent constitue une piste, pas une preuve de vulnérabilité.

Découverte de fichiers et d’endpoints

Des outils de découverte peuvent être utilisés afin d’identifier des ressources non directement référencées.

Par exemple :

ffuf -u https://target.example/FUZZ -w wordlist.txt

peut révéler des interfaces d’administration, documentations Swagger, fichiers de sauvegarde, anciennes APIs, répertoires .git, endpoints de debug ou ressources oubliées.

Le choix de la wordlist doit être adapté. Une liste générique produit souvent beaucoup de bruit ; une liste ciblée sur la technologie, la langue ou les conventions de nommage de l’organisation peut être beaucoup plus efficace.

Chaque découverte doit ensuite être analysée manuellement. Le fait qu’une route retourne 200 ou 403 ne suffit pas à conclure sur sa fonction ou son niveau de risque.

Recherche de vulnérabilités

Une fois la surface cartographiée, l’auditeur commence les tests actifs.

Sur une plateforme e-commerce, il peut créer plusieurs comptes et comparer leur comportement. Sur un portail documentaire, il cherchera à comprendre comment les identifiants sont générés et contrôlés. Il analysera également les mécanismes d’authentification, les workflows métier, les uploads, les APIs et les interfaces exposées.

Le black box oblige souvent l’auditeur à déduire le modèle interne à partir des différences observables. Une réponse plus longue, un message différent, un nom de champ dans JavaScript ou un identifiant dans un callback peut révéler progressivement la structure de l’application.

Exemple de chaîne d’exploitation

Prenons un formulaire d’inscription qui indique qu’une adresse existe déjà. La réponse contient cependant :

{
  "error": "email_already_exists",
  "user_id": "84126"
}

Cette fuite d’information semble limitée.

L’auditeur identifie ensuite un endpoint :

POST /api/auth/token/84126 HTTP/2
Host: app.example.com
Authorization: Bearer <token_attaquant>

et constate que l’API ne vérifie pas que l’identifiant demandé correspond à l’utilisateur authentifié.

En remplaçant son propre identifiant par celui obtenu précédemment, il peut générer un token associé à un autre compte.

La compromission résulte donc de la combinaison de deux comportements qui, analysés séparément, pourraient sembler moins critiques : une fuite d’identifiant et une BOLA dans un endpoint de génération de token.

C’est précisément ce type de scénario qui échappe souvent aux scanners automatisés, car il nécessite de comprendre que la donnée exposée par la première fonction est consommable par une seconde fonction ayant une logique d’autorisation différente.

Analyse des workflows métier

Le black box se prête particulièrement bien à l’analyse du comportement réel de l’application.

Une plateforme e-commerce peut par exemple accepter :

{
  "product_id": 471,
  "quantity": 1,
  "unit_price": 129.90
}

Le pentester modifie les quantités, prix, coupons et séquences de requêtes afin de déterminer quelles valeurs sont réellement recalculées côté serveur.

Il peut également tester des états inhabituels : annuler puis confirmer, appliquer plusieurs fois une promotion, envoyer simultanément deux requêtes, modifier un objet entre deux étapes ou reproduire une requête provenant d’un autre compte.

Ces tests permettent souvent d’identifier des faiblesses qu’un scanner générique ne peut pas comprendre.

Avantages et limites du black box

Le principal avantage est le réalisme. La surface trouvée par le pentester correspond à celle qu’un attaquant externe peut lui-même découvrir.

Le black box permet également d’évaluer la qualité réelle de l’exposition publique : informations divulguées, endpoints oubliés, mécanismes de découverte, anciennes versions et protections appliquées avant toute connaissance interne.

La limite vient du temps consacré à cette découverte. Certaines fonctionnalités ou branches applicatives peuvent rester invisibles pendant la durée de l’audit. Un contrôle rarement accessible, une route conditionnelle ou une fonctionnalité réservée à un compte particulier peut ne jamais être rencontrée.

Pour une application complexe, le black box est donc particulièrement pertinent lorsque le réalisme externe est l’objectif principal, mais il n’offre pas automatiquement la couverture la plus exhaustive.

Pentest web en boite grise

Dans une approche grey box, le pentester reçoit certains accès ou informations avant le début de la mission. Il peut disposer de comptes représentant plusieurs rôles, d’une documentation fonctionnelle limitée ou d’informations sur quelques composants du périmètre.

Le grey box permet ainsi de consacrer davantage de temps aux parties authentifiées et aux contrôles de permissions, tout en conservant une approche dynamique proche de celle d’un utilisateur compromis ou malveillant.

Analyse des rôles et permissions

Une application SaaS peut par exemple distinguer :

employee
manager
administrator
super administrator

L’auditeur compare les permissions réellement appliquées entre ces profils.

Il cartographie les objets accessibles, les actions possibles et les frontières de privilèges. Il observe comment les rôles sont représentés dans les tokens, les réponses API et les paramètres, puis teste si le serveur applique systématiquement le modèle attendu.

La simple absence d’un bouton dans l’interface n’est jamais considérée comme une preuve de sécurité. Les requêtes sont rejouées directement avec les différentes sessions.

Test des contrôles d’accès

Les identifiants d’objets, fonctions administratives, endpoints non documentés et paramètres influençant les permissions font l’objet de tests approfondis.

Le pentester compare horizontalement plusieurs comptes de même niveau et verticalement des rôles différents. Il vérifie les lectures mais aussi les modifications, suppressions, exports, invitations, changements de propriétaire et opérations en masse.

Les frontières multi-tenant sont particulièrement importantes. Une erreur d’autorisation entre deux utilisateurs d’une même organisation est déjà sensible, mais une faiblesse permettant de sortir de son tenant peut exposer l’ensemble des clients de la plateforme.

Exemple d’escalade de privilèges

Considérons une requête légitime utilisée par un administrateur :

PATCH /api/organizations/06fa370/users/123 HTTP/2
Host: backend.example.com
Authorization: Bearer <token_administrateur>
Content-Type: application/json

{
  "organization_role": "administrator"
}

L’auditeur la rejoue avec un token d’utilisateur standard.

Si le serveur accepte la modification, l’autorisation est absente ou incomplète.

L’analyse peut ensuite révéler un rôle supplémentaire :

{
  "organization_role": "root"
}

Si cette valeur est également acceptée sans vérification suffisante, un utilisateur standard peut potentiellement devenir super-administrateur.

Dans un environnement SaaS multi-tenant, l’impact peut alors concerner l’intégralité de la plateforme et non uniquement l’organisation d’origine.

Ce scénario illustre également une autre faiblesse fréquente : l’API peut accepter des valeurs que l’interface ne propose jamais. Le pentest grey box permet de comparer le trafic des rôles et d’identifier ces fonctions « cachées » beaucoup plus rapidement.

Test des fonctionnalités internes et blind XSS

Le grey box donne accès à davantage de formulaires et workflows.

Certaines données saisies par un utilisateur peuvent être consultées plus tard par un administrateur : tickets de support, signalements, commentaires, noms d’organisation ou champs de profil.

Une XSS stockée dans ces données peut ne jamais s’exécuter dans le navigateur de l’attaquant mais seulement dans celui du support. Ces scénarios de blind XSS nécessitent donc d’analyser le chemin complet suivi par la donnée.

Lorsque l’auditeur n’a pas accès à l’interface interne qui affichera le contenu, il peut utiliser une charge de callback contrôlée pour confirmer l’exécution sans capturer inutilement des données de session ou des informations sensibles.

Le même raisonnement s’applique à d’autres traitements différés : génération de PDF, export CSV, indexation, e-mailing ou ingestion par un système tiers. Une donnée sûre dans le contexte de saisie peut devenir dangereuse lorsqu’elle est réutilisée plus tard dans un autre contexte.

Avantages et limites du grey box

Le grey box constitue souvent un excellent compromis entre réalisme et profondeur.

L’auditeur évite de consacrer une part importante du temps à obtenir un accès que l’organisation peut lui fournir directement. Il peut ainsi approfondir les contrôles d’accès, la logique métier, les APIs et les fonctions réservées aux utilisateurs authentifiés.

La visibilité reste toutefois incomplète. Le code et certaines fonctionnalités internes peuvent rester difficiles à découvrir. Des branches rarement exécutées, des jobs asynchrones ou des endpoints non référencés peuvent échapper à l’analyse.

Le grey box n’est donc pas « meilleur » que le black box au sens absolu : il répond à un objectif différent, privilégiant la couverture fonctionnelle authentifiée plutôt que la reproduction stricte de la phase d’accès initial d’un attaquant externe.

Pentest web en boite blanche

Le pentest white box donne accès au code source et éventuellement à des informations supplémentaires sur l’architecture, les configurations ou les composants de déploiement.

Cette connaissance ne remplace pas les tests dynamiques. Elle permet au contraire de mieux les orienter et d’augmenter la couverture sur les zones difficiles à découvrir depuis l’extérieur.

Analyse de l’architecture et du code source

L’auditeur identifie les composants principaux : contrôleurs, middlewares, handlers d’API, fonctions d’autorisation, moteurs de template, appels vers des services externes, traitements de fichiers, jobs asynchrones et mécanismes de sérialisation.

Il peut ainsi concentrer rapidement son attention sur les parties spécifiques à l’application plutôt que d’essayer de déduire l’ensemble de son fonctionnement depuis l’extérieur.

Une première lecture de l’architecture permet aussi de repérer les frontières de confiance : données provenant du navigateur, messages entre services, secrets injectés au runtime, rôles cloud, files de messages ou bases partagées.

Recherche de sources et de fonctions sensibles

Certaines fonctions méritent une attention particulière car elles désactivent volontairement une protection du framework ou interprètent des données.

Dans Angular, par exemple :

this.safeHtml =
  this.sanitizer.bypassSecurityTrustHtml(this.content);

ne constitue pas automatiquement une XSS.

L’auditeur doit déterminer l’origine de this.content. Si cette valeur peut être influencée par un utilisateur, il remonte le flux de données jusqu’à l’entrée correspondante puis vérifie comment elle est finalement rendue.

Le même raisonnement s’applique à une fonction de shell, un moteur de template, un appel SQL dynamique, une lecture de fichier ou un client HTTP serveur. La présence d’un sink sensible crée une piste ; l’exploitabilité dépend de la capacité d’une source non fiable à l’atteindre dans un contexte insuffisamment sécurisé.

Analyse des flux de données

L’analyse white box permet de suivre une donnée depuis son entrée jusqu’à son utilisation.

Le pentester détermine où elle est reçue, quelles transformations elle subit, quelles validations sont appliquées puis dans quel contexte elle est finalement interprétée.

Cette démarche est particulièrement utile pour les injections, XSS, SSTI, SSRF et interactions avec des interpréteurs.

Elle permet également d’identifier les vulnérabilités de second ordre. Une donnée peut être validée et stockée dans un premier workflow, puis être relue plus tard et injectée dans un contexte différent où la validation initiale n’a plus de sens.

Le white box évite alors l’erreur consistant à considérer une donnée provenant de la base comme « de confiance » : ce qui importe est son origine réelle et le contexte de sa réutilisation.

Identification des faiblesses de contrôle d’accès

Le code facilite également la recherche d’incohérences d’autorisation.

Une route peut appliquer :

@require_role("admin")
def delete_user(user_id):
    ...

tandis qu’une autre opération sensible ne présente aucun contrôle apparent :

def update_user_role(user_id):
    ...

Cela ne suffit pas à conclure à une vulnérabilité car le contrôle peut être effectué à un autre niveau. Mais cette différence constitue une excellente hypothèse de test dynamique.

Une fois un pattern défaillant trouvé, l’auditeur peut rechercher toutes les occurrences similaires dans le code afin de déterminer s’il s’agit d’un bug local ou d’un défaut systémique.

Cette capacité est particulièrement utile dans les applications comportant de nombreuses routes ou microservices qui auraient été développés à des périodes différentes avec des conventions de sécurité hétérogènes.

Analyse statique et Semgrep

Semgrep et les outils SAST permettent d’automatiser la recherche de certains patterns.

Ils peuvent identifier des fonctions sensibles, des constructions SQL dangereuses, des secrets codés en dur, des désérialiseurs risqués ou certaines propagations de données non fiables.

Une alerte n’est toutefois qu’une hypothèse. L’auditeur doit vérifier l’atteignabilité du code, l’origine des données, les validations intermédiaires et le contexte final d’exploitation.

Un outil peut signaler de nombreuses occurrences techniquement similaires dont seules quelques-unes sont réellement atteignables depuis une entrée contrôlée par l’utilisateur. Inversement, une faiblesse de logique métier ou une incohérence d’autorisation peut ne générer aucune alerte statique.

L’intérêt du SAST dans un pentest white box réside donc dans la combinaison : automatiser les recherches répétitives, puis utiliser l’expertise humaine pour relier le finding à un chemin d’attaque concret.

Avantages et limites du white box

Le white box améliore fortement la couverture.

Il permet de découvrir des routes cachées, jobs asynchrones, services internes, contrôles rarement exécutés et problèmes systémiques difficiles à identifier depuis l’extérieur. Il accélère également la compréhension des causes racines et peut rendre les recommandations plus précises.

En revanche, il reproduit moins directement le niveau de connaissance d’un attaquant externe. L’auditeur dispose d’informations que celui-ci devrait normalement découvrir ou obtenir par d’autres moyens.

Il nécessite également de donner au prestataire accès à des éléments particulièrement sensibles du patrimoine logiciel. Les modalités d’accès, de stockage, de suppression et de confidentialité du code doivent donc être encadrées.

Le white box doit enfin rester un pentest : si toute l’énergie est consacrée à lire le code sans valider les comportements dans l’application déployée, la mission se rapproche d’une revue de code et perd une partie de sa dimension dynamique.

Principaux outils de pentest web

Burp Suite

Burp Suite est l’un des outils les plus utilisés pour les tests d’applications web.

Son proxy permet d’intercepter les échanges entre le navigateur et l’application. Le pentester peut modifier une requête avant son envoi, la rejouer, comparer les réponses obtenues avec différents comptes ou automatiser certaines variations de paramètres.

Repeater est particulièrement utile pour le travail manuel : une requête peut être progressivement simplifiée puis modifiée afin de comprendre exactement quelles propriétés influencent le comportement.

Intruder et d’autres fonctions permettent d’automatiser des séries de valeurs lorsque cela est pertinent, tandis que les extensions ajoutent des capacités spécialisées. Selon l’édition, Burp inclut également des fonctions de scan automatisé qui servent de complément à l’analyse manuelle.

OWASP ZAP

OWASP ZAP fournit également un proxy HTTP ainsi que des fonctions de découverte et de scan.

Son caractère open source le rend particulièrement intéressant pour l’apprentissage, les environnements où un outil libre est requis et certaines intégrations de sécurité automatisées.

Il permet d’explorer l’application, de rejouer des requêtes, de manipuler le trafic et d’automatiser une partie des contrôles.

Comme pour tout scanner, ses résultats doivent être interprétés et validés. Une alerte automatisée n’est pas équivalente à une vulnérabilité démontrée, et l’absence d’alerte ne signifie pas que la logique métier ou les contrôles d’accès sont sûrs.

ffuf

ffuf est utilisé pour le fuzzing et la découverte de contenu.

Il peut rechercher des fichiers, répertoires, endpoints, paramètres ou virtual hosts.

Son efficacité dépend fortement du choix des wordlists et du contexte. Une liste générique peut générer beaucoup de requêtes inutiles, alors qu’une liste construite à partir de la technologie, du JavaScript, de l’historique ou des conventions de nommage de l’application sera souvent beaucoup plus productive.

Le pentester doit également filtrer les réponses génériques. Certaines applications retournent un 200 pour toutes les routes inconnues, ce qui impose d’utiliser la taille, des mots-clés ou d’autres caractéristiques afin de distinguer une vraie découverte d’une page de fallback.

Nmap

Nmap est principalement un outil de découverte réseau et de services.

Dans un pentest web, il peut permettre d’identifier des services HTTP alternatifs, interfaces d’administration, reverse proxies ou autres ports exposés sur l’infrastructure liée à l’application.

Il ne remplace pas un proxy applicatif ni une cartographie fonctionnelle, mais complète la compréhension de la surface d’attaque lorsque le périmètre autorise l’analyse des services environnants.

Les scripts NSE peuvent également fournir des informations supplémentaires, mais leur utilisation doit être adaptée à la cible et aux règles d’engagement afin d’éviter des tests trop agressifs ou hors périmètre.

Semgrep

Semgrep est principalement utilisé dans les approches white box.

Il permet d’identifier des patterns potentiellement dangereux et de créer des règles adaptées au code de l’application.

Sa valeur réside surtout dans sa capacité à accélérer l’analyse d’un codebase important : recherche de sinks, contrôles d’autorisation oubliés, secrets, fonctions cryptographiques, désérialisation ou construction dynamique de requêtes.

Les règles génériques sont utiles, mais des règles spécifiques à l’architecture interne peuvent être encore plus efficaces. Si l’auditeur découvre qu’un middleware précis doit protéger chaque route sensible, il peut par exemple rechercher toutes les routes qui ne l’utilisent pas.

SQLmap

SQLmap automatise de nombreux tests liés aux injections SQL.

Il peut aider à confirmer ou caractériser une injection déjà suspectée, identifier le SGBD et automatiser certaines techniques qui seraient longues à reproduire manuellement.

Son utilisation doit cependant être contrôlée. Certaines fonctions génèrent un volume important de requêtes ou peuvent avoir des effets indésirables. En environnement de production, l’auditeur privilégie les options nécessaires à la preuve et évite les extractions inutiles.

La compréhension manuelle de la vulnérabilité reste indispensable pour produire une remédiation pertinente. Savoir que SQLmap exploite un paramètre n’explique pas pourquoi le code est vulnérable ni quelle construction doit être corrigée.

Comment préparer et dimensionner un pentest web ?

La qualité d’un pentest dépend aussi de sa préparation. Un périmètre mal décrit, des rôles manquants ou un environnement instable peuvent réduire la couverture même lorsque les tests sont techniquement bien réalisés.

Définir le périmètre d’un pentest web

Le dimensionnement doit être fondé sur la surface réelle de l’application.

Le nombre de pages n’est pas un indicateur suffisant. Une application composée de quelques écrans peut présenter de nombreux rôles, une API GraphQL, plusieurs intégrations et des workflows métier complexes.

Il est donc nécessaire d’identifier les fonctionnalités principales, les profils utilisateurs, les APIs, les interfaces d’administration, les services externes interagissant avec l’application et, selon le type de test, les dépôts de code ou composants d’infrastructure concernés.

Les exclusions doivent également être explicites : fournisseur de paiement tiers, domaine géré par un partenaire, environnement de production non modifiable, fonctions de déni de service ou données ne devant jamais être consultées.

Choisir entre black box, grey box et white box

Le choix dépend de l’objectif.

Le black box répond particulièrement bien à la question : qu’est-ce qu’un attaquant externe pourrait découvrir et exploiter sans connaissance interne ?

Le grey box permet de consacrer davantage de temps aux fonctions authentifiées, aux rôles et aux contrôles d’accès. Il est souvent adapté aux SaaS et aux applications où la majorité de la valeur se trouve derrière une authentification.

Le white box maximise la visibilité et facilite l’identification de problèmes systémiques ou cachés dans le code. Il est particulièrement utile lorsque l’objectif principal est la couverture, lorsqu’une application est critique ou lorsqu’une architecture complexe rend certains chemins difficiles à découvrir dynamiquement.

Ces approches ne correspondent pas à trois niveaux croissants de qualité. Elles répondent à des besoins différents et peuvent être combinées selon les objectifs de la mission.

Combien de temps dure un pentest web ?

Il n’existe pas de durée standard.

Le temps nécessaire dépend de la complexité fonctionnelle, du nombre de rôles, de la taille des APIs, des intégrations, de la profondeur souhaitée et du type d’approche.

Une petite application publique n’exige évidemment pas le même effort qu’une plateforme SaaS multi-tenant disposant de dizaines de modules, de plusieurs profils administratifs, d’une API GraphQL, d’un SSO et de workflows de paiement.

Le black box consacre davantage de temps à la reconnaissance et à la découverte. Le grey box permet de concentrer plus rapidement les efforts sur les fonctions authentifiées. Le white box ajoute une phase de lecture et d’analyse du code mais peut aussi accélérer la découverte de routes et de patterns vulnérables.

Le dimensionnement doit donc être effectué à partir de l’architecture et des fonctionnalités réelles, et non d’un simple nombre d’URLs.

Combien coûte un pentest web ?

Le coût dépend principalement du niveau d’effort nécessaire pour tester correctement le périmètre.

Deux applications visuellement proches peuvent nécessiter des charges radicalement différentes.

Une landing page avec quelques formulaires présente une surface limitée. Une application contenant un back-office, plusieurs rôles, une API GraphQL, un système de paiement, un SSO et des intégrations externes nécessite un travail beaucoup plus important.

Le prix doit donc être considéré comme la conséquence du périmètre, de la complexité et de la profondeur attendue, et non comme un tarif fixe associé au terme « pentest web ».

Un chiffrage sérieux nécessite généralement de comprendre les rôles, les grandes familles de fonctionnalités, le nombre d’applications ou APIs, les contraintes d’environnement et les livrables attendus.

Comment choisir un prestataire ?

Le choix ne devrait pas reposer uniquement sur les outils utilisés ou sur la mention de l’OWASP Top 10.

L’OWASP Top 10 est un document de sensibilisation aux grandes catégories de risques, pas une méthodologie exhaustive de pentest. Un audit approfondi doit être adapté à l’architecture et à la logique métier de l’application.

Il est donc pertinent de s’intéresser à la part de tests manuels, à l’expérience sur les APIs, les contrôles d’accès, les SSO et les architectures concernées, ainsi qu’à la capacité à construire des chaînes d’exploitation.

La qualité du rapport et de l’accompagnement à la remédiation est tout aussi importante. Un résultat techniquement correct mais difficilement exploitable par les équipes de développement perd une grande partie de sa valeur.

Il faut également examiner la gestion du contre-test, les règles de confidentialité, la manière dont les données de mission sont protégées et la capacité du prestataire à échanger directement avec les équipes techniques lorsque des clarifications sont nécessaires.

Enfin, l’expertise doit correspondre au périmètre. Une application classique, une architecture GraphQL, une plateforme cloud-native, un environnement fortement fédéré par SSO ou une application intégrant des agents IA ne mobilisent pas exactement les mêmes compétences.

Conclusion

Le pentest d’application web reste l’un des moyens les plus efficaces pour évaluer concrètement la résistance d’une application face à des attaques réalistes.

Sa valeur ne repose toutefois pas sur le nombre de payloads exécutés ou d’outils utilisés.

Les vulnérabilités les plus importantes sont souvent découvertes lorsque l’auditeur comprend suffisamment bien l’application pour identifier un comportement que ses concepteurs n’avaient pas anticipé.

Il peut s’agir d’un contrôle d’accès appliqué sur une route mais oublié sur une autre, d’un workflow financier manipulable, d’une fonctionnalité interne atteignable via SSRF, d’un flux OAuth qui accepte un token dans le mauvais contexte ou de plusieurs faiblesses secondaires qui, une fois combinées, permettent une compromission majeure.

Cette capacité à comprendre la logique du système, à remettre en question ses hypothèses de sécurité et à construire des chaînes d’exploitation explique pourquoi l’analyse manuelle reste centrale.

Le choix entre black box, grey box et white box dépend quant à lui de l’objectif recherché. Le black box reproduit au plus près la perspective d’un attaquant externe. Le grey box permet d’approfondir les contrôles présents dans les zones authentifiées. Le white box apporte une visibilité supplémentaire sur l’implémentation et permet d’améliorer encore la couverture.

Quelle que soit l’approche retenue, le pentest ne doit enfin pas être considéré comme une opération isolée. Sa valeur dépend de la capacité à transformer les vulnérabilités identifiées en correctifs durables, à vérifier leur efficacité lors du contre-test et à intégrer les enseignements de l’audit dans les pratiques de développement, de conception et de sécurisation de l’application.

Références