制御された環境でファジング・テストを用いて、再現可能で一貫性のあるテスト結果を実現します。
ファジングには危険が伴います。結局のところ、侵害行為を試みるのですから。
ファジングでは、ソフトウェアに意図的に不正なデータを入力し、ソフトウェアでエラーになるかどうかを確認します。エラーが発生した場合は、見つかった脆弱性をコードに戻って修正することができます。ファジングは、ソフトウェア開発においてセキュリティ上の弱点を修正するための優れた予防手段ではありますが、
同時に、ゼロデイ脆弱性を探している攻撃者が好んで用いる手法です。ファジングはソフトウェア障害を発生させることを意図しています。
ファジングの標準的なガイドラインを次に示します。
ファジング・テストは必ず、制御され、分離された試験環境で実行することをお勧めします。ファジング・ツールは途中にシステムを介在させず、できればスイッチも使用したりせずに、ターゲットに直接接続するのが理想です。
試験環境は、テストが予期せずブロードキャスト、増幅、または中継された場合に備えて、ネットワークおよびインターネットの他の部分から切り離す必要があります。
仮想マシンは制御された環境でファジング・テストを行うための優れた方法です。仮想マシンでは、ホスト環境に影響する機能を設定によって限定し、仮想ネットワークを厳密に制御することができます。
場合によっては、ファジング・ツール(Defensics®など)とターゲット・ソフトウェアの両方を同じ仮想マシンに配置し、すべてのファジングを厳密に制限された環境内に維持することもできます。
代わりに、別の仮想マシンまたはホストシステムでファジング・ツールを使用して、独自の仮想マシン内にあるターゲットをテストすることもできます。
コンテナ化にはもう一つ利点があります。Linuxカーネル上で実行されるアプリケーション・ソフトウェアをテストする場合、コンテナ化すれば、わずかなリソース消費で仮想マシンを制御・分離することができます。
コンテナ化によって環境を制御・分離する以外に、構成とセットアップを(Dockerfile内で)コードとして指定することで、テストと結果の再現性と一貫性を確保する方法もあります。
たとえば、オープンソース・プロジェクトmosquitto(MQTTブローカー)をコンテナ内で実行するとします。以下では、さまざまな状況で、コンテナを使用してファジング・テストを実行する方法について説明します。
まず、アプリケーションのバイナリ成果物を取得して実行する単純な例をご紹介します。
mosquittoでは、apt-getコマンドを使用してインストールするだけで、この例をシミュレーションできます。これを実行するDockerfileを以下に示します。
FROM ubuntu RUN apt-get update RUN apt-get install -y mosquitto ENTRYPOINT mosquitto
管理しやすいように単純なディレクトリ構造を用いています。筆者は、ファジング・ターゲットとしてコンテナを作成するときはいつも、次のファイルを使用します。
この簡単な例では、name.shは次のように記述されています。
IMAGE=mosquitto-box
build.shスクリプトでは、name.shを呼び出してコンテナ・イメージを作成します。
source name.sh docker build -t ${IMAGE} -f Dockerfile .
最後に、run.shスクリプトでイメージのインスタンスを作成し、MQTTポート1883を公開します。
source name.sh docker run \ -it \ --rm \ -p 1883:1883 \ --hostname ${IMAGE} \ --name ${IMAGE} \ ${IMAGE}
このコードをコピーして貼り付ける必要はありません。この記事に掲載されているすべてのコードは次のWebサイトから入手できます。
https://github.com/jknudsen-synopsys/blog-box
前述した最初の単純な例はmbox01です。
この例を使用するには、build.shでイメージを作成し、run.shで実行します。コンテナ内でmosquittoを実行し、ポート1883で接続を待機します。先ほどポート1883を開いたので、Defensics(または他のMQTTテストツール)を実行し、localhostポート1883でmosquittoと通信することができます。
ファジング・テストを開発プロセスに組み込む場合、ソースからアプリケーションをビルドして、最新のコードをテストできるようにします。
コンテナをテストのターゲットにする利点の1つは、一貫性があることです。コンテナ・イメージの構成が適切に取得されれば、ビルドしたアプリケーションが想定どおりに動作し、再現性と一貫性のある結果を得ることが容易になります。
ここでも、サンプルアプリケーションとしてmosquittoを使用します。mosquittoのビルドの依存関係を持つコンテナ・イメージを準備し、gitリポジトリからソースコードを取得してビルドします。
最初の例では、mosquitto 1.6.9がインストールされました。ソースからビルドする場合、現行のバージョンは2.0.6です。セキュリティが高めに設定されているため、mosquittoが外部ネットワークで待ち受けて、確実に匿名接続が受け入れられるようにするためにDockerfileに変更を加える必要があります。
この記事のサンプルコード・リポジトリではmbox02です。Dockerfileは次のようになります。
FROM ubuntu RUN apt-get update RUN apt-get install -y build-essential git \ libssl-dev libc-ares-dev uuid-dev libcjson-dev RUN git clone https://github.com/eclipse/mosquitto.git && cd mosquitto && \ make WITH_DOCS=no RUN sed -i 's/#listener/listener 1883 0.0.0.0/g' /mosquitto/mosquitto.conf RUN sed -i 's/#allow_anonymous false/allow_anonymous true/g' /mosquitto/mosquitto.conf RUN useradd mosquitto ENTRYPOINT /mosquitto/src/mosquitto -c /mosquitto/mosquitto.conf
AddressSanitizerをDefensics Agent Instrumentation Frameworkと組み合わせてファジング・ターゲットのメモリリークを監視する方法については既にご紹介しました。
Dockerコンテナでこれを設定するには多少の追加作業が必要ですが、その労力をかける価値は十分にあります。サンプルコードではmbox03です。ただし、ファイル・ディレクトリにDefensics Agent Instrumentation Frameworkエージェント・サーバー(agent_linux_amd64)が配置されるまでは直ちに機能しません。このエージェント・サーバーが配置されていれば、通常の方法でbuild.shを実行することによってコンテナ・イメージにコピーされます。
Dockerfileはエージェント・サーバー上でコピーを処理し、AddressSanitizerを有効にしてmosquittoをコンパイルします。mosquittoを直接起動するのではなく、エージェント・サーバーを起動します。
FROM ubuntu RUN apt-get update RUN apt-get install -y build-essential git \ libssl-dev libc-ares-dev uuid-dev libcjson-dev RUN git clone https://github.com/eclipse/mosquitto.git && cd mosquitto && \ make CFLAGS=-fsanitize=address LDFLAGS=-fsanitize=address WITH_DOCS=no RUN sed -i 's/#listener/listener 1883 0.0.0.0/g' /mosquitto/mosquitto.conf RUN sed -i 's/#allow_anonymous false/allow_anonymous true/g' /mosquitto/mosquitto.conf RUN useradd mosquitto COPY files /files ENTRYPOINT /files/agent_linux_amd64 server –insecure
このコンテナを実行する場合は、エージェント・サーバーに到達できるようにポート12345も公開する必要があります。更新後のrun.shは次のとおりです。
source name.sh docker run \ -it \ --rm \ -p 1883:1883 \ -p 12345:12345 \ --hostname ${IMAGE} \ --name ${IMAGE} \ ${IMAGE}
コンテナが実行されたら、/mosquitto/src/mosquitto -c /mosquitto/mosquitto.confコマンドを使用して、mosquittoを実行するようにDefensics SanitizerProcessMonitorAgentを構成するだけです。
詳細については、ブログ記事「Find more bugs by detecting failure better: An introduction to SanitizerProcessMonitorAgent(障害検出の向上によるバグ発見の強化:SanitizerProcessMonitorAgentの紹介)」をご覧ください。
この記事がコンテナ内でファジング・ターゲットを実行する可能性を検討する参考になれば幸いです。この方法には以下の重要な利点があります。
ファジングを始めましょう!