Scripts personnalisés

Les scripts personnalisés dynamisent vos examens DAST. Vous pouvez ajouter du JavaScript pour manipuler les requêtes et les réponses HTTP pendant un examen, soit avant l'envoi d'un requête au serveur, soit après la réception d'une réponse.

Présentation

Les scripts personnalisés s'exécutent dans AppScan et fonctionnent sur des modèles de demande et de réponse en mémoire, ce qui vous permet d'ajuster les demandes par programmation et d'inspecter les réponses sans créer d'extension ou utiliser de proxy.

En un coup d'œil :

Avant la requête : Exécute un script pour modifier une requête HTTP avant de l'envoyer à votre application (ajout/suppression d'en-têtes, chiffrement de données, gestion des jetons, etc.).

Après la réponse : Traitez la réponse HTTP après qu'elle a été reçue de votre application (déchiffrer le contenu, extraire les valeurs, etc.).

Paramètre : Générez des valeurs pour les Opérations en plusieurs étapes et le Remplissage de formulaire en utilisant JavaScript uniquement.

Utilisez cette fonction à bon escient pour améliorer l'efficacité de vos examens. Testez vos scripts dans un environnement contrôlé avant tout déploiement dans l'environnement actif pour vous assurer qu'ils fonctionnent comme prévu.

Exemple de chemin de modèle : C:\Program Files (x86)\HCL\AppScan Standard\Templates.

Exemples de scripts personnalisés : Référentiel GitHub.

Ajout de scripts personnalisés

Ajoutez des JavaScripts personnalisés à vos examens DAST comme suit :
  1. Sélectionnez Scripts personnalisés dans la section Avancé des paramètres de configuration.
  2. Cliquez sur le bouton + Ajouter.
  3. Modifiez le champ Nom prérempli si nécessaire.
  4. Choisissez le Contexte d'exécution approprié pour votre script : :
    1. Avant la requête pour que les scripts soient exécutés avant l'envoi des requêtes.
    2. Après la réponse pour que les scripts soient exécutés après la réception des réponses.
    3. Paramètre pour les tâches qui impliquent plusieurs étapes ou le remplissage de formulaires. Vous pouvez utiliser ce contexte en conjonction avec la méthode setResultValue pour permettre aux scripts de renvoyer les résultats à AppScan.
  5. Saisissez votre JavaScript dans le champ JavaScript (éditeur de code) et utilisez Ctrl+espace pour obtenir des suggestions automatiques dans l'environnement AppScan.
  6. Cliquez sur Ajouter pour enregistrer votre script. Le script est ajouté à la liste et activé par défaut.
  7. Vous pouvez choisir d'activer ou de désactiver un script de la liste des scripts personnalisés à l'aide de la case à cocher Activer.
  8. Gérez vos scripts en utilisant la case à cocher Activer ou en modifiant, en supprimant ou en réorganisant les scripts dans la liste de scripts. Menu Options
  9. Cliquez sur Démarrer un examen complet pour démarrer l'examen.
  10. Résultat : Les scripts activés sont exécutés pour chaque requête ou réponse. Vous pouvez consulter les détails des scripts dans Données > onglet Requêtes > Requête/Réponse.

    Vérifiez l'exactitude syntaxique et la compatibilité de votre script avec la version JavaScript prise en charge dans AppScan. Pour obtenir des instructions détaillées, reportez-vous à la section Code JavaScript.

    Remarque :
    • Les scripts personnalisés sont enregistrés dans le fichier de configuration des examens et peuvent être exportés avec un modèle. Ils ne sont pas inclus dans les résultats de l'examen.
    • Par défaut, les scripts personnalisés sont chiffrés lorsqu'ils sont exportés dans un modèle. Pour désactiver le chiffrement, définissez le paramètre Général : Chiffrer les données sensibles sur False dans la configuration des examens.

Activation des scripts personnalisés

Les scripts personnalisés sont activés par défaut et s'exécutent avec chaque requête et réponse HTTP pendant l'enregistrement et l'examen.

Pour désactiver l'exécution du script, accédez à Outils > Options > onglet Avancé et définissez le paramètre CustomScripts.Enable sur « False ».

Contextes d'exécution

Avant la requête

But : Mutez les requêtes HTTP sortantes.

Données : Seuls les objets de requête et d'environnement sont disponibles, les autres objets seront nuls.
// Attach Authorization from stored global variable
var token = environment.globalVariables.get("Authorization");
if (token) request.headers.set("Authorization", token);

Après la réponse

But : Inspectez les réponses et les valeurs persistantes.

Données : Seuls les objets de données de réponse et d'environnement sont disponibles. Les autres objets seront nuls.
// Capture token from JSON response and store it for reuse
try {
		var result = JSON.parse(response.body);
		if (result && result.Authorization) {
			environment.globalVariables.addOrUpdate("Authorization", result.Authorization);
		}
} catch(e) { log(e); }

Paramètre

But : Générez des valeurs pour les Opérations en plusieurs étapes et le Remplissage de formulaire.
  • Aucun objet de données (requête ou réponse) n'est disponible dans ce contexte ; leur utilisation renvoie une valeur nulle.
  • Renvoie les valeurs avec setResultValue(value).

Dans le remplissage de formulaire, lorsque vous sélectionnez Source de valeur > Script personnalisé, la liste affiche uniquement les scripts dont le contexte d'exécution est Paramètre.

Dans les opérations en plusieurs étapes, vous pouvez également fournir des valeurs dynamiques à l'aide de scripts Paramètre.
// Example: Return a unique email for registration flows
function random(n) { return Math.random().toString(36).slice(2, 2+n); }
var email = "test_" + Date.now() + "_" + random(6) + "@example.test";
setResultValue(email);

Référence d'API

Objet de requête (contexte Avant la requête) - API complète
// Examples:
// Handle headers
request.headers.set("Authorization", "Bearer");
request.headers.add("X-Trace", "abc");

// Manipulate body
request.body = JSON.stringify( { user:"admin" });
if(request.body.includes("admin") { ... }

// Read path
if (request.path.startsWith("/api/v1")) { ... }

// Edit query
request.query.addOrUpdate("lang","en")
request.query.remove("debug")
request.query.getQueryString()

// Read method
if (request.method == "GET") { ... }
ATTENTION : Les scripts pouvant s'exécuter plusieurs fois par requête, il est conseillé d'utiliser la méthode Set pour ajouter de nouveaux en-têtes, car elle remplace les en-têtes existants et empêche les doublons. Utilisez la méthode Add uniquement lorsque vous avez besoin de plusieurs en-têtes avec le même nom et des valeurs différentes. La méthode Add n'ajoute pas d'en-tête si un en-tête avec le même nom et la même valeur existe déjà. Veillez à ne pas dupliquer les en-têtes, car cela peut provoquer des erreurs.
Objet de réponse (contexte Après la réponse) - API complète
// Examples:
// Handle headers
response.headers.set("Authorization", "Bearer");
response.headers.add("X-Trace", "abc");

// Read body (since it's read only)
var j = JSON.parse(response.body);

// Read path
if (response.path.startsWith("/api/v1")) { ... }

// Read response
if (response.status.statusCode == 200) { ... }

// Read parent request
if (response.request.path.startsWith("/api/v1")) { ... }
Contexte Paramètre - API complète
// Update the result back to AppScan
setResultValue("ABC-" + Date.now());

Données d'environnement

Les données à court terme sont disponibles uniquement jusqu'à la fin de la tâche, par exemple lorsque vous mettez en pause, arrêtez ou terminez un examen, que vous vous connectez ou que vous terminez un test manuel. Elles sont effacées au début de chaque nouvel examen ou réexamen.

  1. Variable globale : Les données des variables globales sont une structure de données clé-valeur conçue pour stocker des paires de données spécifiques à l'utilisateur. Les clés sont uniques (c'est-à-dire que deux éléments ne peuvent pas avoir la même clé, bien que plusieurs éléments puissent partager la même valeur), ce qui est utile pour partager des données entre des scripts en cours d'exécution.
  2. Statut de l'examen : Contient des informations sur l'examen en cours.
    // Check the status of the scan
    environment.status.isInExplore();
    environment.status.isInTest();

Journalisation - API complète

Active la journalisation dans votre script pour aider au débogage et au dépannage. La commande console.log standard n'est pas prise en charge dans cet environnement. Utilisez plutôt la fonction log avec un message entre guillemets, par exemple : log("Your message here"). Si une erreur d'exécution se produit pendant le fonctionnement du moteur qui n'est pas liée à la syntaxe ou à l'utilisation de JavaScript, elle est enregistrée dans le journal de suivi du moteur pour une analyse plus approfondie.

Les journaux sont écrits dans le fichier UserScript.log du dossier de journalisation AppScan.

Par défaut, il s'agit du dossier [UserDataFolder]\AppData\Roaming\HCL\AppScan Standard\logs.

Contraintes et limites d'exécution

  • Fonctions restreintes : eval, Function (constructor), setTimeout, setlnterval. Si l'une d'entre elles est utilisée, le script échoue.
  • Limites : Durée d'exécution maximale : 5 secondes ; limite de mémoire : 64 Mo. Le dépassement de ces limites entraîne l'échec du script.

    En cas d'échec, l'examen s'interrompt et les détails sont enregistrés dans UserScript.log.

Versions JavaScript prises en charge

ECMAScript ES6 (2015) à ES15 (2024), à l'exception des fonctions suivantes :
  • ES6 : Générateurs, appels résiduels
  • ES8 : Mémoire partagée et opérations atomiques
  • ES15 : Atomics.waitAsync, indicateur d'expressions régulières \v

Objets disponibles dans la saisie semi-automatique

Ces objets apparaissent dans les suggestions de saisie semi-automatique de l'éditeur de script, ce qui facilite leur recherche et leur utilisation :

  • Mot-clé
  • Tableau
  • Date
  • Objet
  • Chaîne
  • RegExp
  • JSON
  • Map
  • Math
Pris en charge, sauf dans la saisie semi-automatique

Ces objets sont entièrement pris en charge par le moteur de script, mais n'apparaissent pas dans les listes de saisie semi-automatique. Vous pouvez toujours les utiliser en saisissant leur nom directement dans l'éditeur :

  • ArrayBuffer
  • BigInt
  • Booléen
  • DataView
  • Erreur
  • Iterator
  • Nombre
  • Promise
  • Proxy
  • Reflect
  • SharedArrayBuffer
  • Symbole
  • TypedArray

  • WeakMap

  • WeakRef

  • WeakSet

    Remarque : « Pas dans la saisie semi-automatique » signifie que l'éditeur ne suggère pas ces éléments automatiquement. Cependant, les objets sont implémentés et se comportent exactement comme dans JavaScript standard.

Résolution des problèmes

Problèmes courants et solutions :
  1. Échecs de script : Vérifiez le dossier des journaux (par défaut : [UserDataFolder]\AppData\Roaming\HCL\AppScan Standard\logs) pour plus de détails sur l'erreur. Si vous rencontrez une exception non gérée, entourez votre code d'un bloc try...catch pour la gérer de manière appropriée.
  2. Script non exécuté : Assurez-vous que le script est activé dans les paramètres de configuration.

    Si le problème est lié à la connexion/l'autorisation, envisagez de supprimer la valeur de négociation dans Configuration→ Configuration avancée → Ordre du package de sécurité pour empêcher AppScan de gérer ces authentifications automatiquement.

API Requête complète

Tableau 1. Objet Requête - Propriétés
Membre Type Description Exemple
en-têtes objet Un objet encapsulant les en-têtes de la requête HTTP en cours, fournissant des méthodes pour ajouter, mettre à jour, récupérer ou supprimer des en-têtes de manière dynamique, ce qui permet un contrôle précis des métadonnées de la requête. request.headers.set("Authorization","Bearer ...")
corps chaîne Le corps de la requête HTTP en cours. request.body = JSON.stringify({ user:"jsmith" })
chemin chaîne

Lecture seule🔒

Le chemin relatif de la requête HTTP en cours.

if (request.path.startsWith("/api/v1/")) { ... }
query objet Un objet qui contient différentes méthodes pour ajouter, mettre à jour ou supprimer des paramètres de requête dans la requête HTTP en cours, ce qui permet une manipulation dynamique de la chaîne de requête. request.query.addOrUpdate("lang","en") request.query.remove("debug")
méthode chaîne

Lecture seule🔒

La méthode de la requête HTTP actuelle.

if (request.method == "GET") {{ ... }}
Tableau 2. Objet Requête - Méthodes
Membre Type Description Exemple

addOrUpdate

(nom : chaîne, valeur : chaîne)

vide Ajoute une nouvelle valeur à la chaîne de requête ou met à jour une valeur existante. request.query.addOrUpdate("appscan","appscanvalue")
getQueryString() chaîne

Renvoie la chaîne de requête complète de la requête HTTP en cours, y compris tous les paramètres et leurs valeurs.

request.query.getQueryString()

contains

(nom : chaîne)

booléen

Vérifie si un paramètre de requête spécifique existe dans la requête HTTP en cours.

Renvoie true si le paramètre existe, false sinon.

request.query.contains("lang")

remove

(nom : chaîne)

booléen

Supprime un paramètre de requête spécifique de la requête HTTP en cours.

Renvoie true si le paramètre a été supprimé, false si ce n'est pas le cas.

request.query.remove("lang")
clear() vide

Supprime tous les paramètres de requête de la requête HTTP en cours.

request.query.clear()

API Réponse complète

Tableau 3. Objet Réponse - objectStatus
Membre Type Description Exemple
en-têtes objet Un objet encapsulant les en-têtes de la réponse HTTP en cours, fournissant des méthodes pour ajouter, mettre à jour, récupérer ou supprimer des en-têtes de manière dynamique, permettant un contrôle précis des métadonnées de la réponse. response.headers.set("Authorization","Bearer ...")
corps chaîne Le corps de la réponse HTTP en cours. response.body = JSON.stringify({ user:"jsmith" })
chemin chaîne

Lecture seule🔒

Le chemin relatif de la réponse HTTP en cours.

if (response.path.startsWith("/api/v1/")) { ... }
status objet Un objet représentant l'état de la réponse HTTP en cours, y compris les propriétés du code d'état et du message d'état. if (response.status.code == 200) { ... }
demande objet Un objet représentant la requête à l'origine de la réponse. Les données de requête sont en lecture seule et incluent toutes les propriétés définies dans l'objet de requête décrit précédemment. if (response.request.path) { ... }
Tableau 4. Propriétés
Membre Type Description Exemple
statusCode nombre

Lecture seule🔒

Le code de statut HTTP de la réponse en cours.

response.status.statusCode = 200
statusDescription chaîne

Lecture seule🔒

Le message de statut HTTP de la réponse en cours.

response.status.statusDescription = "OK"
statusLine chaîne

Lecture seule🔒

La ligne de statut HTTP de la réponse en cours.

response.status.statusLine = "HTTP/1.1 200 OK"

API Paramètre complète

Tableau 5. Objet Paramètre
Membre Type Description Exemple

setResultValue

(valeur : chaîne)

vide Définit la valeur de résultat pour le script de contexte de paramètre en cours. setResultValue("ABC-" + Date.now())

Objets communs

Tableau 6. Objet En-têtes - Propriétés
Membre Type Description Exemple
éléments tableau

Lecture seule🔒

Un tableau de tous les en-têtes de la requête HTTP en cours.

if (request.headers.items.length > 0) { ... }

if (response.headers.items.length > 0) { ... }

Tableau 7. Objet En-têtes - Méthodes
Membre Type Description Exemple
add

(nom : chaîne, valeur : chaîne)

vide

Ajoute un nouvel en-tête à la requête HTTP en cours. Si un en-tête avec le même nom et la même valeur existe déjà, il ne sera pas ajouté à nouveau.

request.headers.add("Authorization", "MyCoolApiKey")

response.headers.add("Authorization",MyCoolApiKey")

set

(nom : chaîne, valeur : chaîne)

vide Définit un en-tête dans la requête HTTP en cours. Si l'en-tête existe déjà, sa valeur est remplacée.

request.headers.set("Authorization", "SecondApiKey")

response.headers.set("Authorization","SecondApiKey")

remove

(nom : chaîne)

vide Supprime un en-tête de la requête HTTP en cours. request.headers.remove("Authorization")response.headers.remove("Authorization")
[nom : chaîne] chaîne Récupère la valeur d'un en-tête spécifique par son nom. Renvoie une valeur nulle si l'en-tête n'existe pas.

request.headers['Authorization'] = "myapikey3"

response.headers['Authorization'] = "myapikey3"

Données d'environnement

Tableau 8. Objet Environnement - Propriétés
Membre Type Description Exemple
globalVariables objet Une structure de données clé-valeur pour le stockage de paires de données spécifiques à l'utilisateur. Les clés doivent être uniques, ce qui garantit l'absence de doublons, tandis que les valeurs peuvent être partagées entre plusieurs clés. Cette structure facilite le partage des données entre les scripts en cours d'exécution. environment.globalVariables.addOrUpdate(key, value)
status objet Informations sur le statut actuel de l'examen. environment.status.isInExplore()
Tableau 9. Objet Variables globales - Méthodes
Membre Type Description Exemple

addOrUpdate

(clé : chaîne, valeur :

chaîne)

vide Ajoute une nouvelle paire clé-valeur aux variables globales ou met à jour la valeur d'une clé existante. environment.globalVariables.addOrUpdate("mycoolkey", "testValue")

remove

(clé : chaîne)

booléen Supprime une paire clé-valeur des variables globales. Renvoie true si la clé a été trouvée et supprimée, sinon false. environment.globalVariables.remove("mycoolkey")
get

(clé : chaîne)

chaîne Récupère la valeur d'une clé spécifique à partir des variables globales. Renvoie une chaîne vide si la clé n'existe pas. environment.globalVariables.get("mycoolkey")
Tableau 10. Objet Statut - Méthodes
Méthode Type Description Exemple
isInExplore() booléen Vérifie si l'examen est actuellement en phase d'exploration. environment.status.isInExplore()
isInTest() booléen Vérifie si l'examen est actuellement en phase de test. environment.status.isInTest()

Journalisation

Tableau 11. Méthodes
Membre Type Description Exemple
log(message: string) log(message: string, source: string) vide Ajoute une nouvelle entrée de journal avec le message spécifié et la source facultative. log("This is a log message")

log("This is a log message", "mySource")