Intégration de scripts personnalisés dans AppScan pour un examen DAST amélioré

Intégrez des scripts personnalisés à vos examens DAST avec AppScan pour manipuler les requêtes et les réponses HTTP de manière dynamique, améliorant ainsi la flexibilité et l'efficacité de vos tests de sécurité.

Activation des scripts personnalisés dans AppScan

Les scripts personnalisés dans AppScan sont activés par défaut (le paramètre CustomScripts.Enable est défini sur True).
Remarque : Une fois activés, ces scripts sont exécutés avec chaque requête et réponse HTTP dans AppScan Standard, pendant des opérations telles que l'enregistrement et l'examen.

Pour désactiver les scripts personnalisés :

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

Mise en œuvre et gestion de scripts personnalisés pour des examens DAST améliorées

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.

    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.

    Conseil : Les erreurs de syntaxe sont mises en évidence dans l'éditeur de code et peuvent être identifiées par des info-bulles, bien qu'elles n'empêchent pas l'exécution du script.

    Illustration de l'info-bulle de l'éditeur de code

    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 : stockez les clés API des réponses dans des 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 : ajoutez 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}`)
        }    
    Exemple 4 : Ajouter un autre en-tête avec une valeur différente.
    // Avant chaque requête, 
    function addUniqueHeader(headerName, value) {
        if(!(request.headers[headerName] != null && request.headers[headerName].includes(value))) {
            request.headers.add(headerName, value)
            }
    }
    addUniqueHeader(“headerName”,”Value”) 
  6. Cliquez sur Ajouter pour enregistrer votre script. Le script est ajouté à la liste et activé par défaut.
    Remarque : Ces scripts 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 vos scripts dans un environnement contrôlé avant tout déploiement dans l'environnement actif pour vous assurer qu'ils fonctionnent comme prévu.
  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.
    Remarque : Les scripts personnalisés sont chiffrés par défaut lorsqu'ils sont exportés dans un modèle. Pour désactiver le chiffrement, réglez le paramètre Général : Chiffrer les données sensibles sur False dans la configuration des examens.

Exemples de scripts personnalisés pour AppScan

Des exemples de scripts personnalisés pour AppScan sont chargés dans le référentiel GitHub.

Instructions pour l'écriture de code JavaScript efficace dans AppScan

Contexte

Requête : Modifiez les données de la requête avant de l'envoyer au serveur. Chaque objet de requête inclut des propriétés telles que les en-têtes, le corps, le chemin et la méthode, que vous pouvez manipuler pour personnaliser vos examens DAST.
  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.
    // Ajoute un nouvel en-tête s'il est absent ; le remplace s'il est présent 
    request.headers.set(key, value)
    // Ajoute l'en-tête 
    request.headers.add(key, value)
    ATTENTION : Étant donné que les scripts peuvent 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'ajoutera pas d'en-tête si un en-tête avec le même nom et la même valeur existe déjà. Faites attention à ne pas dupliquer les en-têtes, car cela peut provoquer des erreurs.
    // 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 : AppScan omet le délimiteur de requête (« ? ») si le paramètre de requête est vide.
    // 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 réponse est au format chaîne, vous devez donc la convertir manuellement si nécessaire (en JSON par exemple). Cette propriété est en lecture seule ; elle reste inchangée même si vous tentez de la modifier avant d'exécuter le script.
    // 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")

Résultats

Définit le résultat de l'exécution du script personnalisé et fonctionne conjointement avec le contexte 'Paramètre'. AppScan utilisera ce résultat si nécessaire.

// Sets the script execution result
setResultValue("result")

Contraintes

  1. Évitez d'utiliser des méthodes restreintes dans vos scripts pour éviter les échecs et les erreurs d'exécution.
    1. eval
    2. Fonction (constructeur)
    3. setTimeout
    4. setInterval

      L'utilisation de l'une de ces méthodes entraînera l'échec du script et la production d'une erreur.

  2. Respectez les limites d'exécution des scripts pour garantir des performances optimales et éviter une utilisation excessive des ressources.
    1. 5 secondes (max.) de temps d'exécution
    2. 64 Mo d'allocation de mémoire

      Si au moins une de ces limites est dépassée, le script échoue.

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