■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関数の使い方について書きます。
次へ