初めに
業務でOWASP ZAPを用いた脆弱性診断を行う機会があったので備忘録的に。
設定から実際の診断までの流れを一通り説明します。
環境
- macOS High Sierra ver 10.13.6
- OWASP ZAP ver 2.8.0
ダウンロード
こちらからダウンロードすることができます。
起動
OWASP ZAP起動時、以下のダイアログが出現します。
ver2.4以降、セッションの保持方法が選択可能となりました。セッションにより保持されるデータは、アクセス/スキャンしたURL、そのリクエスト/レスポンス、発見された脆弱性などです。しかし、スパイダーや動的スキャンそのもののデータは保持されません。
セッションデータを読み込むことで、設定や診断結果を再現することが可能となります。
全ての場面ではなく、必要に応じて保存すればよいケースがほとんどだと思うので、「継続的に保存せず、必要に応じてセッションを保存」を選択すれば事足りるでしょう。
また、ダイアログ内メッセージにもある通り、この設定は「オプション > データベース」から変更が可能です。
セッションの保持に関しては、以下の記事が大変参考になります。
OWASP ZAP 2.4 のデータ保存について - Web Application Security Memo
起動後最初に行うこと
まず初めに、モードをプロテクトモードに変更しましょう。
標準モード/攻撃モードだと、意図せず自分の管理外のサイトをスキャンしてしまう恐れがあります。
また、セーフモードではブラウザで画面操作しながらレスポンスを解析する静的スキャンは可能ですが、実際に攻撃を仕掛ける動的スキャンは実行することができません。
設定
設定の流れは、
- ローカルプロキシの設定
- コンテキストの設定
- その他の設定(Basic認証、ログイン処理、CSRFトークン対応)
の3段階に分けて記載します。
1. ローカルプロキシの設定
OWASP ZAPをプロキシとして使用することで診断対象サイトへリクエストを送信し、そのレスポンスから脆弱性を診断します。
OWASP ZAP側の設定
「ツール」 > 「オプション」 > 「ローカル・プロキシ」を選択。
Address欄には「localhost」、ポート欄には任意のポート番号(他と競合しない番号)を入力。49152~65535は自由に利用できるポート番号として割り当てられているため、今回は「55555」を使用。
ポート番号の入力欄は見えづらいので(使ってみれば分かります)、右スクロールまたは画面拡大するのが良いでしょう。
※画面左上の赤枠にて「プロテクトモード」を選択していますが、他サイトに誤って攻撃を仕掛けないためにも最初にこの設定に変更しておきましょう。デフォルトでは「標準モード」が選択されています。
ブラウザ側の設定
今回使用するブラウザはFireFoxです。Firefoxはプロキシ設定をOSと切り離して行うことができるため、設定の戻し忘れによるネットワーク繋がらない問題を回避できたりと、何かと便利なようです。
画面右上ハンバーガーメニュー > 「設定」 > 画面下部の「ネットワーク設定」の「接続設定」を選択。
「手動でプロキシーを設定する」を選択し、HTTP プロキシー欄に「localhost」、ポート欄に先程OWASP ZAP側で設定したものと同じ番号「55555」を入力。
さらにその下の「すべてのプロトコルでこのプロキシーを使用する」にチェック。
これにてプロキシの設定は終了です。
2. コンテキストの設定
次にコンテキストの設定を行います。簡単に言えば、診断対象となるサイトを指定することです。
**あくまでも診断は自分が管理するサイトに対してのみ行うようにしてください。**許可を得ないまま他サイトに攻撃仕掛けちゃうとまずいので、充分注意しましょう。
※筆者は「じゅうぶん」は「十分」ではなく「充分」と書く派です。駿台予備校時代に数学の石川先生に影響を受けました。
1でプロキシの設定を終えた後、診断したいサイトにFireFoxからアクセスしてみてください。
すると、以下の画像の赤枠で囲った部分に諸々反映されてくるはずです。
ここで診断対象としたいサイトのトップURLを右クリックし、「コンテキストに含める」 > 「New Context」を選択すると、以下の画面が出てきます。
ここで診断対象サイトのURLを確認し、右の「変更」ボタンをクリックし、\Qと\Eで囲ってエスケープしておきましょう。
コンテキストに含めることができたら、左側のコンテキスト欄に診断対象サイトのURLが追加されていることを確認しましょう。
以上で基本的なコンテキストの設定は終了です。
3. その他の設定
さて、ここまできて早速診断を開始したいところですが、いくつか問題がありました。
今回の診断対象サイトにはBasic認証が設定されており、かつログイン機能がありました。
今回はその他の設定として、Basic認証とログイン処理への対応方法を紹介します。
Basic認証への対応方法
jsで記述したスクリプトを読み込み実行することで対応します。
- 「サイト」の右の「+」 > 「スクリプト」をクリック。
org.parosproxy.paros.network.HttpSender.addListener(
new org.zaproxy.zap.network.HttpSenderListener {
getListenerOrder: function() {
return 1;
},
onHttpRequestSend: function(msg, initiator) {
msg.getRequestHeader().setHeader(
// 第1引数:「Authorization」、第2引数:「Basic 」 + 「ユーザー名:パスワード」をBase64でエンコードした文字列
“Authorization”, “Basic xxxxxxxxxxxxxxxxxx”
);
},
onHttpResponseReceive: function(msg, initiator) {
}
});
ログイン処理への対応方法
自動認証機能を使用します。
これにより、ログインが必要なページに移動した際、適切なPOSTデータを送信し、ログイン状態となって移動してくれます。また、ログアウトした際にも、ログアウト状態(つまりログインしていない状態)であることを検知し、自動でログイン処理を行い期待する動作に復帰してくれます。
- 診断対象コンテキストをダブルクリックし、「認証」部分をクリック。
- 「Currently selected Authentication method for the Context」 => 「Form-based Authentication」を選択。※今回はemailとpasswordの2つのパラメータによる認証フォームを想定しています。
- 「Login Form Target URL」にログインページのURLを入力。
- 「Login Request Post Data(if any)」にPOSTで送信されるパラメータを入力。デフォルトのusername, passwordの部分を適宜変更しましょう。
- 「Username Parameter」と「Password Parameter」を適切な値に設定。今回は「Username Parameter」 => 「email」、 「Password Parameter」 => 「password」となります。
- 「Regex pattern identified in Logged In response messages」に、HTTPレスポンスヘッダまたはボディの中で、ログイン状態の際にのみ出現する文字列を正規表現で指定。この文字列が含まれていればログイン状態、含まれていなければログアウト状態であると判断されます。今回はログアウトリンクを指定しました。
- 「Regex pattern identified in Logged Out response messages」は、上の「Regex pattern identified in Logged In response messages」を入力していれば入力は不要です。5と反対にログアウト状態であると識別するための文字列を指定します。
-
その下の「ユーザ」をクリック。
- 右側の「追加」をクリック。
- ユーザ名:何でもよい。今回は適当にtestuserと入力。
- 有効チェックボックス:ON
- Username:ログイン権限のあるユーザの名前
- パスワード:5のユーザのパスワード
- 「追加」、「OK」をクリック。
有効になる前
これにてログイン処理への対応の準備も整いました。
以上で初期設定は完了となります。
いよいよここから実際に診断を行っていくのですが、ここまでで体力が尽きてしまいました。
また気が向いた際に実際の診断方法なども執筆していきたいと思います。
頻出アラートと対処例
・X-Content-Type-Optionsヘッダの設定ミス
HTTP Respose Headerに「X-Content-Type-Options: nosniff」を付与する。
最後に
これが私のQiitaデビューです!
最後までお読みいただきありがとうございました!
間違っている箇所などあればご指摘いただけると幸いです。