■Active Rulesスクリプト編(2) スクリプト作成時のテクニック・注意点
・「Script Active Scan Rules」のみを実行するスキャンポリシーの作成
part4で解説した通り、Active Rulesスクリプトは「動的スキャン(Active Scan)」の実行時に、スキャンポリシーの「一般」カテゴリの「Script Active Scan Rules」としてスクリプトが実行されます。
Active Rulesスクリプトを何度も実行してデバッグするようなときは、「Script Active Scan Rules」のみを実行するスキャンポリシーを作ってしまうと楽です。
作り方は、
1) ZAPのメニューの「ポリシー」-「スキャンポリシー」を選択。
2) 表示された「Scan Policy Manager」ウィンドウで「追加」を選択。
3) 表示された「スキャンポリシー」ウィンドウで、
・ポリシー名:任意(「script_only」など)
・Thresholdを、「一般」カテゴリの「Script Active Scan Rules」のみ「既定」、他は全てオフ
にして「OK」を押下
後は、動的スキャン実施時に表示されるダイアログで、「ポリシー」としてここで設定したポリシー名を指定すれば「Script Active Scan Rules」のみを手軽に実行させることができます。
注意点:ActiveRulesのスクリプト実行時printの結果が二重に入り乱れる場合
あと、気づきにくい注意点として、ActiveRulesのスクリプトを実行する際、ZAPのデフォルトの設定だと、「ツール」-「オプション」-「動的スキャンの設定」で「並列スキャンスレッド数:」の目盛りが「2」になっていますが、そうすると、作成したActiveRulesスクリプトも並列で2つ同時に実行されてしまうため、スクリプトの書き方によってはprintが二重に入り乱れて表示されてしまい混乱することがあります。
part4で作成したテンプレートそのままのサンプルでは大丈夫なようですが、スクリプトテスト時に妙な現象でハマらないために、ActiveRulesスクリプトの動作確認時には「並列スキャンスレッド数:」は「1」にしておくことをお勧めします。

■Active Rulesスクリプト編(2) ディレクトリ一覧を表示するスクリプトの作成
ではActive Rulesスクリプトの関数の呼ばれ方が分かったので、関数の中身を作っていってみます。
まずは、scanNode関数がノードごとに呼ばれることを利用して、URLがディレクトリであるかどうか判定してprintするような簡単な処理を書いてみます。
・ZAPの履歴からディレクトリ一覧を取得するスクリプト(ActiveRules版)
// scanNode関数
function scanNode(as, msg) {
// URI文字列
var uristr = msg.getRequestHeader().getURI().toString();
// ディレクトリであれば
if(isDir(msg)){
// URI文字列の末尾が'/'でなければ'/'を付ける
uristr = addSlashToURIString(uristr);
// ディレクトリ表示
print("dir: "+uristr);
}
}
// scan関数
function scan(as, msg, param, value) {
//nop
}
// URI文字列の末尾が'/'でなければ'/'を付けて返す
function addSlashToURIString(uristr){
// ディレクトリとみなし、末尾に/がなければ付ける
if(uristr.substr(uristr.length-1) != '/'){
uristr = uristr + '/';
}
return uristr;
}
// 現在のパスがディレクトリかファイルかを判定しtrue/falseを返す
function isDir(msg) {
path = msg.getRequestHeader().getURI().getPath();
var is_dir;
if(path!=null){
var patharr = path.split("/");
var chkfilename = patharr[patharr.length-1];
if (chkfilename.indexOf('.') > -1) {
is_dir = false;
} else {
is_dir = true;
}
} else {
// path==null:rootはディレクトリと判定
is_dir = true;
}
return is_dir;
}
このスクリプトをpart4でやったように、ActiveRulesスクリプトとして保存・有効化し、例えばhttp://localhost/zaptest/dir1/dir2/dir3/test.php?aaa=bbb
dir: http://localhost/
dir: http://localhost/zaptest/
dir: http://localhost/zaptest/dir1/
dir: http://localhost/zaptest/dir1/dir2/
dir: http://localhost/zaptest/dir1/dir2/dir3/
■Active Rulesスクリプト編(3) ディレクトリに対してOPTIONSを実行する
上のスクリプトに少し手を加えれば、例えば各ディレクトリにOPTIONSを発行するスクリプトが作成できます。
各ディレクトリに対して一括でOPTIONSを発行し、サポートしているメソッドの一覧が参照できれば、効率よく情報収集ができますので、サンプルとして作成してみます。
また、Active Rulesスクリプトの場合、アラートを上げることが可能なので、実装のサンプルとしてOPTIONSが有効だったらInfomationレベルのアラートを上げるようにしてみます。
・ZAPの履歴からディレクトリ一覧を取得し、OPTIONSメソッドを実行するスクリプト(ActiveRules版)
// scanNode関数
function scanNode(as, msg) {
// URI文字列
var uristr = msg.getRequestHeader().getURI().toString();
// ディレクトリであれば
if(isDir(msg)){
// リクエストをコピー
var clmsg = msg.cloneRequest();
// メソッドをOPTIONSにする
clmsg.getRequestHeader().setMethod("OPTIONS")
// sendAndReceive(msg, followRedirect, handleAntiCSRFtoken)
// 末尾が「/」でないURLの場合、いったん末尾が「/」のURLにリダイレクトされる
// 場合があるのでfollowRedirect==true
as.sendAndReceive(clmsg, true, false);
// リクエスト送信・レスポンス受信
rsp = clmsg.getResponseHeader().toString();
print("-------------------------------------------"
+"-------------------------------------------");
// レスポンスヘッダ内に"Allow:" ヘッダがあれば
if (rsp.indexOf("Allow:")>-1) {
// URI出力
print("[URI] "+uristr);
// "Allow:"ヘッダ の内容を出力
print("[OPTIONS] " + clmsg.getResponseHeader().getHeader("Allow"));
as.raiseAlert(0, 2, '*** OPTIONS Method ***',
'*** OPTIONS Method ***', clmsg.getRequestHeader().getURI().toString(),
'(options)', '(options)', '(options)', '(options)',
"[OPTIONS] " + clmsg.getResponseHeader().getHeader("Allow"), 0, 0, msg);
} else {
print("-");
}
// Check if the scan was stopped before performing lengthy tasks
if (as.isStop()) {
return
}
}
}
// scan関数
function scan(as, msg, param, value) {
//nop 何もしない
}
// URI文字列の末尾が'/'でなければ'/'を付けて返す
function addSlashToURIString(uristr){
// ディレクトリとみなし、末尾に/がなければ付ける
if(uristr.substr(uristr.length-1) != '/'){
uristr = uristr + '/';
}
return uristr;
}
// 現在のパスがディレクトリかファイルかを判定しtrue/falseを返す
function isDir(msg) {
path = msg.getRequestHeader().getURI().getPath();
var is_dir;
if(path!=null){
var patharr = path.split("/");
var chkfilename = patharr[patharr.length-1];
if (chkfilename.indexOf('.') > -1) {
is_dir = false;
} else {
is_dir = true;
}
} else {
// path==null:rootはディレクトリと判定
is_dir = true;
}
return is_dir;
}
このスクリプトをpart4でやったように、ActiveRulesスクリプトとして保存・有効化し、例えばhttp://localhost/zaptest/dir1/dir2/dir3/test.php?aaa=bbb
--------------------------------------------------------------------------------------
[URI] http://localhost
[OPTIONS] POST,OPTIONS,GET,HEAD,TRACE
--------------------------------------------------------------------------------------
[URI] http://localhost/zaptest
[OPTIONS] POST,OPTIONS,GET,HEAD,TRACE
--------------------------------------------------------------------------------------
[URI] http://localhost/zaptest/dir1
[OPTIONS] POST,OPTIONS,GET,HEAD,TRACE
--------------------------------------------------------------------------------------
[URI] http://localhost/zaptest/dir1/dir2
[OPTIONS] POST,OPTIONS,GET,HEAD,TRACE
--------------------------------------------------------------------------------------
[URI] http://localhost/zaptest/dir1/dir2/dir3
[OPTIONS] POST,OPTIONS,GET,HEAD,TRACE
また、OPTIONSが有効な場合ZAPのアラートも上げるようにしてあるため、

このような形で、OPTIONSが有効なディレクトリに対してアラートが作成され、アラートの詳細の「証拠」欄にOPTIONSの戻り値である有効なメソッド一覧が記載されています。

次はscan関数の使い方について書きます。
次へ