
JAW: クライアントサイドJavaScriptのためのグラフベースのセキュリティ分析フレームワーク
J A W
Webサイト | ドキュメント | セットアップ | クローラ | クイックスタート | Docker(例)
JavaScript用のプロパティグラフのオープンソース・プロトタイプ実装です。esprima パーサと EsTree SpiderMonkey Spec に基づいています。JAWは、WebアプリケーションのクライアントサイドやJavaScriptベースのプログラムの解析に使用できます。
このプロジェクトは GNU AFFERO GENERAL PUBLIC LICENSE V3.0 の下でライセンスされています。詳細はこちらをご覧ください。
JAWはGithub PagesのWebサイトを https://soheilkhodayari.github.io/JAW/ で公開しています。
リリースノート:
JAW-V2ブランチを参照。JAW-V1ブランチを参照。JAWのアーキテクチャを以下に示します。
JAWは2つの異なる方法で使用できます。
path を指定することで、任意のJavaScriptプログラムのモデリングと解析にJAWを利用します。Neo4j グラフデータベースを様々な解析のためにクエリします。JAWは、データフロー解析、制御フロー解析、到達可能性解析、パターンマッチングのためのユーティリティトラバーサルを提供します。これらはカスタムのセキュリティ解析の開発に使用できます。インストールスクリプトは以下の前提条件に依存します。
npm package manager(node js)の最新バージョンpython 3.x の安定版pip パッケージマネージャその後、以下で必要な依存関係をインストールします。
$ ./install.sh
詳細なインストール手順については、こちらを参照してください。
パイプラインのインスタンスをバックグラウンド画面で実行するには、以下を実行します。
$ python3 -m run_pipeline --conf=config.yaml
CLIは以下のオプションを提供します。
$ python3 -m run_pipeline -h
usage: run_pipeline.py [-h] [--conf FILE] [--site SITE] [--list LIST] [--from FROM] [--to TO]
This script runs the tool pipeline.
optional arguments:
-h, --help show this help message and exit
--conf FILE, -C FILE pipeline configuration file. (default: config.yaml)
--site SITE, -S SITE website to test; overrides config file (default: None)
--list LIST, -L LIST site list to test; overrides config file (default: None)
--from FROM, -F FROM the first entry to consider when a site list is provided; overrides config file (default: -1)
--to TO, -T TO the last entry to consider when a site list is provided; overrides config file (default: -1)
入力設定: JAWは入力として .yaml 設定ファイルを期待します。例は config.yaml を参照してください。
ヒント: 設定ファイルは異なるパス(例: クローリング、静的解析など)を指定し、脆弱性クラスごとに有効/無効を切り替えることができます。これにより、ツールのビルディングブロックを個別に、または異なる順序(例: 最初にすべてのWebアプリをクロールし、その後セキュリティ解析を実施)で実行できます。
プロパティグラフを構築し、その上でCypherクエリを実行する方法を示すクイック例を実行するには、以下を実行します。
$ python3 -m analyses.example.example_analysis --input=$(pwd)/data/test_program/test.js
このモジュールは、テストに必要なデータ(JavaScriptコードとWebページの状態値)を収集します。すでにファイルシステム上に特定のJavaScriptファイルがある場合は、このステップをスキップできます。
JAWには、Selenium(JAW-v1)、Puppeteer(JAW-v2、v3)、Playwright(JAW-v3)に基づくクローラがあります。最新の機能については、PuppeteerまたはPlaywrightベースのバージョンを使用することをお勧めします。
このWebクローラは、foxhound(Firefoxの計装版)を使用して、Webページを移動しながら動的タイントラッキングを実行します。クローラを起動するには、以下を実行します。
$ cd crawler
$ node crawler-taint.js --seedurl=https://google.com --maxurls=100 --headless=true --foxhoundpath=<optional-foxhound-executable-path>
foxhoundpath はデフォルトで crawler/foxhound/firefox ディレクトリに設定されており、firefox というバイナリが含まれています。
注意: このバージョンを使用するには、foxhound のビルドが必要です。UbuntuビルドはJAW-v3のリリースに含まれています。
クローラを起動するには、以下を実行します。
$ cd crawler
$ node crawler.js --seedurl=https://google.com --maxurls=100 --browser=chrome --headless=true
詳細はこちらを参照してください。
クローラを起動するには、以下を実行します。
$ cd crawler/hpg_crawler
$ vim docker-compose.yaml # クロールしたいWebサイトをここに設定して保存
$ docker-compose build
$ docker-compose up -d
hpg_crawler のドキュメントはこちらを参照してください。
特定の(複数の)JavaScriptファイルのHPGを生成するには、以下を実行します。
$ node engine/cli.js --lang=js --graphid=graph1 --input=/in/file1.js --input=/in/file2.js --output=$(pwd)/data/out/ --mode=csv
optional arguments:
--lang: language of the input program
--graphid: an identifier for the generated HPG
--input: path of the input program(s)
--output: path of the output HPG, must be i
--mode: determines the output format (csv or graphML)
HPGをneo4jグラフデータベース(Dockerインスタンス)にインポートするには、以下を実行します。
$ python3 -m hpg_neo4j.hpg_import --rpath=<path-to-the-folder-of-the-csv-files> --id=<xyz> --nodes=<nodes.csv> --edges=<rels.csv>
$ python3 -m hpg_neo4j.hpg_import -h
usage: hpg_import.py [-h] [--rpath P] [--id I] [--nodes N] [--edges E]
This script imports a CSV of a property graph into a neo4j docker database.
optional arguments:
-h, --help show this help message and exit
--rpath P relative path to the folder containing the graph CSV files inside the `data` directory
--id I an identifier for the graph or docker container
--nodes N the name of the nodes csv file (default: nodes.csv)
--edges E the name of the relations csv file (default: rels.csv)
hpg_crawler の出力のハイブリッドプロパティグラフを作成し、ローカルのneo4jインスタンスにインポートするには、以下も実行できます。
$ 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>
パラメータの仕様:
<path>: 解析するプログラムファイルが含まれるフォルダへの絶対パス(engine/outputs フォルダ以下である必要があります)。--js=<program.js>: 解析するJavaScriptプログラムの名前(デフォルト: js_program.js)。--import=<bool>: 構築されたプロパティグラフをアクティブなneo4jデータベースにインポートするかどうか(デフォルト: true)。--hybrid=bool: ハイブリッドモードを有効にするかどうか(デフォルト: false)。これは、テスターがJAWクローラによって収集されたHTMLスナップショット、発生イベント、HTTPリクエスト、Cookieのいずれかのファイルを入力してプロパティグラフを拡張したい場合を意味します。--reqs=<requests.out>: ハイブリッドモードのみ、監視されたネットワークリクエストのシーケンスを含むファイル名。除外するには文字列 false を渡します(デフォルト: request_logs_short.out)。--evts=<events.out>: ハイブリッドモードのみ、発生したイベントのシーケンスを含むファイル名。除外するには文字列 false を渡します(デフォルト: events.out)。詳細については、グラフ構築APIのヘルプCLIを使用できます。
$ python3 -m engine.api -h
構築されたHPGは、Cypher または NeoModel ORM を使用してクエリできます。
クエリは analyses/<ANALYSIS_NAME> に配置して実行する必要があります。
NeoModel ORM を使用してHPGをクエリできます。クエリを作成するには:
analyses/example フォルダにあるサンプルクエリファイル example_query_orm.py を参照してください。$ python3 -m analyses.example.example_query_orm
詳細については、こちらを参照してください。
Cypher を使用してカスタムクエリを作成できます。そのためには:
analyses/example フォルダにあるサンプルクエリファイル example_query_cypher.py を参照してください。$ python3 -m analyses.example.example_query_cypher
詳細については、こちらを参照してください。
このセクションでは、JAWを脆弱性検出に設定して使用する方法と、出力の解釈方法について説明します。 JAWには、とりわけ、クライアントサイドCSRFとDOM Clobberingを検出するための自己完結型クエリが含まれています。
ステップ1. 入力 config.yaml ファイルで、脆弱性クラスの解析コンポーネントを有効にします。
request_hijacking:
enabled: true
# [...]
open_redirect:
enabled: false
# [...]
domclobbering:
enabled: false
# [...]
cs_csrf:
enabled: false
# [...]
ステップ2. 以下でパイプラインのインスタンスを実行します。
$ python3 -m run_pipeline --conf=config.yaml
ヒント. パイプラインの複数のインスタンスを異なる screen で実行できます。
$ 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'
$ # [...]
設定ファイルを自動的に並列生成するには、generate_config.py スクリプトを使用できます。
出力は、入力と同じフォルダ内の sink.flows.out というファイルに保存されます。たとえば、クライアントサイドCSRFの場合、検出された各HTTPリクエストに対して、JAWはリクエストを構成する要素に関連付けられたセマンティックタイプのセット(プログラムスライス)を示すエントリを出力します。たとえば、['WIN.LOC'] というセマンティックタイプでマークされたHTTPリクエストは、window.location インジェクションポイントを介して偽装可能です。一方、['NON-REACH'] でマークされたリクエストは偽装できません。
以下に出力エントリの例を示します。
[*] 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
このエントリは、29行目に $.ajax 呼び出し式があり、この呼び出し式が ajaxloc + "/bearer1234/" というURLテンプレート値を持つ ajax リクエストをトリガーしていることを示しています。パラメータ ajaxloc は、6行目の window.location.href から値を読み取るプログラムスライスであるため、['WIN.LOC'] を介して偽装可能です。
JAWのテストプロセスを合理化し、セットアップが正しいことを確認するために、JAWでテストできるシンプルな node.js Webアプリケーションを提供しています。
まず、以下で依存関係をインストールします。
$ cd tests/test-webapp
$ npm install
次に、新しい画面でアプリケーションを実行します。
$ screen -dmS jawwebapp bash -c 'PORT=6789 npm run devstart; exec sh'
詳細については、こちらのWikiページをご覧ください。以下はクイックアクセスのための目次です。
プルリクエストは常に歓迎します。このプロジェクトは安全で歓迎的なスペースを意図しており、貢献者は貢献者の行動規範に従うことが期待されています。
学術研究でJAWを使用する場合は、以下の論文を引用することをお勧めします。
@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は長い道のりを経てきました。ここで貢献者に感謝の意を表します!
--cookies=<cookies.pkl>: ハイブリッドモードのみ、Cookieを含むファイル名。除外するには文字列 false を渡します(デフォルト: cookies.pkl)。--html=<html_snapshot.html>: ハイブリッドモードのみ、DOMツリースナップショットを含むファイル名。除外するには文字列 false を渡します(デフォルト: html_rendered.html)。