Des prompts de pentest par IA qui produisent des preuves, pas seulement des résultats
Guide pratique pour concevoir des workflows de test de sécurité assistés par l'IA qui transforment des preuves délimitées en résultats vérifiables, grâce à des sorties structurées, des points de validation et une exécution contrôlée.
Vous demandez au modèle de trouver une vulnérabilité
Imaginez qu'une nouvelle API atterrisse sur votre bureau. Elle contient des dizaines de routes, des middlewares inconnus et assez de code pour occuper un relecteur pendant des jours.
Prompt donné au modèle : « Passe en revue ce dépôt et trouve les vulnérabilités de sécurité. »
Quelques instants plus tard, la réponse arrive. Elle mentionne une injection SQL, des secrets codés en dur, des contrôles d'autorisation manquants et une désérialisation non sécurisée. Elle est organisée, assurée et mise en forme comme un rapport de sécurité.
Point de décision : l'enverriez-vous à l'équipe d'ingénierie ?
Pas encore. Déterminez d'abord ce que le modèle a réellement testé. Peut-être qu'aucun endpoint n'a été suivi de la requête jusqu'à la base de données. Aucune entrée n'a atteint un sink dangereux. Aucune décision d'autorisation n'a été exercée. Aucune condition d'exploitabilité n'a été vérifiée. Le résultat peut contenir des hypothèses utiles, mais une hypothèse n'est pas encore un résultat.
C'est ici que le test de sécurité assisté par l'IA devient utile ou devient du bruit. Le défi n'est pas de faire parler un modèle comme un pentesteur. Il est de passer d'une demande large à une question précise, de cette question à des preuves, et des preuves à un résultat qu'un autre ingénieur peut reproduire.
Reconstruisons le test une décision à la fois.
D'abord, choisissez une seule question qui vaut la peine d'être traitée
Parmi les pistes générées figure un possible problème d'autorisation sur GET /v1/invoices/{id}.
Affirmation initiale : « L'endpoint peut exposer des factures appartenant à d'autres utilisateurs. »
Preuves nécessaires : identifier le propriétaire de la ressource, localiser le contrôle d'autorisation, comprendre l'accès de l'attaquant et observer ce qui se passe lorsqu'un utilisateur authentifié demande la facture d'un autre compte.
Objectif du test : déterminer si un utilisateur authentifié peut récupérer une facture appartenant à un autre compte via GET /v1/invoices/{id}.
La cible est devenue plus petite, mais l'investigation est devenue plus profonde. Elle dispose désormais d'une interface, d'une frontière de propriété, d'une capacité d'attaquant et d'une condition de réussite.
Le même changement fonctionne dans tous les domaines de la sécurité :
| Demande large | Question à laquelle le workflow peut répondre |
|---|---|
| Vérifier les intents Android | Pour l'activité exportée ShareActivity, un extra contrôlé par l'attaquant peut-il atteindre un composant privilégié sans validation ? |
| Chercher des injections | Le paramètre de requête sort peut-il atteindre une opération de requête dynamique sans traitement sûr ? |
| Trouver des secrets stockés | La valeur sensible suspectée est-elle écrite dans le stockage de l'application, et peut-elle être récupérée selon le modèle d'attaquant décrit ? |
C'est l'isolation contextuelle en pratique. Au lieu de déverser un dépôt entier dans le modèle, fournissez la définition de la route, le middleware concerné, le handler, le code d'accès aux données, les tests et les preuves observées de requête ou de réponse.
Le modèle dispose maintenant de moins de matière pour s'égarer et d'une question claire à traiter.
Ensuite, décidez de ce qui comptera comme preuve
Supposons que le modèle lise le handler des factures et renvoie :
Affirmation initiale : « L'endpoint est vulnérable à une IDOR parce qu'il récupère une facture par son ID. »
Verdict : pas encore. Récupérer un objet par son ID est un comportement normal d'une application. La question décisive est de savoir si la propriété ou une autre politique d'autorisation est appliquée avant le renvoi de la réponse. Ce contrôle peut exister dans un middleware, une couche de service, une requête de base de données ou une fonction de politique située en dehors du code visible.
Avant de demander une conclusion, donnez à la tâche un contrat de preuves. Exigez que le workflow renvoie le chemin de code inspecté, la capacité de l'attaquant, le contrôle d'autorisation attendu, la requête et la réponse de validation, ainsi qu'un statut parmi confirmed, needs_validation ou not_reproduced.
Une sortie structurée ne rend pas une affirmation vraie. Elle rend visible l'absence de preuve.
task:
id: api-object-authorization-001
vulnerability_class: broken_object_level_authorization
target:
method: GET
path: /v1/invoices/{id}
owner_boundary: account_id
objective: >
Determine whether an authenticated user can retrieve an invoice that belongs
to a different account.
permitted_actions:
- Read source files listed in context.
- Inspect supplied test traffic and test fixtures.
- Generate a test request only against the approved staging target.
required_evidence:
- Authorization check location or its absence.
- Request and response identifiers for the cross-account test.
- Expected versus observed authorization result.
output_rules:
- Do not report a confirmed vulnerability without runtime or test evidence.
- Return needs_validation when execution is unavailable.
- Cite every conclusion with an evidence reference.
Le contrat introduit une règle qui doit survivre à chaque révision du prompt :
Pas de preuve, pas de confirmation.
Puis, laissez chaque résultat choisir l'étape suivante
Le modèle suit la route. Il trouve un middleware d'authentification et une requête de base de données qui charge une facture à partir de son identifiant. Il ne trouve toujours aucune condition de propriété.
Décision suivante : ne générez pas une nouvelle explication. Choisissez le prochain test capable de réduire l'incertitude. Le workflow a besoin d'une boucle contrôlée :
- Planifier : identifier la plus petite question qui réduirait l'incertitude.
- Collecter : récupérer le code source, la fixture, le trafic ou la sortie d'outil approuvée pertinents.
- Analyser : relier les preuves au contrôle de sécurité examiné.
- Valider : rejouer une requête, exécuter un test sûr, inspecter une trace ou demander une revue humaine.
- Décider : confirmer le résultat, affiner l'hypothèse ou s'arrêter.
Pour l'endpoint des factures, utilisez deux comptes de préproduction contrôlés par le testeur. Laissez le compte A créer une facture contenant un marqueur unique et non sensible. Confirmez d'abord que le compte A peut la récupérer via l'endpoint testé. Authentifiez-vous ensuite en tant que compte B et demandez le même identifiant.
Question de validation : quel résultat prouverait le problème ?
Si le compte B reçoit le marqueur unique du compte A, le test démontre un accès inter-comptes, mais seulement si les factures sont privées et que les comptes n'ont aucune relation de partage. Un refus montre que le chemin testé a appliqué la frontière dans ce cas. Si la référence manque, si la réponse n'est pas claire, si le partage est intentionnel ou si l'environnement de test est indisponible, le résultat reste needs_validation.
La trace du code source et la réponse à l'exécution répondent à des questions différentes. La première montre où le contrôle semble manquer. La seconde montre comment le système en fonctionnement se comporte. Un workflow fiable conserve les deux éléments et ne substitue jamais l'un à l'autre.
Chaque boucle doit modifier l'état de l'investigation. Si elle ne produit qu'une nouvelle version du même soupçon, le système génère du langage au lieu de tester la cible.
Appliquons maintenant la même méthode à d'autres questions de sécurité
Le cas des factures nous donne un chemin complet, mais un workflow de pentest par IA ne peut pas être conçu autour de la seule autorisation. Appliquons le même raisonnement à trois autres investigations.
Un intent Android n'est que le début
Le modèle trouve une activité Android exportée nommée ShareActivity. Il voit aussi un extra d'intent entrant et un appel à startActivity.
Point de décision : cela suffit-il pour signaler une redirection d'intent ?
Non. Le workflow doit encore relier les éléments. Il doit confirmer que le composant est atteignable de l'extérieur, identifier les extras que contrôle un attaquant, suivre ces valeurs jusqu'à startActivity, startService ou sendBroadcast, et inspecter toute validation ou restriction de composant appliquée avant l'appel.
L'étape suivante est un test contrôlé à l'exécution depuis une application distincte. Pour confirmer une redirection d'intent, l'entrée fabriquée doit amener l'application victime à effectuer une action que l'application de test ne pourrait pas invoquer directement. Par exemple, elle pourrait atteindre un composant interne non exporté ou une opération protégée.
Ouvrir une autre activité exportée ne prouve pas un contournement de sécurité. Si l'activité d'entrée n'est pas exportée, si l'intent imbriqué est restreint ou si aucun effet protégé ne se produit, affinez l'affirmation ou marquez-la not_reproduced.
L'API dangereuse était une piste. L'atteignabilité, le contrôle par l'attaquant et le comportement observé déterminent si elle devient un résultat.
Un paramètre de requête n'est pas automatiquement une injection
Ensuite, le modèle remarque que le paramètre de requête sort atteint une fonction de construction de requête. Il qualifie ce chemin d'« injection SQL possible ».
Question suivante : la valeur devient-elle une partie de la commande SQL, ou reste-t-elle une donnée ? Une liste d'autorisation qui associe name ou created_at à des noms de colonnes fixes change la conclusion. Insérer directement la valeur dans la requête justifierait un test de validation sûr dans l'environnement approuvé.
Le workflow suit la valeur du handler HTTP jusqu'au constructeur de requête et consigne toute validation ou transformation. Il exécute ensuite des tests appariés et non destructifs sur des données appartenant au testeur. Pour confirmer une injection, une entrée contrôlée par l'attaquant doit modifier le comportement de la requête alors que la requête de référence reste stable. Une erreur de base de données seule ne suffit pas : une entrée mal formée peut provoquer une erreur sans permettre une injection. Une concaténation de chaînes sans entrée atteignable par l'attaquant reste une preuve statique, et non une exploitation démontrée.
Une valeur sensible doit réellement atteindre le stockage
Enfin, le modèle trouve du code qui écrit des valeurs dans les shared preferences, une base de données locale ou un cache. Il signale un « stockage non sécurisé de données sensibles ».
Preuve manquante : le workflow doit identifier la valeur. Une API de stockage ne prouve pas que des mots de passe, des jetons, des données personnelles ou du matériel cryptographique y sont écrits. Il doit ensuite suivre le chemin d'écriture ou exercer le flux applicatif concerné, et inspecter le stockage obtenu selon le modèle d'attaquant décrit.
Si une valeur sensible appartenant au testeur apparaît sur le disque, consignez son emplacement, les étapes de sa création, sa protection et les conditions de sa récupération. Précisez également si l'extraction a nécessité un build débogable, run-as, un accès aux sauvegardes, le root, un accès physique ou une instrumentation à l'exécution.
Des données récupérées dans un stockage privé uniquement après avoir obtenu l'accès root ne soutiennent pas la même affirmation de risque que des données exposées dans un stockage lisible de l'extérieur. Si les preuves ne montrent qu'un helper de stockage générique, l'affirmation reste une hypothèse.
Ces exemples utilisent des outils et des preuves différents, mais suivent la même progression : affiner la question, suivre le contrôle par l'attaquant, identifier le contrôle attendu, tester en toute sécurité et conserver le résultat observé.
Une piste devient un résultat au point de validation
Le compte A récupère avec succès sa facture marquée. Le compte B, sans relation de partage, récupère ensuite le même marqueur privé via le même endpoint. Le workflow consigne les deux identités, la référence de propriété, les requêtes, les réponses, le chemin de code et la divulgation inter-comptes observée.
Ce n'est que maintenant que la piste peut devenir un résultat confirmé.
Des affirmations différentes exigent des points de validation différents :
| Affirmation | Ce que le workflow doit démontrer |
|---|---|
| Une valeur sensible est stockée localement | Récupérer une valeur appartenant au testeur depuis l'emplacement de stockage indiqué et documenter les prérequis d'accès. |
| L'endpoint n'a pas d'autorisation au niveau des objets | Établir l'accès du propriétaire, puis démontrer l'accès d'un second principal contrôlé par le testeur, sans relation de partage. |
| Une entrée utilisateur atteint un sink dangereux | Suivre le contrôle par l'attaquant et utiliser des tests appariés et sûrs pour démontrer le comportement du sink pertinent pour la sécurité. |
| Exécution de code à distance | Produire un marqueur d'exécution unique et inoffensif dans un environnement autorisé ; un simple crash ne suffit pas. |
Une API suspecte, un contrôle qui semble manquer, un endpoint inhabituel ou une fonction dangereuse peuvent guider le prochain test. Aucun n'est automatiquement une vulnérabilité digne d'un rapport.
Si la validation est indisponible : dites-le. Needs_validation est plus utile qu'un faux positif assuré, car il indique au relecteur ce qui reste inconnu.
Avant de donner des outils au modèle, fixez les limites
L'investigation fonctionne, et la tentation est donc de donner au modèle plus d'accès : plus d'outils, plus de cibles, peut-être des identifiants de production.
Question de sécurité : quelle est l'action la plus dommageable que ce workflow pourrait entreprendre s'il avait mal compris la tâche ou suivi un contenu malveillant ?
« Soyez prudent » n'est pas une frontière de sécurité. La couche d'exécution doit imposer un accès en lecture seule au code source, des cibles sur liste d'autorisation, des identités synthétiques, des limites de débit, des environnements de préproduction approuvés et une approbation humaine avant toute action modifiant l'état.
Les fichiers du dépôt, les tickets, les pages web, les journaux et les réponses de la cible sont des entrées non fiables. Ils peuvent contenir des instructions destinées à détourner un système d'IA. L'injection de prompt et l'autonomie excessive sont donc des risques de conception du système, et non des problèmes résolus par une formulation astucieuse.
Le modèle peut proposer une action. C'est la couche d'exécution qui décide si elle est permise.
Un test réussi n'est toujours qu'un seul test
Question de fiabilité : une seule investigation réussie sur les factures prouve-t-elle que l'architecture du prompt est fiable ?
Non. Elle prouve seulement qu'un workflow a traité un cas.
Constituez un jeu d'évaluation à partir de vulnérabilités confirmées, de faux positifs connus, de composants sains et de cas incomplets où le résultat correct est needs_validation. Exécutez ces cas chaque fois que le modèle, le prompt, l'outil, la règle de sélection du contexte ou le schéma de sortie change.
Demandez ensuite :
- A-t-il identifié le problème connu ?
- A-t-il joint les bonnes preuves ?
- A-t-il rejeté le faux positif connu ?
- S'est-il arrêté lorsque la preuve à l'exécution n'était pas disponible ?
- Un relecteur pouvait-il reproduire la conclusion ?
Cela transforme la modification des prompts en ingénierie. Une modification mérite sa place en améliorant un résultat mesuré, et non en produisant une prose plus persuasive.
À quoi feriez-vous confiance maintenant ?
Revenez à la première réponse : une liste soignée de vulnérabilités possibles, générée à partir d'une revue large du dépôt.
Comparez-la maintenant à l'investigation sur les factures. Le second résultat dispose d'une cible délimitée, d'un modèle d'attaquant, d'une trace de code, de deux identités contrôlées, d'une requête et d'une réponse capturées, d'une défaillance d'autorisation observée et d'un statut ayant franchi un point de validation défini.
Décision finale : quel résultat enverriez-vous à l'équipe d'ingénierie ?
L'IA peut aider les équipes de sécurité à naviguer dans de grandes bases de code, à organiser les preuves, à générer des plans de test ciblés et à décider quoi inspecter ensuite. Elle ne supprime pas le besoin d'une cible, d'un test, d'un contrôle ou d'un relecteur.
L'objectif n'est pas une liste plus longue de vulnérabilités possibles. C'est un chemin court et défendable à travers la cible :
Périmètre → question → preuve → test → résultat observé → conclusion.
C'est la différence entre un modèle capable de décrire le test de sécurité et un workflow qui laisse derrière lui quelque chose qu'un autre ingénieur peut rejouer, contester, corriger et vérifier.