ファジング

ファジングとは、コンピュータプログラムヘの入力として、無効なデータ、予期しないデータ、ランダムなデータを用いた自動化ないし半自動化されたソフトウェアテストの手法である。コンピュータプログラムにファズを与えることで、意図的に例外的な状況を発生させ、その例外的な状況での挙動を確認するという方法を用いる。ファズテストとも呼ばれる。また、ファジングの対象プログラムに対してファズテストを実行するツールは、ファザーと呼ばれる。

1. 概要
-----

ファジングは、コンピュータプログラムの検証プロセスの一環として、構造化された入力を受け取るプログラムをテストするために使用される。この構造化された入力とは、たとえばファイル形式やプロトコルで指定された有効な入力、あるいは無効な入力を指す。ファザーは、プログラムに対して有効な入力データを生成する。ファザーが生成する入力データ等を使用することで、通常のプログラムの操作や他のテスト方法では達成できない例外的な状況を発生させる可能性がある。 ファジングによって作り出された例外的な状況により、意図せぬクラッシュ、適切に処理されていないコーナーケースの発見、組み込みコードアサーションの失敗、潜在的なメモリリーク、実行時エラーの発見・分析などが可能となる。 ファジングの重要な要素として「自動化」が挙げられる。ソフトウェアテストは、従来、テスト実施者の経験と勘に頼って手作業で行われてきた。これに対して、ファジングは、テストケースの自動生成・実行と、自動化に伴う再現性の高さとコードカバレッジの広さで優れており、テスト実施者の経験と勘に依存しないソフトウェアテストとして発展してきた。ただし、ファジングにおいても依然としてテスト実施者の経験と勘に依存する要素はある。入力データの決定方法では半自動化を選択する場合もあるほか、ファイル形式のファジングなどの分野では手動ファジングが効果的な場合もある。 ファジングが有効な例としては、信頼境界線を越えた入力が挙げられる。一例として、ファジングを用いたコードの検証を行う際は、管理者権限ユーザーのみがアクセスできる構成ファイルを解析するコードよりも、任意のユーザーによるファイルのアップロードを処理するコードのほうが、有効な結果を得られる可能性が高い。 ファジングはソフトウェアまたはコンピュータシステムの不具合、特に脆弱性を発見するために一般的に使用され、ソフトウェアの未知の脆弱性と堅牢性の課題を明らかにするうえで最も重要な手法の一つである。 品質保証の分野でもファジングと同様の手法が使用されており、堅牢性テスト、構文テスト、または否定テストと呼ばれている。

2. ファジングの歴史
-----------

2.1. ファジングの前史
-------------

「ファジング」という用語が登場し、手順が確立される以前から、ランダムな入力の実行を用いたテスト手法が存在していた。たとえば、ジェラルド・ワインバーグは、コンピュータプログラムヘの入力として、ゴミ箱から引き出されたパンチカードや乱数のカードを使用し、それらの実行によって望ましくない動作を引き出し、バグの検出に用いていた。

1981年、DuranとNtafosは、ランダムな入力を使用してプログラムをテストすることの有効性を正式に調査した研究論文を発表している。それまでランダムな入力によるテストは、プログラムをテストするための「最悪の手段」であると広く認識されていたが、DuranとNtafosは、ランダムな入力によるテストが費用効果の高い代替手段であることを示した。 1983年、AppleのSteve Cappsは、Mac Paintなどの従来のMacOSアプリケーション用にランダムな入力を生成するツールTheMonkeyを開発した。名称の由来にあるMonkeyは、「無限の猿定理」で提示された「猿がタイプライターのキーボードでランダムにキーを無限に押せば最終的にシェイクスピア全集をタイプアウトする」という思考実験に由来する。 1991年、ランダムなプロセッサ命令のセットを実行することにより、UnixおよびUnixライクなオペレーティングシステムでプログラムの信頼性・堅牢性をテストするように設計されたアプリケーションcrashmeが公開された。 これらのテスト手法は、ランダムテストまたはモンキーテストとも呼ばれてきた。

2.2. 用語「ファジング」の登場
-----------------

原始的なファジングツールは、ウィスコンシン大学マディソン校のオペレーションシステムに関する講義において、教授バートン・ミラーと、ミラーが指導する大学院生Lars FredriksenおよびBryan Soによって1988年に開発され、1990年に研究論文として公開された。 これは、UNIXアプリケーションの脆弱性テストに作成したコマンドラインプログラムである。ランダムな入力およびコマンドラインパラメータを自動的に生成することを目的として、エラーで停止するまで他のプログラムにパラメータとして渡されるランダムデータを生成した。ランダムな非構造化データを使用した初めてのテストであるだけでなく、さまざまなオペレーティングシステムのさまざまなプログラムをテストし、テスト中に発生するエラーの種類を体系的に分析するための最初の専用アプリケーションでもあった。 このプロジェクトは、「オペレーティングシステムユーティリティ信頼性プログラム――ファジングジェネレータ」と名付けられた。このファジングという語は、英語の単語fuzzyに由来する。 ミラーらのプロジェクトは、テストしたUNIXユーティリティの25～33％をクラッシュさせることに成功した。また、各クラッシュをデバッグして原因を特定し、検出された各障害を分類した。加えて、他の研究者が他のソフトウェアでも同様の検証実験を行えるようにするために、ツールのソースコード、テスト手順、及び生の結果データが公開された。なお、1990年の研究論文では、ファジングの信頼性とセキュリティの関係性についても言及されている。 この時点ではまだ用いられているテスト内容は、たんに「クラッシュするか否か」「ハングするか否か」といったレベルのものであり、ファジングという用語も概念も登場する前のことであったが、これらのことを行なったバートン・ミラーは「ファジングの父」と呼ばれている。 ファザーを用いたテストは、1995年に再度実験が行われた。アプリケーションは、MacOSおよびWindows用のGUIアプリケーション、ネットワークプロトコル、およびシステムライブラリAPIテストを含むように拡張された。このときには様々なUNIXアプリケーションに対して脆弱性が発見されている。

2.3. ファジンツールの多様化
----------------

体系的なファジングツールは、オウル大学でのPROTOSプロジェクトによって開発された。PROTOSの開発は1999年に始まり、2002年には同プロジェクトのメンバーによって商用ファズツールの設計開発会社Codenom1iconが設立され、2005年には商用ファズツールがリリースされている。なお、PROTOSはオープンソースであるが2004年以降開発されていない。2005年にはファジング専門のメーリングリストが作成されるなど、セキュリティ研究家の中でも取り上げられる存在となった。 2002年、Dave Aitelによって作成されたオープンソースのファズツールフレームワークSPIKEおよびそれを使ったファズツールsharefuzzなどが登場した。これ以降、Webブラウザを対象としたファジング、ファイル形式を対象としたフジァング、ハードウェアファジング機器、ActiveXを対象としたファジングなど，特定分野における様々なファズツールが作られることとなった。 2012年4月、Goog1leは、Chromium Webブラウザのセキュリティが重要なコンポーネント用のクラウドベースのファジングインフラストラクチャであるClusterFuzzを発表した。セキュリティ研究者は、ClusterFuzzがアップロードされたファザーでクラッシュを検出した場合、独自のファザーをアップロードしてバグバウンティを収集できる。 2014年9月には、2014年シェルショック脆弱性の類似する脆弱性として開示されたセキュリティバグ広く使用でUNIXのbashシェル。Shellshockのほとんどの脆弱性は、後述するファジングツールAFLを使用して発見された。発見された脆弱性によりは、一部のWebサーバー展開など、多くのインターネット向けサービスはBashを使用して特定の要求を処理し、攻撃者が脆弱なバージョンのBashに任意のコマンドを実行させることを可能することで、攻撃者はコンピューター・システムヘの不正アクセスを取得することができた。 2015年4月、Hanno
Bockは、AFLが2014年のHeartbleedの脆弱性の発見手法を報告している。Heartbleedの脆弱性は2014年4月に公開された。これは、攻撃者が暗号化された通信を解読できる深刻な脆弱性であった。この脆弱性は、TLSを実装するOpenSSLに誤って導入され、インターネット上のサーバーの大部分で使用されていた。Shodanは2016年4月に238,000台、2017年1月に200,000台のマシンがまだ脆弱であると報告されている。 2016年8月、米国国防高等研究計画局は、キャプチャー・ザ・フラッグコンテストとしてサイバーグランドチャレンジを開催した。これは、ソフトウェアの欠陥をリアルタイムで発見悪用、修正できる自動防御システムを開発することを目的としたイベントであった。ファジングは、対戦相手のソフトウェアの欠陥を発見するための効果的な攻撃戦略として使用され、脆性弱検出の自動化に大きな可能性が示された。なお、優勝はデイビット・ブラムリーが率いるチームFor All Secureによって開発されたシステム「メイヘム」であった。 2016年9月、マイクロソフトは、ソフトウェアのセキュリティ上の重大なバグを検出するためのクラウドベースのファジングテストサービスであるProject Springfieldを発表した。2016年12月、GoogleはOSS-Fuzzを発表した。これにより、セキュリティが重要ないくつかのオープンソースプロジェクトを継続的にファジングできる。セキュリテイカンファレンスBlackHat2018で、Christopher Domasは、ファジングを使用してプロセッサ内の隠れたRISCコアの発見手法を提案した。このコアは、既存のセキュリティチェックをバイパスして、リング3からリング0コマンドを実行することができた。 2020年9月、MicrosoftによってOne Fuzzがリリースされた。これは、ソフトウェアのバグの検出を自動化し、自己ホスト型のサービスとしてのファジングプラットフォームであり、WindowsとLinuxをサポートしている。

3. ファジングの用途と限界
--------------

ファジングは主に、悪意を持って悪用される可能性のあるセキュリティクリテイカルなプログラムの脆弱性を明らかにするための自動化された手法として使用される。より一般的には、ファジングは、バグが存在しないことではなく、存在することを示すために使用される。バグを見つけずにファジングキャンペーンを数週間実行しても、プログラムが正しいことは証明とはならなく、プログラムはまだ実行されていない入力に対して失敗する可能性がある。すべての入力に対してプログラムを実行することは非常にコストがかかるが、プログラムがすべての入力に対して正しいことを証明することが目的である場合は、形式仕様が存在し、形式手法の手法を使用する必要がある。 以下、ファジングが特に効果を発揮している用途を挙げて解説する。

3.1. バグの発見
----------

バグの発見のために、ファザーは予期されたプログラムの動作と予期しないプログラムの動作を区別できなければならない。ただし、マシンは常にバグと機能を区別できるとは限らない。自動ソフトウェアテストでは、これはテストオラクル問題とも呼ばる。 通常、ファザーは、仕様がない場合にクラッシュする入力とクラッシュしない入力を区別し、単純で客観的な手段を使用する。クラッシュは簡単に特定でき、潜在的な脆弱性を示している可能性がある。ただし、クラッシュがないからといって、脆弱性がないことを示すものではない。たとえばCで記述されたプログラムは、入力によってバッファオーバーフローが発生した場合にクラッシュする場合とクラッシュしない場合がある。むしろ、プログラムの動作は未定義であることが多い。クラッシュ以外の障害に対してファザーをより敏感にするために、サニタイザーを使用して、障害が検出されたときにプログラムをクラッシュさせるアサーションを挿入できる。さまざまな種類のバグに対して、さまざまな解消方法がある。バッファオーバーフローやメモリ解放後の再使用(Address Sanitizerなどのメモリデバッガを使用）