
JAW : Un cadre d'analyse de sécurité basé sur les graphes pour JavaScript côté client
J A W
Site Web | Documentation | Installation | Robot d'exploration | Démarrage rapide Docker (Exemple)
Une implémentation prototype open-source de graphes de propriétés pour JavaScript basée sur l'analyseur esprima et la spécification EsTree SpiderMonkey. JAW peut être utilisé pour analyser le côté client des applications web et les programmes basés sur JavaScript.
Ce projet est sous licence GNU AFFERO GENERAL PUBLIC LICENSE V3.0. Voir ici pour plus d'informations.
JAW dispose d'un site web Github pages accessible à l'adresse https://soheilkhodayari.github.io/JAW/.
Notes de version :
JAW-V2.JAW-V1.L'architecture de JAW est présentée ci-dessous.
JAW peut être utilisé de deux manières distinctes :
Analyse de JavaScript arbitraire : Utilisez JAW pour modéliser et analyser n'importe quel programme JavaScript en spécifiant le chemin du système de fichiers du programme.
Analyse d'application web : Analysez une application web en fournissant une seule URL de départ.
Utilisez les ressources web collectées pour créer un graphe de programme hybride (HPG), qui sera importé dans une base de données Neo4j.
Optionnellement, fournissez au module de construction du HPG un mappage des types sémantiques vers des jetons de langage JavaScript personnalisés, facilitant la catégorisation des fonctions JavaScript en fonction de leur objectif (par exemple, fonctions de requêtes HTTP).
Interrogez la base de données de graphes Neo4j construite pour diverses analyses. JAW propose des parcours utilitaires pour l'analyse de flux de données, l'analyse de flux de contrôle, l'analyse d'accessibilité et la correspondance de motifs. Ces parcours peuvent être utilisés pour développer des analyses de sécurité personnalisées.
JAW inclut également des parcours intégrés pour détecter les vulnérabilités CSRF côté client, DOM Clobbering et de détournement de requêtes.
Les résultats seront stockés dans le même dossier que celui de l'entrée.
Le script d'installation repose sur les prérequis suivants :
gestionnaire de paquets npm (node js)python 3.xpipEnsuite, installez les dépendances nécessaires via :
$ ./install.sh
Pour des instructions d'installation détaillées, veuillez consulter ici.
Vous pouvez exécuter une instance du pipeline dans un écran d'arrière-plan via :
$ python3 -m run_pipeline --conf=config.yaml
Le CLI propose les options suivantes :
$ python3 -m run_pipeline -h
usage: run_pipeline.py [-h] [--conf FILE] [--site SITE] [--list LIST] [--from FROM] [--to TO]
Ce script exécute le pipeline de l'outil.
arguments optionnels :
-h, --help affiche ce message d'aide et quitte
--conf FILE, -C FILE fichier de configuration du pipeline (défaut : config.yaml)
--site SITE, -S SITE site web à tester ; remplace le fichier de configuration (défaut : None)
--list LIST, -L LIST liste de sites à tester ; remplace le fichier de configuration (défaut : None)
--from FROM, -F FROM la première entrée à considérer lorsqu'une liste de sites est fournie ; remplace le fichier de configuration (défaut : -1)
--to TO, -T TO la dernière entrée à considérer lorsqu'une liste de sites est fournie ; remplace le fichier de configuration (défaut : -1)
Config d'entrée : JAW attend un fichier de configuration .yaml en entrée. Voir config.yaml pour un exemple.
Indice. Le fichier de configuration spécifie différentes étapes (par exemple, exploration, analyse statique, etc.) qui peuvent être activées ou désactivées pour chaque classe de vulnérabilité. Cela permet d'exécuter les blocs de construction de l'outil individuellement, ou dans un ordre différent (par exemple, explorer toutes les applications web d'abord, puis effectuer l'analyse de sécurité).
Pour exécuter un exemple rapide démontrant comment construire un graphe de propriétés et exécuter des requêtes Cypher dessus, faites :
$ python3 -m analyses.example.example_analysis --input=$(pwd)/data/test_program/test.js
Ce module collecte les données (c'est-à-dire le code JavaScript et les valeurs d'état des pages web) nécessaires aux tests. Si vous souhaitez tester un fichier JavaScript spécifique que vous avez déjà sur votre système de fichiers, vous pouvez ignorer cette étape.
JAW dispose de robots d'exploration basés sur Selenium (JAW-v1), Puppeteer (JAW-v2, v3) et Playwright (JAW-v3). Pour les fonctionnalités les plus récentes, il est recommandé d'utiliser les versions basées sur Puppeteer ou Playwright.
Ce robot d'exploration web utilise foxhound, une version instrumentée de Firefox, pour effectuer un suivi de teinte dynamique lors de la navigation dans les pages web. Pour démarrer le robot, faites :
$ cd crawler
$ node crawler-taint.js --seedurl=https://google.com --maxurls=100 --headless=true --foxhoundpath=<chemin-optionnel-vers-l-executable-foxhound>
Le foxhoundpath est par défaut défini sur le répertoire suivant : crawler/foxhound/firefox qui contient un binaire nommé firefox.
Remarque : vous avez besoin d'une compilation de foxhound pour utiliser cette version. Une compilation Ubuntu est incluse dans la version JAW-v3.
Pour démarrer le robot, faites :
$ cd crawler
$ node crawler.js --seedurl=https://google.com --maxurls=100 --browser=chrome --headless=true
Voir ici pour plus d'informations.
Pour démarrer le robot, faites :
$ cd crawler/hpg_crawler
$ vim docker-compose.yaml # définissez les sites web que vous voulez explorer ici et enregistrez
$ docker-compose build
$ docker-compose up -d
Veuillez vous référer à la documentation du hpg_crawler ici pour plus d'informations.
Pour générer un HPG pour un (ensemble de) fichier(s) JavaScript donné(s), faites :
$ node engine/cli.js --lang=js --graphid=graphe1 --input=/in/fichier1.js --input=/in/fichier2.js --output=$(pwd)/data/out/ --mode=csv
arguments optionnels :
--lang : langue du programme d'entrée
--graphid : un identifiant pour le HPG généré
--input : chemin du (des) programme(s) d'entrée
--output : chemin du HPG de sortie, doit être i
--mode : détermine le format de sortie (csv ou graphML)
Pour importer un HPG dans une base de données de graphes neo4j (instance docker), faites :
$ python3 -m hpg_neo4j.hpg_import --rpath=<chemin-vers-le-dossier-des-fichiers-csv> --id=<xyz> --nodes=<noeuds.csv> --edges=<relations.csv>
$ python3 -m hpg_neo4j.hpg_import -h
usage: hpg_import.py [-h] [--rpath P] [--id I] [--nodes N] [--edges E]
Ce script importe un CSV d'un graphe de propriétés dans une base de données neo4j docker.
arguments optionnels :
-h, --help affiche ce message d'aide et quitte
--rpath P chemin relatif vers le dossier contenant les fichiers CSV du graphe dans le répertoire `data`
--id I un identifiant pour le graphe ou le conteneur docker
--nodes N le nom du fichier csv des noeuds (défaut : nodes.csv)
--edges E le nom du fichier csv des relations (défaut : rels.csv)
Afin de créer un graphe de propriétés hybride pour la sortie du hpg_crawler et de l'importer dans une instance neo4j locale, vous pouvez également faire :
$ python3 -m engine.api <path> --js=<program.js> --import=<bool> --hybrid=<bool> --reqs=<requests.out> --evts=<events.out> --cookies=<cookies.pkl> --html=<html_snapshot.html>
Spécification des paramètres :
<path> : chemin absolu vers le dossier contenant les fichiers du programme pour l'analyse (doit être sous le dossier engine/outputs).--js=<program.js> : nom du programme JavaScript pour l'analyse (défaut : js_program.js).--import=<bool> : si le graphe de propriétés construit doit être importé dans une base de données neo4j active (défaut : true).--hybrid=bool : si le mode hybride est activé (défaut : false). Cela implique que le testeur souhaite enrichir le graphe de propriétés en entrant des fichiers pour l'instantané HTML, les événements déclenchés, les requêtes HTTP et les cookies, tels que collectés par le robot d'exploration JAW.--reqs=<requests.out> : pour le mode hybride uniquement, nom du fichier contenant la séquence des requêtes réseau observées, passer la chaîne false pour exclure (défaut : request_logs_short.out).--evts=<events.out> : pour le mode hybride uniquement, nom du fichier contenant la séquence des événements déclenchés, passer la chaîne pour exclure (défaut : ).Pour plus d'informations, vous pouvez utiliser le CLI d'aide fourni avec l'API de construction de graphe :
$ python3 -m engine.api -h
Le HPG construit peut ensuite être interrogé en utilisant Cypher ou l'ORM NeoModel.
Vous devez placer et exécuter vos requêtes dans analyses/<NOM_DE_L_ANALYSE>.
Vous pouvez utiliser l'ORM NeoModel pour interroger le HPG. Pour écrire une requête :
example_query_orm.py dans le dossier analyses/example.$ python3 -m analyses.example.example_query_orm
Pour plus d'informations, veuillez consulter ici.
Vous pouvez utiliser Cypher pour écrire des requêtes personnalisées. Pour cela :
example_query_cypher.py dans le dossier analyses/example.$ python3 -m analyses.example.example_query_cypher
Pour plus d'informations, veuillez consulter ici.
Cette section décrit comment configurer et utiliser JAW pour la détection de vulnérabilités, et comment interpréter les résultats. JAW contient, entre autres, des requêtes autonomes pour détecter les vulnérabilités CSRF côté client et DOM Clobbering.
Étape 1. activez le composant d'analyse pour la classe de vulnérabilité dans le fichier d'entrée config.yaml :
request_hijacking:
enabled: true
# [...]
open_redirect:
enabled: false
# [...]
domclobbering:
enabled: false
# [...]
cs_csrf:
enabled: false
# [...]
Étape 2. Exécutez une instance du pipeline avec :
$ python3 -m run_pipeline --conf=config.yaml
Indice. Vous pouvez exécuter plusieurs instances du pipeline sous différents screens :
$ screen -dmS s1 bash -c 'python3 -m run_pipeline --conf=conf1.yaml; exec sh'
$ screen -dmS s2 bash -c 'python3 -m run_pipeline --conf=conf2.yaml; exec sh'
$ # [...]
Pour générer automatiquement des fichiers de configuration parallèles, vous pouvez utiliser le script generate_config.py.
Les résultats seront stockés dans un fichier nommé sink.flows.out dans le même dossier que celui de l'entrée. Pour le CSRF côté client, par exemple, pour chaque requête HTTP détectée, JAW génère une entrée marquant l'ensemble des types sémantiques (c'est-à-dire les étiquettes ou libellés sémantiques) associés aux éléments construisant la requête (c'est-à-dire les tranches de programme). Par exemple, une requête HTTP marquée avec le type sémantique ['WIN.LOC'] est falsifiable via le point d'injection window.location. Cependant, une requête marquée avec ['NON-REACH'] n'est pas falsifiable.
Un exemple d'entrée de sortie est présenté ci-dessous :
[*] Tags: ['WIN.LOC']
[*] NodeId: {'TopExpression': '86', 'CallExpression': '87', 'Argument': '94'}
[*] Location: 29
[*] Function: ajax
[*] Template: ajaxloc + "/bearer1234/"
[*] Top Expression: $.ajax({ xhrFields: { withCredentials: "true" }, url: ajaxloc + "/bearer1234/" })
1:['WIN.LOC'] variable=ajaxloc
0 (loc:6)- var ajaxloc = window.location.href
Cette entrée montre qu'à la ligne 29, il y a une expression d'appel $.ajax, et cette expression d'appel déclenche une requête ajax avec la valeur de modèle d'url ajaxloc + "/bearer1234/, où le paramètre ajaxloc est une tranche de programme lisant sa valeur à la ligne 6 depuis window.location.href, donc falsifiable via ['WIN.LOC'].
Afin de simplifier le processus de test de JAW et de garantir l'exactitude de votre configuration, nous fournissons une simple application web node.js avec laquelle vous pouvez tester JAW.
Tout d'abord, installez les dépendances via :
$ cd tests/test-webapp
$ npm install
Ensuite, exécutez l'application dans un nouvel écran :
$ screen -dmS jawwebapp bash -c 'PORT=6789 npm run devstart; exec sh'
Pour plus d'informations, visitez notre page wiki ici. Voici une table des matières pour un accès rapide.
Les demandes d'extraction (pull requests) sont toujours les bienvenues. Ce projet a pour vocation d'être un espace sûr et accueillant, et les contributeurs sont censés respecter le code de conduite des contributeurs.
Si vous utilisez JAW pour la recherche académique, nous vous encourageons à citer l'article suivant :
@inproceedings{JAW,
title = {JAW: Studying Client-side CSRF with Hybrid Property Graphs and Declarative Traversals},
author= {Soheil Khodayari and Giancarlo Pellegrino},
booktitle = {30th {USENIX} Security Symposium ({USENIX} Security 21)},
year = {2021},
address = {Vancouver, B.C.},
publisher = {{USENIX} Association},
}
JAW a parcouru un long chemin et nous souhaitons remercier chaleureusement nos contributeurs ici !
falseevents.out--cookies=<cookies.pkl> : pour le mode hybride uniquement, nom du fichier contenant les cookies, passer la chaîne false pour exclure (défaut : cookies.pkl).--html=<html_snapshot.html> : pour le mode hybride uniquement, nom du fichier contenant l'instantané de l'arbre DOM, passer la chaîne false pour exclure (défaut : html_rendered.html).