今回からは「Zest」編です。
OWASP ZAPを利用しているとZAPのあちこちのメニューに「Zest」云々というのがあるので、OWASP ZAPでスクリプト処理を行う際に、使いやすい言語は「Zest」なのかな? という印象が何となくあります。
しかし、実際にZAPでスクリプトでの処理をやろうとして「Zest」を調べてみると、サンプルコードを見ても通常の手続き型言語からかなりかけ離れたコードになっていて敷居が高く、どうやって作ったらいいのかよく分からず、ECMAScript(やrubyやpython)で処理書けそうだからいいか、となってしまって手を付けずに諦めてしまう人が多いのではないでしょうか。
ただ、調べてみると「Zest」はOWASP ZAPが暗に推すだけあって、ECMAScript等にはない便利さがあり、非常に使える言語でした。
今回も調査は手探りなので、何か漏れやら非効率等おかしなところもあるかもしれませんが、調べた結果を公開してみます。
■Zest編(1)モチベーションを上げる
Zestはかなり敷居が高いので、最初の段階からモチベーションを上げて取り掛からないと挫折率が高そうなので、モチベを上げる情報を最初に書いて、それから各種説明に入りたいと思います。
Zestを触ってみた印象では「ZAPをスクリプトで操作したい」という人が求めてるものはZestにあるのではないか、という感じがしました。
ZAPでZestを使うと
・複数画面遷移
・(CSRFチェックの入っている画面の)複数画面遷移
・複数画面遷をした後のページの自動スキャン(※)
・複数画面遷移を行いながらのファジングおよび判定ロジックの実装
こんな処理が結構簡単に設定できます。
やってみたくなってきましたでしょうか。
※ただし、後述しますが、Zestでできるのは「(複数)画面遷移を行った後でその画面にとどまっての動的スキャン」であり、「動的スキャンの1診断項目ごとに複数画面遷移を行ってPOST/GETを繰り返すような処理」はできないようなので、あまり期待はしすぎないようお願いします。
■Zest編(2)サンプルサイトの作成
CSRFチェックの入った画面遷移を行うサイトのサンプルを以下に置きます。あまり良いコードではないかもしれませんが、これをサンプルサイトとして使います。
https://sites.google.com/site/secmemofiles1452/cabinet/csrftestsite.zip
このzipをダウンロードするとphpファイルが4つ解凍されますので、それを自己管理下のphpが動作するWEBサーバーに置きます。
本例では以下、このサンプルサイトの4ファイルを http://localhost/zaptest/csrftest/ 下に配置したことにします。
■Zest編(3)サンプルコードの作成
OWASP ZAPを立ち上げ、画面左上のScriptsタブ - スクリプト - Stand Aloneを右クリックし、「新規スクリプト」を選択します。
すると「新規スクリプト」設定用のウィンドウが立ち上がるので、
Script名: script_test7
タイプ:Stand Alone
Script engine:Zest: Mozilla Zest
テンプレート:Standalone default template.js
開始時にロード:オン
という設定で「保存」を押下します。
すると保存後、「Edit Zest Script」という別のウィンドウが立ち上がるのですが、これはひとまず値は変えずにそのまま「保存」を選びます。
それからZAPをプロキシとしたブラウザでさきほど配布したサンプルサイトにアクセスします。
サンプルサイトは
http://localhost/zaptest/csrftest/index.php
↓
http://localhost/zaptest/csrftest/confirm.php
↓
http://localhost/zaptest/csrftest/complete.php
という遷移になっていますので、この順にブラウザでアクセスし、ZAPの履歴にこれらのURLを記録します。
ZAPの履歴上で、
http://localhost/zaptest/csrftest/index.php
への履歴を右クリック - 「Zest Scriptへ追加」 - 「script_test7」を選択。すると「Scripts」タブに切り替わり、「script_test7」の下に「→GET http://localhost/zaptest/csrftest/index.php」というノードが追加されます。「→GET http://localhost/zaptest/csrftest/index.php」の先頭に三角形のマークがあるので、クリックしてみると、
「Assert - Status Code(200)」
「Assert - Length(response body = [数値] +/- 1%)」
という二つの子ノードが表示されると思います。
これはZest ScriptにGETやPOSTのリクエストを挿入するとデフォルトで付くアサーションチェックの項目です。Zestスクリプトの実行時に、この条件に反する状態が発生しているとエラーとなります。
このアサーション項目の意味は、
「HTTPステータスコードが200」
「response bodyのlength(Content-Lengthとイコール)が[数値]のプラスマイナス1%の範囲」
ということです。
レスポンスのHTTPステータスコードが200以外だったり、レスポンスのbodyのlengthがZest登録時と大幅に違う場合は異常が発生したと判定しNGとなります。
試しに、ページをリネームなどで404になるようにして一度Zestを実行してみましょう。
Stand Aloneスクリプトの実行は、ZAPの画面の右上、Scriptコンソールタブの下に「実行」ボタンがあるのでそれを押下するだけです。
アサーションチェックの結果が表示されます。ステータスコードが404で200以外なのでバツマークとなります。
このアサーション項目はノード右クリックのメニューで削除することもできますし、ダブルクリックして内容を編集することも可能です。
※ここで一つ注意点があるのですが、このresponse bodyのlengthに関するアサーションにバグがあり、マルチバイト(日本語など)の文字列がページ内にあって、Content-Typeヘッダーに「charset=UTF-8」などの文字コードの指定があると、サイズの算出がおかしくなり、アサーション結果がNGになってしまいます。
このブログを書いているときにこのバグを見つけ、開発元のGitHubにIssueを投げましたので、そのうち解消されると思われますが、現状だと日本語を含むページを扱う際にはこの「Assert - Length(response body = [数値] +/- 1%)」のアサーションは削除しておく必要があります。(本項のサンプルサイトは日本語を使っていないのでアサーションの削除は不要です)
アサーションの動作確認が完了したら、次に残りのURL、
http://localhost/zaptest/csrftest/confirm.php
http://localhost/zaptest/csrftest/complete.php
の履歴も同様に、履歴上で右クリック - 「Zest Scriptへ追加」 - 「script_test7」を行います。
「script_test7」の下にPOSTのノードが二つぶら下がります。
この状態で、Zest画面上部の「実行」を押下すると「index.php」-「confirm.php」-「complete.php」へのリクエストが順に発生し、ZAP画面下部の「Zest Results」タブにアサーションの結果が表示されます。(アサーション結果がNGでも処理は止まらず、最後まで実行されます)
ここで、confirm.phpとcomplete.phpのアサーションがFAILEDになっているのは、CSRF対策用トークンがエラーになっていてエラー画面が表示されているため、正常系の画面とは別の画面が表示されていてresponse bodyのlengthが大幅に変わっているからです。
ここで単純な「複数画面遷移」には成功しましたが、CSRFチェックが入っている画面遷移には対応できていないので、次回はCSRFチェックが入っている複数画面遷移を成功させてみます。
次へ