Web アプリケーション診断
診断の仕組み
Shisho Cloud は、登録されたそれぞれのシナリオに対して擬似攻撃を送信し、レスポンスを精査して脆弱性を検出します。 シナリオは、依存関係を持つエンドポイントのシーケンスです。
アプリケーションによっては、リクエストに認証ヘッダーやログイン後の Cookie など特定の情報を付与する必要がある場合があります。 認証設定を登録することにより、巡回や診断でリクエストを送信する際に付与すべきヘッダー等を指定できます。 付与するヘッダー等の値は固定値だけでなく、ログイン操作を表すシナリオをリプレイして動的に抽出することもできます。
場合によっては、アプリケーションの一部機能を診断の対象外にしたいこともあるでしょう。 そのような場合には、スコープを適切に設定することにより、アプリケーションの特定部分のみを診断することができます。
以降のセクションでは、それぞれの概念をより詳しく説明します。
スコープ
スコープは、アプリケーションの診断対象とする範囲を定義します。
デフォルトの入力方式では、URL の prefix を指定すると、その prefix から始まる URL が診断対象になります。 「スコープを追加」ボタンをクリックして、複数の prefix を指定することもできます。
トグルをクリックして上級者モードに切り替えると、prefix の代わりに正規表現を用いて、診断対象とする URL の範囲を定義できます。
シナリオ
シナリオは、診断の単位であり、依存関係のあるエンドポイントのシーケンスを表します。例えば以下のようなリクエストの流れをシナリオとして表現でき、エンドポイントの関係性を踏まえた診断が可能となります。
- 入力画面の CSRF トークンを抽出し、それを付与して POST リクエストを送信する
- アイテムを削除するリクエストを送信する前に、アイテムを作成するリクエストを送信する
- アイテムの作成リクエストを送信した後に、アイテム情報が表示される画面をリクエストし、蓄積型の脆弱性を検出する
シナリオは1つ以上のステップから構成され、1つ1つのステップはリクエストを送信するエンドポイントを指します。
例えば以下の2ステップからなるシナリオは、アイテムを作成した後にアイテム一覧画面をリクエストするものです。これにより、アイテム作成に起因する蓄積型の脆弱性を検出することができます。
各ステップの YAML 入力欄には以下の詳細オプションを記述できます。
- ステップ間の入出力の関係を表すもの
extractors
: リクエストの結果から値を抽出し、変数に格納して後続のステップで使えるようにするbindings
: 以前のステップのextractors
で変数に格納した値を、このステップのリクエストパラメータに注入する
- 診断での取り扱いを調節するもの
skipInjection
: そのステップに攻撃ペイロードを注入しない
extractors
リクエストの結果から値を抽出し、変数に格納して後続のステップで使えるようにする設定項目であり、後述する Extractor オブジェクトの配列を指定します。配列の要素として複数の Extractor オブジェクトを指定すれば、複数の情報を抽出してそれぞれ変数に格納できます。
YAML 入力欄に例えば以下を入力すると、レスポンスボディに対して正規表現 token=([a-z0-9]+)
によるマッチが行われ、([a-z0-9]+)
にマッチした部分が変数 token
に格納されます。
extractors:
- name: token
type: regex
regex:
- 'token=([a-z0-9]+)'
group: 1
Extractor オブジェクト
Extractor オブジェクトは、リクエストの結果から値を抽出する方法と、抽出した値を格納する変数名を定義します。
基本的な構造は以下の通りです。name
にて指定した変数名は、後続するステップの bindings
で用いられます。type
には抽出方法のタイプを指定し、さらに抽出方法ごとの設定項目が続きます。
name: "<格納先の変数名>"
type: "<抽出方法のタイプ>"
# ... <抽出方法に応じた設定> ...
抽出方法のタイプには以下のいずれかを指定します。
regex
Extractor
正規表現を用いた抽出を表す Extractor です。
設定項目:
regex
: 抽出に用いる正規表現の配列- 構文については RE2 のドキュメントを参照してください
group
: 値を抽出するキャプチャグループの番号- デフォルト: 0 (マッチの全体)
part
: 正規表現でマッチする対象body
: レスポンスのボディ (デフォルト)header
: レスポンスのヘッダー
例えば以下の Extractor は、レスポンスのヘッダーに対してマッチを行い、1番目のグループ、つまり Location
ヘッダーの値の部分を redirect_url
という変数に格納します。
name: redirect_url
type: regex
regex:
- '(?m)^Location: (.+?)$'
group: 1
part: header
xpath
Extractor
XPath を用いて HTML や XML から値を抽出する Extractor です。
設定項目:
xpath
: 抽出に用いる XPath の配列attribute
: 抽出する属性名- 未指定の場合: ノードのテキスト
例えば以下の Extractor は、1番目の <form>
要素の内部にある <input name="csrf_token" value="...">
のような要素を検索し、その value
属性の値を csrf_token
という変数に格納します。
name: csrf_token
type: xpath
xpath:
- '//form[1]//input[@name="csrf_token"]'
attribute: value
目的の要素を指す XPath は、ブラウザの開発者ツールを用いて簡単に取得できます。詳細な手順はブラウザごとに異なりますが、開発者ツール上で目的の要素を右クリックし、「Copy XPath」のようなメニューを選択すると、その要素を指す XPath がクリップボードにコピーされます。また、開発者ツールのコンソールでは、 $x('//form[1]//input[@name="csrf_token"]')
のように $x
関数を用いて、XPath による検索結果を確認できます。
json
Extractor
jq クエリを用いて JSON から値を抽出する Extractor です。
設定項目:
json
: 抽出に用いる jq クエリの配列
例えば以下の Extractor は、レスポンスボディが {"item": {"id": "XXXX", ...}}
のようなデータである場合に、 XXXX
の部分を抽出して item_id
という変数に格納します。
type: json
name: item_id
json:
- '.item.id'
bindings
以前のステップの extractors
で変数に格納した値を、このステップのリクエストパラメータに注入する設定項目です。
例えば以下の設定は、以前のステップで csrf_token
という変数に格納された CSRF トークンを、リクエストボディの .csrf_token
というパラメータに注入します。
bindings:
- type: body # 注入するパラメータのタイプ
key: .csrf_token # 注入先
extractorName: csrf_token # 注入する値を格納した変数名
type
には pathParam
, header
, query
, body
のいずれかを指定します。
key
には注入先のパラメータを指定します。
タイプが pathParam
, header
, query
の場合は、パラメータ名をそのまま指定します。例えばヘッダー Custom-Header: XXXX
に注入したい場合は、key: 'Custom-Header'
と指定します。
タイプが body
の場合は、プロパティ名をドットで繋いで注入したい箇所を指定します。例えば、リクエストボディが {"item": {"id": "XXXX", ...}}
のような JSON である場合に、key: '.item.id'
と指定すると、XXXX
の部分に値が注入されます。
extractorName
には、以前のステップの extractors
において、name
フィールドに記載した変数名を指定します。
skipInjection
ステップに skipInjection: true
と設定すると、診断時にそのステップに攻撃ペイロードが注入されなくなります。
例えば蓄積型の脆弱性を検出するために、1番目のステップで POST /items/new
に攻撃リクエストを送信し、2番目のステップで GET /items
をリクエストしてレスポンスに問題がないか検査するシナリオを定義したいとします。この目的のもとでは、攻撃ペイロードは1番目のステップだけに注入したいですから、2番目のステップには skipInjection: true
を設定します。
認証設定
認証設定を定義することにより、巡回や診断の際に送信されるリクエストに、適切なヘッダーや Cookie を付与させることができます。
「認証情報の付加箇所」は、リクエストに付与したい情報の箇所を「ヘッダー」「クエリパラメータ」「ボディ」から選択します。例えば Cookie を付与したい場合は「ヘッダー」を選択し、「ヘッダー名」欄に Cookie
と入力します。
リクエストに付与したい値については、「ヘッダー値」または「パラメータ値」の欄にて指定します。付与する値の指定方法としては、「固定値」と「認証リクエストを送信して抽出」の2つがあります。付与する値に有効期限等がない場合は「固定値」、有効期限等がある場合は「認証リクエストを送信して抽出」が適しています。
「固定値」を選択した場合には、リクエストに付与すべき値をそのまま入力します。
シナリオから認証情報を抽出する
「認証リクエストを送信して抽出」を選択した場合は、以下の設定項目が追加されます。
- 「認証情報の取得方法」: シナリオから認証情報を取得するので、「シナリオから抽出」のままにする
- 「認証リクエストのシナリオ」: 付与したい値を得るためのリクエスト手順を表すシナリオ
- 「認証リクエストのパラメータ」: 上記シナリオに注入すべきパラメータ (ユーザー名、パスワード等)
- 「認証情報の抽出方法」: レスポンスから値を抽出する方法
- 「認証情報の更新条件」: 認証リクエストの送信と抽出を再実行すべき条件 (有効期限等)
認証リクエストのパラメータ
「認証リクエストのシナリオ」に注入するパラメータを指定します。
例えば以下の設定は、シナリオの1番目 (0-indexed) のステップに対して、username
と password
の2つのパラメータを注入します。
- stepIndex: 1
type: body
key: .username
value: test
- stepIndex: 1
type: body
key: .password
value: n}0b6P@5jkjy&7<KFdwANh9f>IY_?,Ty
この設定項目には、以下のプロパティとするオブジェクトの配列を入力します。
stepIndex
: パラメータを注入するステップのインデックス (0-indexed)type
: パラメータのタイプ (pathParam
,header
,query
,body
のいずれか)key
: パラメータの名前- タイプが
pathParam
,header
,query
の場合は、パラメータ名をそのまま指定します - タイプが
body
の場合は、プロパティ名をドットで繋いだものを指定します- 例えばリクエストボディが
{"item": {"id": "XXXX", ...}}
のような JSON である場合に、key: '.item.id'
と指定すると、XXXX
の部分に値が注入されます
- 例えばリクエストボディが
- タイプが
value
: パラメータの値
認証情報の抽出方法
「認証リクエストのシナリオ」のレスポンスから値を抽出する方法を、Extractor オブジェクトを用いて指定します。なお、Extractor の name
フィールドは省略できます。
例えば以下の設定は、レスポンスヘッダーから Set-Cookie: session=XXXX
のような文字列を検索し、XXXX
の部分を抽出します。
part: header
type: regex
regex:
- "Set-Cookie: (session=[a-zA-Z0-9]+)"
group: 1
認証情報の更新条件
認証リクエストの送信と抽出を再実行すべき条件を設定します。
例えば以下のように設定すると、巡回や診断の初期状態や、前回の抽出から60分が経過した場合に、認証リクエストの送信と抽出が実行されます。
- type: BLANK # 初期状態で更新
config: {}
- type: EXPIRE # 生成から60分以上経過していたら更新
config:
expiresIn: 60m
配列の各要素は、type
フィールドと config
フィールドを持ちます。
type
フィールドには以下のいずれかを 指定します。
BLANK
: 初期状態で更新EXPIRE
: 前回の更新から一定期間が経過した場合に更新
type: BLANK
config
フィールドは空オブジェクト {}
です。
type: EXPIRE
config
フィールドには、更新が必要となる期限を expiresIn
フィールドとして指定します。
- type: EXPIRE
config:
expiresIn: 60m
expiresIn
フィールドの単位としては、s
(秒), m
(分), h
(時間) を利用できます。
用意された認証処理から認証情報を抽出する
Shisho Cloud で用意された認証処理を使用して認証情報を取得することができます。現時点で対応している認証処理は以下です。
「認証リクエストを送信して抽出」を選択し、「認証情報の取得方法」は「用意された認証処理から抽出」に設定すると、指定された認証処理の設定項目が表示されます。
Firebase から認証情報を抽出
Firebase に接続して ID Token 等を取得する認証処理です。現時点では、メールとパスワードの認証のみ対応しております。
「認証情報の取得方法」は「用意された認証処理から抽出」を選択し、「認証処理の種類」は「Firebase 認証」を選択します。
Firebase 認証の場合だと「認証処理の内容」は以下のフィールドを設定する必要があります。
email
: ログインアカウントのメールアドレスpassword
: ログインのパスワードapiKey
: Firebase 発行の API キーextractors
: 抽出する認証情報の項目
「認証処理の内容」の例:
email: user@example.com
password: user_p@ssword
apiKey: 8gpUlIEUgExk8J5oM13
extractors:
- type: json
part: body
json:
- '.id_token'
extractors
は type
と part
は上記同様それぞれ json
と body
を指定する必要があります。json
のフィールドの値は以下が指定可能です。
.id_token
.refresh_token
.expires_in
json
のフィールドは値が一つまでしか指定できません。extractors
はシナリオを後続処理として行う場合のみに複数指定することが可能です。シナリオの後続処理を行わない場合は extractors
で設定された値が抽出されます。
「認証情報の更新条件」の設定はシナリオから認証情報を抽出する場合と同じです。
Cognito から認証情報を抽出
Cognito に接続して ID Token 等を取得する認証処理です。現時点では、メールとパスワードの認証のみ対応しております。
「認証情 報の取得方法」は「用意された認証処理から抽出」を選択し、「認証処理の種類」は「Cognito 認証」を選択します。
Cognito 認証の場合だと「認証処理の内容」は以下のフィールドを設定する必要があります。
email
: ログインアカウントのメールアドレスpassword
: ログインのパスワードregion
: AWS のリージョンのコードclientId
: Cognito 発行のクライアント IDextractors
: 抽出する認証情報の項目
「認証処理の内容」の例:
email: user@example.com
password: user_p@ssword
region: ap-northeast-1
clientId: 7siaq79aq0hql9abh
extractors:
- type: json
part: body
json:
- '.id_token'
extractors
は type
と part
は上記同様それぞれ json
と body
を指定する必要があります。json
のフィールドの値は以下が指定可能です。
.id_token
.access_token
.refresh_token
.token_type
.expires_in
json
のフィールドは値が一つまでしか指定できません。extractors
はシナリオを後続処理として行う場合のみに複数指定することが可能です。シナリオの後続処理を行わない場合は extractors
で設定された値が抽出されます。
「認証情報の更新条件」の設定はシナリオから認証情報を抽出する場合と同じです。
Auth0 から認証情報を抽出
Auth0 に接続して ID Token 等を取得する認証処理です。現時点では、メールとパスワードの認証のみ対応しております。Auth0 認証のカスタムドメインも現時点では対応しておりません。
「認証情報の取得方法」は「用意された認証処理から抽出」を選択し、「認証処理の種類」は「Auth0 認証」を選択します。
Cognito 認証の場合だと「認証処理の内容」は以下のフィールドを設定する必要があります。
email
: ログインアカウントのメールアドレスpassword
: ログインのパスワードdomain
: Auth0 発行の認証ドメイン (auth0.com
のサブドメイン)clientId
: Cognito 発行のクライアント IDclientSecret
: Cognito 発行のクライアントシークレットcallbackUrl
: Cognito の設定で許容した callback の URLextractors
: 抽出する認証情報の項目
「認証処理の内容」の例:
email: user@example.com
password: user_p@ssword
domain: dev-sample-app.jp.auth0.com
clientId: 7siaq79aq0hql9abh
clientSecret: HTOuBdIlg0LukDe0Fm5lTDCjTkYcBDu
callbackUrl: https://example.com/callback
extractors:
- type: json
part: body
json:
- '.id_token'
extractors
は type
と part
は上記同様それぞれ json
と body
を指定する必要があります。json
のフィールドの値は以下が指定可能です。
.id_token
.access_token
.token_type
.expires_in
json
のフィールドは値が一つまでしか指定できません。extractors
はシナリオを後続処理として行う場合のみに複数指定することが可能です。シナリオの後続処理を行わない場合は extractors
で設定された値が抽出されます。
「認証情報の更新条件」の設定はシナリオから認証情報を抽出する場合と同じです。