技術部の津野田です。
昨今、Webアプリケーションに対するセキュリティ診断の内製化の動きが活発になっています。 本日より、当社のお仕事が減らない程度に、セキュリティ診断の内製化に役立つ情報をざっくばらんに不定期発信して行く予定です。
第一回目は、内製化の際に多く利用されるWebアプリケーション脆弱性診断ツール(以下、脆弱性診断ツール)の実力を、さらに引き出すためのコツについてお話したいと思います。
なお、本稿では特定の製品に関するご案内はしていません。 具体的な設定手順や方法などについては、脆弱性診断ツールのマニュアルをご確認ください。
はじめに
まずは、Webアプリケーションにおける代表的な脆弱性を、 一般的な脆弱性診断ツールによる検出の得手不得手で分類してみました。
比較的得意な分野
- XSS(反射型)
- プラットフォーム上の問題
ケースによっては得意な分野
- XSS(格納型、DOMベース)
- CSRF
- パストラバーサル
- SQLインジェクション
- コード・インジェクション
比較的苦手な分野
- XSS(ブラウザ依存)
- 認可・権限・アクセス制御
- 設計上の問題
- 競合状態(レースコンディション)
得手、不得手の根拠
脆弱性診断ツールに事前登録されているスキャンポリシーで検出できるケースが多いものを得意な分野としました。 そのため、利用者は特別な設定せずともこれらの脆弱性については、多くの場合検出することができます。
逆に、苦手な分野では事前登録されているスキャンポリシーで検出できるケースがそう多くありません。 そのため、一般的に利用者自身がスキャンポリシーに落とし込む作業が必要になってきます。
つまり、脆弱性診断ツールの実力を引き出すためには苦手な分野をうまくスキャンポリシーに落とし込み、弱点を補うことが必要になってきます。
実力を引き出すスキャンポリシー作成方法
脆弱性をスキャンポリシーに落とし込むために、大きく分けて以下の2つのコツがあります。
- 診断観点の考察
- 診断手法の考案
それぞれを詳しく説明していきます。
診断観点の考察
スキャンポリシーに落とし込むためには、まず脆弱性の観点を知る必要があります。
次の脆弱性はだれもが「まずい」脆弱性だと認識することができるかと思います。
- 一般ユーザアカウントで管理者アカウント専用画面を閲覧することが可能である。
- 実際よりも安価な決済金額で決済完了することが可能である。
- 現金化が可能なポイントを無限に増殖することが可能である。
しかし、これらの脆弱性はいずれもWebアプリケーション仕様に依存する問題であることから、脆弱性診断ツールへスキャンポリシーとして登録が必要です。 なぜなら、脆弱性診断ツールは、検出すべき脆弱性は理解していますが、Webアプリケーション固有の仕様を知る由もないからです。
この観点を探るというのが、1つ目のコツです。 特にゲームにおけるチートのようなケースでは、複数の仕様の問題を組み合わせる場合もあり 攻撃者特有の「ずる賢さ」が求められます。
診断手法の考案
診断の観点が定まったので、次は該当する脆弱性を確認すべき機能およびパラメータを選定します。 問題を確認するためには、診断観点に関連するパラメータに対してどういった文字列を送り、 その結果どういうレスポンスが得られれば問題として確認できるかを精査する必要があります。 これが、2つ目のコツです。
その際、入力値の選定や手法にはアプリケーションの仕様に対する理解を必要とするケースがあります。 具体的な例を2つほど見ていきましょう。
認可周りの脆弱性を確認するケース
ここでは、次のような仕様を持つ架空のWebアプリケーションを使って説明します。
アカウントAでは、以下のURLのみが閲覧可能。
* http://example.com/info/8
* http://example.com/info/16
アカウントBでは、以下のURLのみが閲覧可能。
* http://example.com/info/1024
* http://example.com/info/838861
このようなWebアプリケーションに対してアカウントAを使って「第三者(=アカウントB)の情報が閲覧可能」という問題を 検出するためには、以下の仕様を理解する必要があります。
- 現在、アカウントAでログインしている。
- アカウントAとは異なるアカウントBが存在している。
- アカウント毎に閲覧可能な情報が限られている。
- URLの末尾は連番であるが、欠番も多く存在する。
- 閲覧した情報がどのアカウントに紐付いている情報なのかを判断する手段がある。
こういった概念をスキャンポリシーに落とし込み、脆弱性診断ツールに対して仕様を教えてあげる必要があるわけです。
HTTPレスポンスに差異が発生しないケース
一般的な脆弱性診断ツールでは、各HTTPリクエストに対するHTTPレスポンス毎の差異や、 処理時間などで脆弱性を検出していることが多いことから、HTTPレスポンスに差異が発生しない場合には脆弱性として検出することが困難です。 そのため、脆弱性診断ツール自身が脆弱性を検出するためのカスタマイズが必要となるケースがあります。
例えば、アカウント登録処理に於いて、User ' || version() || '
という文字列にてアカウント名を登録したケースを考えてみましょう。
ブラウザ上のアカウント登録完了画面(HTTPレスポンス)では、以下の文言が表示されました。
登録メールアドレス宛に、アカウント登録完了メールを送信しました。
しかし、メーラーで受信した登録完了メール内に次のような本文が含まれていました。
登録アカウント名:User 5.X.XX
本来であればUser ' || version() || '
というアカウント名で登録されなければなりませんが、
何やらバージョンらしき文字列がアカント名に含まれています。
どうやら、アカウント登録処理に於いてSQLインジェクションの脆弱性がありそうです。
ここで、今回の一連のフローに対して脆弱性診断ツールで検査しても、SQLインジェクションの見落としに繋がる可能性が高いです。 なぜなら、メールサーバと連携していない限り、脆弱性診断ツール自身がアカウント登録完了メール本文(非HTTPレスポンス)を確認することが難しいためです。
今回のケースにおいてSQLインジェクションを検出するためには、次のような対策が挙げられます。
- HTTPレスポンス内(今回のケースでは、アカウント登録完了画面)に、暫定的に非HTTPレスポンス(今回のケースでは、アカウント登録完了メール本文)を含ませるようなカスタマイズを実施する。
- Time-based(時間差を利用した)のSQLインジェクションで検出する。
- アカウント登録処理がバックグラウンドで実行されている場合は、Time-basedでは検出が出来ないことを理解している必要がある。
最後に
脆弱性診断ツールの実力をより引き出すためには、コツがあることがおわかりいただけたかと思います。 これらのコツへの理解が、よりセキュアなサービスの構築の一助になれば幸いです。
また、そんな中、当社でマニュアル診断を基本としている大きな理由は、 たくさんのサービスを診断している中でも、サービスごとのきめ細かい仕様の差異を柔軟に取り入れるためには、 マニュアル診断が最も適切だと考えているからです。 そして、これが当社の強みであると自負しています:)