ソフトウェア・インテグリティ

 

サイバー・セキュリティの実現方法:ファジング・ターゲットのコンテナ化

制御された環境でファジング・テストを用いて、再現可能で一貫性のあるテスト結果を実現します。

Defensicsを用いたコンテナのファジング | シノプシス

ファジングには危険が伴います。結局のところ、侵害行為を試みるのですから。

ファジングでは、ソフトウェアに意図的に不正なデータを入力し、ソフトウェアでエラーになるかどうかを確認します。エラーが発生した場合は、見つかった脆弱性をコードに戻って修正することができます。ファジングは、ソフトウェア開発においてセキュリティ上の弱点を修正するための優れた予防手段ではありますが、

同時に、ゼロデイ脆弱性を探している攻撃者が好んで用いる手法です。ファジングはソフトウェア障害を発生させることを意図しています。

ファジングのガイドライン

ファジングの標準的なガイドラインを次に示します。

  • 本番環境をファジングのターゲットにしない。ファジングによって、ターゲットにリソース使用量の増加などの軽度の不都合が生じる可能性があります。場合によっては重大な障害が発生することもあります。実際の業務に使用されているシステムをファジングのターゲットにすることはお勧めできません。
  • ファジング・ツールをターゲットの近くに配置する。ファジング・テストケースがターゲットに到達するまでの経路で中間システムを介さないようにするか、少なくとも中間システムの数を最小限に留めるように心がけましょう。中間システムでテストケースが変更または削除されたり、障害が発生する可能性があります。

ファジング・テストは必ず、制御され、分離された試験環境で実行することをお勧めします。ファジング・ツールは途中にシステムを介在させず、できればスイッチも使用したりせずに、ターゲットに直接接続するのが理想です。

試験環境は、テストが予期せずブロードキャスト、増幅、または中継された場合に備えて、ネットワークおよびインターネットの他の部分から切り離す必要があります。

仮想化の利点

仮想マシンは制御された環境でファジング・テストを行うための優れた方法です。仮想マシンでは、ホスト環境に影響する機能を設定によって限定し、仮想ネットワークを厳密に制御することができます。

場合によっては、ファジング・ツール(Defensics®など)とターゲット・ソフトウェアの両方を同じ仮想マシンに配置し、すべてのファジングを厳密に制限された環境内に維持することもできます。

代わりに、別の仮想マシンまたはホストシステムでファジング・ツールを使用して、独自の仮想マシン内にあるターゲットをテストすることもできます。

コンテナ化にはもう一つ利点があります。Linuxカーネル上で実行されるアプリケーション・ソフトウェアをテストする場合、コンテナ化すれば、わずかなリソース消費で仮想マシンを制御・分離することができます。

Dockerコンテナをファジングのターゲットとして使用する

コンテナ化によって環境を制御・分離する以外に、構成とセットアップを(Dockerfile内で)コードとして指定することで、テストと結果の再現性と一貫性を確保する方法もあります。

サンプル:mosquitto

たとえば、オープンソース・プロジェクトmosquitto(MQTTブローカー)をコンテナ内で実行するとします。以下では、さまざまな状況で、コンテナを使用してファジング・テストを実行する方法について説明します。

まず、アプリケーションのバイナリ成果物を取得して実行する単純な例をご紹介します。

mosquittoでは、apt-getコマンドを使用してインストールするだけで、この例をシミュレーションできます。これを実行するDockerfileを以下に示します。

FROM ubuntu
 
RUN apt-get update
RUN apt-get install -y mosquitto
 
ENTRYPOINT mosquitto

管理しやすいように単純なディレクトリ構造を用いています。筆者は、ファジング・ターゲットとしてコンテナを作成するときはいつも、次のファイルを使用します。

  • コンテナ・イメージを定義するDockerfile
  • 実際にDockerfileからイメージを作成するbuild.sh
  • イメージ名を定義するname.sh(build.shとrun.shの両方で使用)
  • コンテナ・イメージをインスタンス化し、ネットワークポートを公開するrun.sh

この簡単な例では、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でパワーアップ

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の紹介)」をご覧ください。

適切なものを適切な場所に

この記事がコンテナ内でファジング・ターゲットを実行する可能性を検討する参考になれば幸いです。この方法には以下の重要な利点があります。

  • 構成の一貫性
  • セットアップと破棄が容易
  • ネットワークトラフィックの分離
  • ビルドの一貫性

ファジングを始めましょう!

 

この著者によるその他の情報