ソフトウェアに対する脆弱性の混入を防止するには、開発ライフサイクルの全体に渡って脆弱性検出のための仕組みを適切に取り入れることが不可欠です。本特集では、IPA セキュリティセンターの協力の下で、脆弱性検出手法のひとつである「ファジング」について、その特徴や効果、導入に向けた留意点、導入事例などを解説します。
前回はファジングの概要や業界動向を紹介しました。今回はそれに引き続き、ファジングの性質や期待できる効果、そしてファジングでは発見できない問題などを取り上げます。
ファジングの特徴
脆弱性の検出手法には、大きく分類すると"ホワイトボックステスト"と"ブラックボックステスト"、そして"グレーボックステスト"があります。ホワイトボックステストは、ソフトウェアやシステムの内部構造を把握した上で、ひとつひとつの機能が意図通りに動作するかをチェックする手法です。内部構造を把握した上での検証なので、細部にいたるまで網羅的にチェックできるというメリットがある一方で、大規模なソフトウェアでは検証に膨大な手間がかかることや、ソースコードが入手できないケースには適用できないといった問題があります。
ブラックボックステストは、ホワイトボックステストとは逆にソフトウェアの内部構造とは関係なく、外部から見た入出力だけに着目するテスト手法です。さまざまな入力に対して、仕様書通りの出力が得られるかどうかを確認することが目的で、システム内部でどういった処理が行われているかは一切考慮しないのが特徴です。
グレーボックステストはホワイトボックステストとブラックボックステストの中間的な位置付けの手法で、ソフトウェアやシステムの内部構造を把握した上で、ブラックボックスのように外部から見た仕様との整合性を検証するというものになります。内部構造を考慮することで適切なテストケースを選択することができるため、テストケースの数を減らせるというメリットがあります。
ファジングは、このブラックボックステストの一種に位置づけられるもので、システムの内部構造を知る必要がないというメリットがあります。また、リバースエンジニアリングなどによって得られる情報を利用することで、グレーボックステストとして実施されるケースも一部ではあります。
ファジングのもうひとつの大きな特徴は、大量のファズを使って総当たり的に検査を行うという点です。このような総当たり的な手法を「ブルートフォース」と呼びます。あらゆるパターンの入力を試すことが理想であるため、同じ手順の作業を少しずつ入力する値を変えながら何度も繰り返して実施することになります。そのため、ファジングはツールによって自動化して行うのが一般的です。
ファジングに期待できる効果
ファジングで使用するファズは、対象のソフトウェアの設計者や開発者の意図とは無関係に、半ば機械的に作成されます。そのため、設計者や開発者が想像していなかったような入力に対しても、どのような結果になるのかを確認することができます。ファジングをできるだけ多くのパターンのファズで何度も繰り返し行えば、入力データに起因するさまざまなバグや脆弱性などの問題を発見できる可能性が高くなり、結果としてソフトウェアの安全性を高める効果が期待できます。
ファジングの作業はツールを利用して自動化して行うのが一般的なので、他の業務を行いながら並行して実施できるというメリットもあります。ツールを活用すれば作業担当者の技術レベルに依存せずにファジングを実施できるという点も大きな強みです。また、ツールによっては複数の担当者で作業を分担して実施することも可能です。その他、似たような入力データを想定するソフトウェアであれば、ファズの流用や再利用も容易なため、テストの工数を削減することにもつながります。
ファジングでは発見できない問題
ほとんどの検査手法がそうであるように、ファジングも決して万能なものではありません。ファジングでは入力データに起因する多くの問題を検出することが期待できますが、逆に入力データに関係のない部分の問題については、どれだけ入念に行っても検出することはできません。検出できない問題の一例としては、必要な認証が存在しないなど、仕様や設計そのものに脆弱性が含まれるようなケースが挙げられます。アクセス制御の設定などに起因する問題なども検出できない可能性が高いものです。ファジングではソフトウェア内部のロジックや設定は考慮しないので、誰がどのデータにアクセスしていいのか/してはいけないのかを判断できないためです。
また、ファジングによって意図しない挙動が発見できたとしても、"なぜそのようになったのか"という原因までは知ることができません。原因を特定するにはソフトウェア内部のロジックを調べる必要があるからです。発見できた挙動が、実際に攻撃につながる問題なのかということも、ファジングだけでは一概に判断できません。中には脆弱性とは呼べないレベルの些細な問題もありますし、個々では特別な影響を与えない挙動でも複数を組み合わせることで攻撃に利用できるような類のものもあります。
導入する上での課題
このように、ファジングだけですべての問題を解決できるわけではないため、その他のさまざまなテスト手法と組み合わせながら、開発ライフサイクルの中の適切な場所で活用することが重要です。そして、問題を発見した場合には、原因を特定するために、問題を再現するファズを特定するフェイズが必要となることも覚えておかなければいけません。
それに加えて、ファジングの導入には、どの程度までテストすれば十分なのかが判断しづらいという課題もあります。問題を誘発させるには、ファズのパターンは多ければ多いに越したことはありません。しかし、無制限にパターンを増やしていったのでは検査時間が大幅に増加してしまいます。また、同じ入力に対して必ず問題が発生するとは限りません。何回かに1度だけ発生するような問題や、特定のタイミングでのみ発生するような問題も存在します。何回テストしたとしても"絶対に安全"と言い切ることはできないのです。ファジングを導入する上では、限られた時間の中で、どの程度のファズを何回テストしたら効果的に脆弱性を発見できるのか、そのポイントを探る必要があります。