Scripts personnalisés

Les scripts personnalisés peuvent dynamiser votre examen DAST. Vous pouvez ajouter des JavaScripts pour manipuler les requêtes ou les réponses HTTP au cours d'un examen. Cette manipulation peut être effectuée avant l'envoi d'une requête au serveur ou après la réception d'une réponse.

Activer des scripts personnalisés pour AppScan

Les scripts personnalisés sont activés par défaut (le paramètre CustomScripts.Enable est défini sur True).

Pour désactiver les scripts :

  1. Allez dans Outils > Options > onglet Avancé.
  2. Réglez le paramètre CustomScripts.Enable sur « False ».

Ajouter et activer des scripts personnalisés pour les examens DAST

Vous pouvez ajouter des JavaScripts personnalisés à votre examen DAST de la manière suivante :
  1. Accédez à l'option Scripts personnalisés dans la section Avancé des paramètres de configuration.
  2. Cliquez sur le bouton + Ajouter.
  3. Le champ Nom est prérempli avec la date et l'heure de création du script. Vous pouvez modifier le nom si nécessaire.
  4. Dans la liste déroulante Contexte d'exécution, sélectionnez Avant la requête ou Après la réponse en fonction du moment où vous souhaitez que le script s'exécute.
  5. Dans le champ JavaScript, saisissez votre code JavaScript. Pour recevoir des suggestions de code JavaScript dans l'environnement AppScan, appuyez sur Ctrl+Espace.

    Assurez-vous que votre code ne contient pas d'erreurs de syntaxe et qu'il est compatible avec la version de JavaScript prise en charge par AppScan. Pour plus d'informations sur les règles et la façon d'écrire le code, voir Code JavaScript.

    Exemple 1 : ajoutez automatiquement des détails de connexion à vos requêtes (sans utiliser la configuration de la gestion des connexions).

    // Before each request
    if(request.method == "POST") {
        request.body = JSON.stringify({
            "username": "jsmith",
            "password": "demo1234"
        })
    }

    Exemple 2 : vérifiez si la réponse inclut une clé API et stockez-la dans les variables globales.

    // After each response
    try {
            var result = JSON.parse(response.body)
            log(`parsing: ${JSON.parse(response.body).Authorization}`)
            if(result.Authorization) {
                environment.globalVariables.addOrUpdate("Authorization", result.Authorization)
                log(`key = ${result.Authorization}`)
            }
    }
    catch (error) {
            log(error)
    }

    Exemple 3 : définissez la clé d'API d'autorisation sur l'en-tête s'il existe.

    // Before each request
    var authorization = environment.globalVariables.get("Authorization")
        if(authorization) {
            request.headers.set("Authorization", authorization)
            log(`authorization is ${authorization}`)
        }
  6. Cliquez sur Ajouter pour enregistrer votre script. Le script est ajouté à la liste et activé par défaut.
    Remarque : Les scripts que vous ajoutez sont exécutés pour chaque requête ou réponse HTTP au cours de l'examen DAST.
    Utilisez cette fonction à bon escient pour améliorer l'efficacité de vos examens. Testez toujours vos scripts dans un environnement contrôlé avant de les déployer dans un examen réel afin d'éviter tout comportement ou résultat inattendu.
  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. Vous pouvez modifier, supprimer ou changer l'ordre d'exécution des scripts. Dans le coin droit du script, cliquez sur Menu-vertical-à-trois-points et sélectionnez l'option comme suit :
    • Modifier
    • Supprimer
    • Déplacer vers le haut
    • Déplacer vers le bas
  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.
    Remarque : Lorsque vous exportez des scripts personnalisés dans un modèle, ils sont cryptés par défaut. Pour désactiver manuellement ce chiffrement, dans les paramètres de configuration des examens, accédez à Configuration avancée et définissez le champ Général : Chiffrer les données sensibles sur False.

Code JavaScript

Contexte

Requête : Vous pouvez lire ou modifier les données de la requête avant qu'elles ne soient envoyées au serveur. Chaque requête est représentée par un objet requête, qui possède les propriétés suivantes :
  1. En-têtes : Contient tous les en-têtes de la requête. Vous pouvez ajouter, supprimer ou modifier n'importe quel en-tête, à l'exception des en-têtes par défaut.
    // Add header
    request.headers.add(key, value)
    // Override header if exist
    request.headers.set(key, value)
    Remarque : L'utilisation de « Ajouter » au lieu de « Définir » peut entraîner plusieurs instances de l'en-tête dans la requête. Par conséquent, « Définir » est préférable à « Ajouter ».
    // Remove header
    request.headers.remove(key)
    // Modify header
    request.headers[key]
    // Examples
    request.headers.add("Authorization", "MyCoolApiKey")
    request.headers.set("Authorization", "SecondApiKey")
    request.headers.remove("Authorization")
    request.headers['Authorization'] = "myapikey3"
    En-têtes par défaut (non sensibles à la casse) : elles sont en lecture seule et ne peuvent pas être modifées.
    • Hôte : Identifie l'hôte auquel la requête est envoyée.
    • Content-Length : Calcule la taille de la requête et envoie cette information au serveur.
  2. Corps : Contient des informations sur le corps de la requête. Le corps est de type « string ».
    // Access body
    request.body
    // Example
    request.body = "{ "username":"user" }"
  3. Chemin : Contient des informations sur le nœud final auquel la requête est destinée. Le format du nœud final exclut l'URL de base (par exemple : /api/v1/test). Cette propriété est en lecture seule ; elle reste la même que lorsqu'elle a été définie pour la première fois, même si vous tentez de la modifier avant d'exécuter le script.
    // Access url path
    request.path
    // Example
    if (request.path.startsWith("api/v1/test"))
  4. Requête : Contient la chaîne de requête et les paramètres (s'il y en a) pour la requête en cours. Vous pouvez ajouter ou supprimer des paramètres de requête de cet objet. Chaque valeur est traitée comme un objet unique, comme « key=value ». Lorsque vous utilisez « getQueryString », vous obtenez une chaîne dont tous les éléments sont concaténés par un signe « & ». Cette chaîne est une copie des éléments, donc si vous changez la chaîne, vous ne changez qu'une copie de la requête.
    Remarque : Si le paramètre de requête est vide, AppScan n'enverra pas le délimiteur de requête (« ? »)
    // Retrieve the current query string
    request.query.getQueryString()
    
    // Example
    // Add new value (or update existing one)
    request.query.addOrUpdate("appscan","appscanvalue")
    // Check if value exist
    request.query.contains("appscan") // for key only check
    request.query.contains("appscan=appscanvalue") // for key and value check
    // Remove an item
    request.query.remove("appscan") // for key only check
    request.query.remove("appscan=appscanvalue") // for key and value check
    request.query.clear() // remove all values
  5. Méthode : Méthode de la requête (par exemple GET/POST/etc). Cette propriété est en lecture seule ; elle reste la même que lorsqu'elle a été définie pour la première fois, même si vous tentez de la modifier avant d'exécuter le script.
    // Access to the method
    request.method
    // Example
    if (request.method == "GET")
Réponse : Un objet qui contient les données de la réponse et une requête parent apparentée. Vous pouvez récupérer des informations, modifier ou enregistrer les données de la réponse. Chaque réponse est représentée par un objet réponse, qui possède les propriétés suivantes :
  1. Corps : Contient le corps de la réponse à la requête. La réponse est au format chaîne, vous devez donc la convertir manuellement si nécessaire (en JSON par exemple).
    // Access body
    response.body
    // Example
    let json = JSON.parse(config.response)
  2. Chemin : Contient des informations sur le nœud final de la réponse.
    // Access to the relative url
    response.path
    // Example
    if (response.path.startsWith("api/v1/test"))
  3. Statut : Stocke des détails sur l'état de la réponse. L'état est un objet doté des propriétés suivantes :
    // Access status
    response.status.statusCode // A numeric representation of the status
    response.status.statusDescription // The description of the status code
    response.status.statusLine //the whole status line including the http version
    // Example
    if (response.status.statusCode == 200) // check only the number
    if (response.status.statusDescription == "OK") // Check only the description
    if (response.status.statusLine == "HTTP1.1 200 OK") // Full line
  4. En-têtes : Contient tous les en-têtes de la réponse. Vous pouvez ajouter, supprimer ou modifier n'importe quel en-tête, à l'exception des en-têtes par défaut.
    // Add header
    response.headers.add(key, value)
    // Override header if exist
    response.headers.set(key, value)
    // Remove header
    response.headers.remove(key)
    // Modify header
    response.headers[key]
    // Examples
    response.headers.add("Authorization", "MyCoolApiKey")
    response.headers.set("Authorization", "SecondApiKey")
    response.headers.remove("Authorization")
    response.headers['Authorization'] = "myapikey3"
  5. ParentRequest : Objet contenant la requête envoyée avant la réponse. Les données de requête sont en lecture seule. La requête possède toutes les propriétés de l'objet requête défini précédemment.
    // Example
    response.request.path //- access to the path from the request

Données d'environnement

Un objet de données à court terme stocke des informations importantes 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 exécutez un test manuel.

  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.

    Ces données sont effacées à chaque fois qu'un nouvel examen ou un réexamen est effectué.

    // Add data to the globals or update existing one
    environment.globalVariables.addOrUpdate(key, value)
    // Remove key data from the globals
    environment.globalVariables.remove(key)
    // Read data - retrieves the value for the current key (without removing it)
    environment.globalVariables.get(key)
  2. Statut de l'examen : Contient des informations sur l'examen en cours.
    // determine if the current phase is explore phase
    environment.status.isInExplore()
    // determine if the current phase is test phase
    environment.status.isInTest()

Logging

Active les fonctions de journalisation dans le script pour aider au débogage et à l'identification des problèmes. La commande « console.log » ne fonctionne pas ici. Utilisez plutôt le mot « log » suivi d'un message entre guillemets. De plus, s'il y a une erreur pendant le fonctionnement du moteur qui n'est pas liée à la syntaxe ou à l'utilisation de JavaScript, cette erreur est enregistrée dans le journal de suivi du moteur.

// Log message to file
log("my cool logging")

// Log message with custom source
log("message", "my-cool-source")

Contraintes

N'utilisez pas les méthodes suivantes dans le contexte du script :
  • eval
  • Fonction (constructeur)
  • setTimeout
  • setInterval
L'utilisation de l'une de ces méthodes entraînera l'échec du script et la production d'une erreur

Gestion des erreurs

Si le script utilise des fonctions restreintes et rencontre une erreur ou une exception, il cesse de fonctionner. Cet échec interrompt l'examen en cours et les détails de l'erreur sont enregistrés dans le fichier « UserScript.log » pour un examen plus approfondi.

Chargement d'un modèle configuré avec des scripts

Vous pouvez lancer un examen en chargeant un modèle configuré avec des scripts activés. Un modèle type, préconfiguré avec des scripts pour le fichier de description demo.testfire, est disponible à l'adresse Program Files (x86)\HCL\AppScan Standard\Templates.

Versions JavaScript prises en charge par AppScan

Actuellement, les versions ECMAScript de ES6 (2015) à ES15 (2024) sont prises en charge, à l'exception des fonctions suivantes :
  • ES6 (2015)
    • Générateurs
    • Appels résiduels
  • ES8 (2017)
    • Mémoire partagée et opérations atomiques
  • ES15 (2024)
    • Atomics.waitAsync
    • Balise d'expression régulière \v