はじめに
OWASP ZAPでログイン認証が必要なWebサイトを診断する場合、
「認証設定」「ログイン状態の判定」「セッション管理」の設定が必要になります。
しかし公式ドキュメントでは以下の点がわかりづらいと感じました。
- Authentication Verificationの違い
- Form / JSON 認証の設定方法
- 認証成功の確認方法
この記事では 実際の設定例と挙動を交えて解説します。
この記事の対象読者
- OWASP ZAPでログインが必要なサイトを診断したい人
- 認証設定がうまくいかない人
次回以降、「Script-Based Authentication」や「Auto-Detect Authentication」について書く予定です。
また、「Automation Framework」やSPA等のクロールしにくいサイトに対するSpider, Ajax Spider等を工夫して行う方法もまとめていきたいと考えています。
【OWASP ZAP】認証設定 (2) ログインスクリプトの作り方。Dockerでのスクリプト利用方法
本記事内で触れていない、インストールから設定、スパイダー、診断の基本的な方法は以下サイトがわかりやすかったです。
目次
- ZAP認証設定の全体像
- 共通設定項目
- Authentication Verification
- GUIなし(Docker / CI)で認証成功を確認する方法
- Form-Based Authentication: HTMLフォームを使った認証
- JSON-Based Authentication: JSONリクエストを使ったAPI認証
- HTTP/NTLM Authentication: ベーシック認証・NTLM認証など
動作環境
- ZAP GUI: 2.15.0
- Docker Image: zaproxy/zap-stable:20240902
ZAP認証設定の全体像
ZAPの認証設定は各Contextに対して行います。
通常、診断対象サイトごとにContextを作成し、それぞれ認証・セッション・ユーザー設定をしていきます。
Context
├ Authentication
├ Session Management
├ Users
└ Forced User Mode
共通して設定必要な項目
Authentication Verification
Authentication Verificationは
ZAPが「現在ログイン状態かどうか」を判断するための仕組みです。
診断中にセッションが切れた場合、
ZAPはこの設定を元にログアウト状態を検出し、
自動的に再ログインを試みます。
公式ドキュメント - Authentication Verification Strategies
ログインに成功したかどうかは、GUIの「アウトプット」で確認でき、「ログインに成功しました」や「ログインに失敗しました」と表示されます。
ZAP内に保存されているAuthentication Statisticsの値でも確認でき、ZAPのAPIを利用することでAuthentication Statisticsの値を取得できます。
ZAP – Authentication Statistics
statsViewStats – API Reference
Authentication Verificationの設定は以下項目から選択できます。
- Check every Response
- Check every Request
- Check every Request or Response
- Poll the Specified URL
- Auto-Detect
Check every Response、Check every Request、Check every Request or Response
レスポンスまたはリクエストに含まれる文字列でログイン状態を判定します。
使用例:
ログイン中のレスポンスHTMLに以下のような文字列が含まれる場合
<a href="/logout">ログアウト</a>
設定例:
(例)Logged In Indicator: \Q<a href="/logout">ログアウト</a>\E
この方法が向いているサイト
- HTMLサイト
- 画面に「ログアウト」リンクがあるサイト
※ 設定例の\Q と \E は 正規表現のエスケープ指定です。
ZAPでは Indicator に正規表現を指定できますが、
単純な文字列として扱いたい場合は
\Q 文字列 \E
で囲みます。
例
\Q<a href="/logout">ログアウト</a>\E
Poll the Specified URL
特定のURLにアクセスした際のリクエストまたはレスポンス内に含まれる文字列でログイン状態を判定します。
上記設定時と同様に「Logged In Indicator」、「Logged Out Indicator」を設定します。
この方法が向いているサイト:
- HTMLレスポンスではログイン状態が判別できないとき
- ログイン状態を確認できるAPIエンドポイントがあるとき
Auto-Detect
Auto-Detect はログイン前後の通信を解析してログイン状態の判定方法を自動推定します。
主に以下を元に判定します。
パラメータ設定がなく楽なのですが、失敗してしまうケースも多かったです。その場合、他の方法で設定します。
- Cookieの変化
- レスポンス内容の差分
- 認証後に出現するURL
GUIなし(Docker / CI)で認証成功を確認する方法
ZAPをDockerコンテナで起動して、API等で診断を実行するケースやCIに組み込むケースがあります。
その場合、ZAPのGUIが見られないため、API等を利用してログインに成功したか判断する必要があります。
ログインできたかどうかを早く判別することで、設定および診断にかかる時間を短くできます。
APIでログインを判別する方法
-
方法1: 「stats.auth.component.state.loggedin」の値を利用
ZAPの内部に保存されている「stats.auth.component.state.loggedin」をAPIで取得します。
その値が0より大きい場合、ログインに成功したと判断できます。 -
方法2: スパイダーの結果確認
スパイダーを実行した後、取得されたURLリストの中にログイン後でないとアクセスできないURLが含まれている場合、ログイン成功と判断できます。
認証が必要なURL例:
/dashboard
/account
/settings
「コンテキストに含まれるURL」設定で、認証が必要なURL1つのみを設定して、スパイダー実行(認証成功確認用のみだけに実行するスパイダー)をすることでかかる時間を短縮できます
Form-Based Authentication
フォーム認証のあるサイトを診断できます。ログインフォームに追加パラメータ(hiddenフィールドなど)がある場合でも
POSTデータに含めれば対応できます。
ただし以下の場合は
Script-Based Authenticationが必要になります。
- 多段ログイン(2画面ログイン)
- JavaScriptでトークン生成
- OAuth / SSO
CSRF対策のトークン等がある場合には、別途CSRF対策トークン名を設定することで、認証できます。
設定項目
- Login Form Target URL
ログイン時に認証情報を送信するURL(POSTメソッド) - URL to GET Login Page
CSRF対策のトークンがある場合などに、上記Target URL送信前にアクセスするページ - Login Request POST Data
ユーザー名のフィールド名とパスワードのフィールド名を設定する項目。設定の仕方がわかりづらいので注意する必要があります。
(例)ユーザー名のフィールド名が「username_field」、パスワードのフィールド名が「password_field」の場合
username_field={%username%}&password_field={%password%}
- Username Parameter
- Password Parameter
Username/Password Parameterは「Login Request POST Data」設定後に、{%~%}となっている項目から選択可能です。
JSON-Based Authentication
認証をJSON形式のデータで行う場合に使用します。設定項目自体は「Form-Based Authentication」と同じです。
「Form-Based Authentication」が「name1=value1&name2=value2」という形式で認証情報を送信するのに対し、
こちらではJSONオブジェクトで送信します。
(例){"username": "{%username%}", "password": "{%password%}"}
HTTP/NTLM Authentication
HTTP Basic認証などブラウザの認証ダイアログで認証が行われるサイトに使用します。
ホスト名、認証レルム、ポートを設定することで利用できます。認証レルムはサーバー側から提示される場合が多く、指定しなくても認証に成功するケースもあります。
本ポストで紹介しなかったけれど、認証が必要なサイトに診断する際に設定必要な項目は下記があります。それほどわかりづらくないと思います。
-
コンテキストに含まれるURL
診断対象とするURLを正規表現で設定する。ワイルドカード設定は「.*」で可能です。
(例)https://example.jp.* -
セッション管理
ほとんどのWebアプリケーションではCookie-Based Session Managementを使用します。
下記項目から選択- Cookie-Based Session Management
ログイン中か判別するために使用されるsession id等がcookieに保存されている場合 - HTTP Authentication Session Management
Authorizationヘッダーでログイン中か判別する場合 - Script-Based Session Management
上記2つで対応できない複雑なセッション管理をしている場合、スクリプトを自作することで対応することもできます。 - Header-Based Session Management
比較的新しい機能で、HTTPヘッダーを利用したセッション管理に対応するための設定と考えられます。 - Auto-Detect Session Management
新しく追加されているが、ドキュメントに記載もなく詳細が不明です。
- Cookie-Based Session Management
-
ユーザ
認証時に使用するユーザー名、パスワードの設定をします。複数ユーザー登録可能です -
強制ユーザ(Forced User Mode)
Forced User Modeを有効にすると、
ZAPが送信するすべてのリクエストに対して
指定したユーザーの認証情報が使用されます。主な用途
- Spider
- Active Scan
- Manual Request
を 常にログイン状態で実行したい場合
おわりに
次回はログインスクリプトの作り方や使用例について解説します。
以下のようなケースへの対応方法を紹介予定です。
- フォーム認証 + ベーシック認証
- Seleniumログイン
- LocalStorage認証
- AWS Cognito認証