コンテンツにスキップ

ビギナー

Mayhem での Docker ターゲットのテスト

docker

テスト対象は、Docker イメージとしてパッケージ化されたコンテナー アプリケーションですか? このレッスンでは、Docker イメージをコンパイルおよびアップロードし、Mayhem を使用して内部のコンテナー化されたアプリケーションをテストする手順を説明します。


学習時間の目安: 30 分

このレッスンを終了すると、以下のことができるようになります。

  1. 独自のローカル Docker イメージをビルドする。
  2. ローカルな Docker イメージを Docker Hub レジストリにプッシュする。
  3. アップロードされた Docker イメージに対して Mayhem UI から Mayhem ランを実行する。
  4. アップロードされた Docker イメージに対して Mayhem CLI から Mayhem ランを実行する。
  1. 独自のローカル Docker イメージをビルドする。
  2. ローカルな Docker イメージを Mayhem Docker レジストリにプッシュする。
  3. アップロードされた Docker イメージに対して Mayhem UI から Mayhem ランを実行する。
  4. アップロードされた Docker イメージに対して Mayhem CLI から Mayhem ランを実行する。

レッスンを駆け足で

始める前に前提条件を確認してください。

  1. Mayhem で Docker ターゲットをテストするには、次のステップを認識する必要があります。

    1. docker build コマンドを使用してローカルな Docker イメージをビルドします。
    2. Docker イメージをパブリックな Docker Hub レジストリにアップロードします (Docker Hub アカウントが必要です)。
    3. Mayhem UI または Mayhem CLI を使用して Mayhem ランを実行します。Mayhem API によって、Mayhem ランに必要な指定された Docker イメージが Docker Hub レジストリからプルされます。
    4. ランが実行され、結果が利用可能になります。
    1. docker build コマンドを使用してローカルな Docker イメージをビルドします。
    2. Docker イメージをパブリックな Docker Hub レジストリまたはプライベートな Mayhem Docker レジストリ (mayhem login を使用した認証が必要です) にアップロードします。
    3. Mayhem UI または Mayhem CLI を使用して Mayhem ランを実行します。Mayhem API によって、Mayhem ランに必要な指定された Docker イメージが指定されたレジストリからプルされます。
    4. ランが実行され、結果が利用可能になります。
  2. Download testme-docker をダウンロードしてファイルを展開し、docker build コマンドおよび次の Dockerfile を使用してtestme-docker イメージをビルドしてタグを付けます。

    1
    2
    3
    4
    5
    6
    7
    FROM debian:buster-slim as builder
    RUN apt-get update && \
        apt-get install -y gcc make libc6-dbg && \
        rm -rf /var/lib/apt/lists/*
    WORKDIR /mayhem
    COPY src testme
    RUN cd testme && make
    
  3. docker tag および docker push コマンドを使用して、testme-docker イメージのタグを変更して Mayhem Docker レジストリにプッシュします。

    docker tag testme-docker <DOCKERHUB_USERNAME>/testme-docker
    docker push <DOCKERHUB_USERNAME>/forallsecure/testme-docker
    
    docker tag testme-docker $MAYHEM_DOCKER_REGISTRY/forallsecure/testme-docker
    docker push $MAYHEM_DOCKER_REGISTRY/forallsecure/testme-docker
    
  4. Mayhem UI or Mayhem CLI で次の Mayhemfile を指定して、testme-docker イメージに対して Mayhem ランを実行します。

    1
    2
    3
    4
    5
    6
    image: $MAYHEM_DOCKER_REGISTRY/forallsecure/testme-docker:latest
    duration: 90
    project: forallsecure-testme-docker
    target: testme
    cmds:
      - cmd: /mayhem/testme/v1/testme @@
    
    1
    2
    3
    4
    5
    6
    image: $MAYHEM_DOCKER_REGISTRY/forallsecure/testme-docker:latest
    duration: 90
    project: forallsecure-testme-docker
    target: testme
    cmds:
      - cmd: /mayhem/testme/v1/testme @@
    

以下が必要です。

  • Docker がインストールされていること
  • Mayhem CLI がインストールされていること
  • Linux または MacOS オペレーティング システム (Mayhem CLI から Docker イメージをテストする場合)
  • Docker がインストールされていること
  • Mayhem CLI がインストールされ、プライベートな Mayhem Docker レジストリで認証されていること
  • Linux または MacOS オペレーティング システム (Mayhem CLI から Docker イメージをテストする場合)

ターミナル記録

Mayhem Docker ターゲットのワークフロー

次の図を見て、Mayhem で Docker ターゲットをテストするために必要な手順を最初から最後まで感覚的につかみましょう。

docker-run-diagram-dockerhub

docker-run-diagram

特に、次のステップに注意する必要があります。

  1. docker build コマンドを使用してローカルな Docker イメージをビルドします。
  2. Docker イメージをパブリックな Docker Hub にアップロードします。
  3. Mayhem UI または Mayhem CLI を使用して Mayhem ランを実行します。Mayhem API によって、Mayhem ランに必要な指定された Docker イメージが Docker Hub レジストリからプルされます。
  4. ランが実行され、結果が利用可能になります。
  1. docker build コマンドを使用してローカルな Docker イメージをビルドします。
  2. Docker イメージをパブリックな Docker Hub レジストリまたはプライベートな Mayhem Docker レジストリ (mayhem login を使用した認証が必要です) にアップロードします。
  3. Mayhem UI または Mayhem CLI を使用して Mayhem ランを実行します。Mayhem API によって、Mayhem ランに必要な指定された Docker イメージが指定されたレジストリからプルされます。
  4. ランが実行され、結果が利用可能になります。

最初のステップであるローカルな Docker イメージの構築から始めましょう。

Docker イメージをビルドしてプッシュする

Docker を使用すると、ターゲット バイナリを含む独自のイメージを簡単にビルドできます。それには、Dockerfile を指定して docker build コマンドを実行するだけです。

始めるための準備として、次のファイルをダウンロードして展開します: testme-docker

展開されたファイルは次のようになります。

├── testme-docker
    └── Dockerfile: 実行される Docker build コマンドを定義する
    └── Makefile: 実行されるビルド タスクを定義する
    └── src: testme アプリケーションのソース ファイルを含むフォルダー

Dockerfile は、基になる Docker コンテナーから Docker イメージを作成するための命令をテキストベースで記述したスクリプトです。Dockerfile では、ユーザーのニーズに合わせて Docker を作成および修正するためのオプションを使用できます。準備ができたら、Dockerfile を指定して docker build コマンドを実行し、Dockerfile の命令に従って Docker コンテナー イメージをビルドしてタグを付加します。

testme-docker ディレクトリに移動して Dockerfile を開きます。

1
2
3
4
5
6
7
FROM debian:buster-slim as builder
RUN apt-get update && \
    apt-get install -y gcc make libc6-dbg && \
    rm -rf /var/lib/apt/lists/*
WORKDIR /mayhem
COPY src testme
RUN cd testme && make

Dockerfile で次のコマンドが使用されているのがわかります。

  • FROM: 新規ビルド ステージを初期化し、その後の命令で使用するベース イメージを設定します。有効な Dockerfile は必ず FROM 命令で始まります。
  • RUN: 現在のイメージに重ねられた新しいレイヤーでコマンドを実行し、結果をコミットします。結果としてコミットされたイメージが Dockerfile の次のステップで使用されます。
  • WORKDIR: Dockerfile 内で後に続く RUNCMDENTRYPOINTCOPYADD 命令の作業ディレクトリを設定します。
  • COPY: 新規ファイルまたはディレクトリを からコピーし、コンテナーのファイルシステムのパス に追加します。

次のコマンドを実行すると、Dockerfile を使用して Docker イメージをビルドします。

docker build -f Dockerfile -t testme-docker .
  • docker build は、Dockerfile から Docker イメージをビルドするのに使用されます。
  • -f パラメーターは、Dockerfile の名前を指定します (デフォルト値は PATH/Dockerfile)。
  • -t パラメーターは、ビルドされた Docker イメージに人間が読みやすい名前をタグ付けします。
  • . は、ビルドおよび (tar によって) パッケージ化されて Docker デーモンに送られるローカル ディレクトリのすべてのファイルの「コンテキスト」への PATH を指定します。

Info

Dockerfile の設定と Docker イメージのビルドの詳細については「Dockerfile Reference」および「docker build examples」を参照してください。

今回使用する testme-docker サンプルでは、Dockerfiledebian:buster-slim ベース イメージを設定し、apt-get コマンドを使用して gccmake などの必要なビルド ツールをダウンロードします。その後、作業ディレクトリとして /mayhem を設定し、src ローカル フォルダーの内容を testme フォルダーにコピーし、testme フォルダーに移動してフォルダー内の Makefile に対して make コマンドを実行します。Docker コンテナーがビルドされ、Docker イメージに testme-docker という名前がタグ付けされます。

docker buildが成功すると、次のように出力されます。

docker-build-successful

testme-docker イメージが正常にビルドされたことを確認するには、docker images コマンドを実行して出力を grep testme-docker にパイプし、testme-docker に一致するものを検索して出力します。

$ docker images | grep testme-docker
testme-docker      latest        118f9b5b7874        5 minutes ago       201MB

おめでとうございます! 初めてのローカル Docker イメージを一から作成できました。

無事に Docker イメージをビルドできたので、今度は Docker Hub にイメージをアップロードして、Mayhem がイメージを取り込んでコンテナー化された testme アプリケーションをファジングできるようにします。

無事に Docker イメージをビルドできたので、今度は Mayhem にイメージをアップロードして、Mayhem がイメージを取り込んでコンテナー化された testme アプリケーションをファジングできるようにします。それには、ローカルにある Docker イメージをプライベートな Docker レジストリにプッシュします。すべての Mayhem デプロイメントはプライベートな Docker レジストリを備えています。

ただし、その前に Mayhem CLI から mayhem login コマンドを実行する必要があります。このコマンドは次の 2 つの処理を行います。

  1. Mayhem サーバーでユーザー認証情報を認証します。
  2. Mayhem Docker レジストリにログインします。
$ mayhem login <MAYHEM_HOST_URL> <USER_API_KEY>
Logged in successfully at '<MAYHEM_HOST_URL>:443' as '<USER>'.
Syncing default settings: /Users/andrew/.config/mayhem/mayhem.
Logging into the Docker registry at <MAYHEM_HOST_URL>:5000
Successfully logged in to the remote Docker registry.

そのため、mayhem login コマンドを使用して Mayhem サーバーにログインします。Mayhem Docker レジストリへのログインが成功したら、docker tag および docker push コマンドを続けて実行し、Mayhem Docker レジストリ向けにローカルな Docker イメージのタグを付けなおし、結果のイメージをレジストリにアップロードできます。

Docker イメージをパブリックな Docker Hub レジストリにアップロードするための docker tag および docker push コマンドの形式は次のとおりです。

Docker イメージをプライベートな Docker レジストリにアップロードするための docker tag および docker push コマンドの形式は次のとおりです。

docker tag <DOCKER_IMAGE> <DOCKERHUB_USERNAME>/<DOCKER_IMAGE>
docker push <DOCKERHUB_USERNAME>/<DOCKER_IMAGE>
docker tag <DOCKER_IMAGE> <REGISTRY_HOST>/<DOCKER_REPO>/<DOCKER_IMAGE>
docker push <REGISTRY_HOST>/<DOCKER_REPO>/<DOCKER_IMAGE>

警告

このサンプルでは、Mayhem デプロイメントは tutorial.forallsecure.com にあり、Mayhem Docker レジストリはポート 5000 にあります。ただし、お使いの Mayhem デプロイメントおよびプライベートな Docker レジストリの場所は異なる可能性があります。 Docker イメージを正常にプッシュするには、mayhem login または mayhem docker-registry コマンドを使用して Mayhem サーバーにログインし、 プライベートな Docker レジストリの場所を確認してください。

したがって、次のコマンドを実行すると、ローカルな testme-docker イメージのタグが付けかえられ、新しくタグ付けされた testme-docker イメージがパブリックな Docker Hub レジストリにプッシュされます。

したがって、次のコマンドを実行すると、ローカルな testme-docker イメージのタグが付けかえられ、新しくタグ付けされた forallsecure/testme-docker イメージが tutorial.forallsecure.com:5000 にあるプライベートな Mayhem Docker レジストリにプッシュされます。

重要

次のサンプルでは、andrew5194 Docker Hub リポジトリが使用されています。ユーザーはそれぞれの Docker Hub アカウント/リポジトリ名を使用してローカルな testme-docker イメージにタグを付ける必要があります。

docker tag testme-docker docker.io/<DOCKERHUB_USERNAME>/testme-docker
docker push docker.io/<DOCKERHUB_USERNAME>/testme-docker
docker tag testme-docker tutorial.forallsecure.com:5000/forallsecure/testme-docker
docker push tutorial.forallsecure.com:5000/forallsecure/testme-docker

ローカルな Docker イメージが Docker Hub レジストリに正常にアップロードされたことを確認するには、Docker Hub に移動して <DOCKERHUB_USERNAME>/testme-docker イメージを検索します。

ローカルな Docker イメージがプライベートな Mayhem Docker レジストリに正常にアップロードされたことを確認するには、Mayhem UI の Mayhem Docker レジストリ ページに移動して forallsecure/testme-docker イメージを検索します。

dockerhub-upload

docker-upload

注意

Mayhem Docker レジストリページの右上隅にある情報アイコン icon を使用してプライベートな Docker レジストリの場所を確認し、表示される docker tag および docker push コマンドをブックマークすることもできます。

Mayhem UI から Docker イメージをテストする

Docker イメージをパブリックな Docker Hub レジストリにアップロードしたので、あとは 、前のレッスンで実行したように、Mayhem UI から新規 Mayhem ランの作成を実行するだけです。

Docker イメージを Mayhem Docker レジストリにアップロードしたので、あとは 、前のレッスンで実行したように、Mayhem UI から新規 Mayhem ランの作成を実行するだけです。

ソースとして Docker Hub レジストリを選択し、先ほどアップロードした <DOCKERHUB_USERNAME>/testme-docker イメージを検索します。新規 Mayhem ランを開始し、関連する Mayhemfile をプレビューして、内容が次のようになっていることを確認します。

ソースとして Mayhem Docker レジストリを選択し、先ほどアップロードした forallsecure/testme-docker イメージを検索します。新規 Mayhem ランを開始し、関連する Mayhemfile をプレビューして、内容が次のようになっていることを確認します。

1
2
3
4
5
6
image: index.docker.io/<DOCKERHUB_USERNAME>/testme-docker:latest
duration: 90
project: forallsecure-testme-docker
target: testme
cmds:
  - cmd: /mayhem/testme/v1/testme @@
1
2
3
4
5
6
image: $MAYHEM_DOCKER_REGISTRY/forallsecure/testme-docker:latest
duration: 90
project: forallsecure-testme-docker
target: testme
cmds:
  - cmd: /mayhem/testme/v1/testme @@

最後に、オプションの選択を確認し、新規ランの作成フローの最後で [Start Run] ボタンをクリックしてローカルな Docker イメージに対する Mayhem ランを実行します。

docker-mayhem-run

よくできました! ローカルな Docker イメージを一からビルドし、パブリックな Docker Hub レジストリにアップロードし、コンテナー化されたターゲットをファジングして不適切な入力検証の欠陥を検出できました。

よくできました! ローカルな Docker イメージを一からビルドし、Mayhem Docker レジストリにアップロードし、コンテナー化されたターゲットをファジングして不適切な入力検証の欠陥を検出できました。

Mayhem CLI から Docker イメージをテストする

UI ではなく Mayhem CLI を使用したい場合、Mayhemfile を作成し、次のように Docker Hub レジストリにある <DOCKERHUB_USERNAME>/testme-docker イメージを指すよう image を変更することもできます。

1
2
3
4
5
6
image: <DOCKERHUB_USERNAME>/testme-docker:latest
duration: 90
project: forallsecure-testme-docker
target: testme
cmds:
  - cmd: /mayhem/testme/v1/testme @@

情報

mayhem login コマンドを使用してユーザー認証情報が正常に Mayhem サーバーで認証され、プライベートな Mayhem Docker レジストリにログインすると、 $MAYHEM_DOCKER_REGISTRY 環境変数が設定されます。

その後、新しく作成した Mayhemfile と同じディレクトリで mayhem run を実行します。

$ mayhem run .
Run started: forallsecure-testme-docker/testme/2
Run URL: https://tutorial.forallsecure.com:443/mayhemuser/forallsecure-testme-docker/testme/2

現実的な演習: testme-npd のビルドとテスト

セグメンテーション違反はメモリ エラーの一種であり、不正なメモリ位置への読み取りまたは書き込みを行おうとしたときに発生します。一例として、値が NULL であるポインターを有効なメモリ領域を指すポインターと同様に使用するという null ポインター間接参照があります。

int *p = NULL;
int y = *p;

この null ポインター間接参照を既存の testme アプリケーションに追加して再ビルドし、Mayhem を使用して変更後の testme-npd アプリケーションをファジングし、新たに追加されたバグを検出できるかどうか試してみましょう。

手順

  1. 次をダウンロードして展開します: testme-docker.zip

  2. テスト ケースがアプリケーションに null を入力した場合に null null ポインター間接参照のバグを引き起こす if-else 文を testme.c ファイルに追加します。

  3. docker build コマンドを使用して Dockerfile を再ビルドし、結果の Docker イメージに testme-npd というタグを付けます。

  4. docker tag および docker push コマンドを使用して testme-npd Docker イメージを内部的な Mayhem Docker レジストリにプッシュします。

  5. Mayhem UI または Mayhem CLI を使用して testme-npd Docker イメージをファジングします。追加の欠陥を検出するのに必要な時間の増加に対応するため、Mayhemfileduration120 秒を指定するのを忘れないでください。 testme-npd バイナリで 2 つの欠陥を発見できるはずです。

  1. 次をダウンロードして展開します: testme-docker.zip

  2. テスト ケースがアプリケーションに null を入力した場合に null null ポインター間接参照のバグを引き起こす if-else 文を testme.c ファイルに追加します。

  3. docker build コマンドを使用して Dockerfile を再ビルドし、結果の Docker イメージに testme-npd というタグを付けます。

  4. docker tag および docker push コマンドを使用して testme-npd Docker イメージを内部的な Mayhem Docker レジストリにプッシュします。

  5. Mayhem UI または Mayhem CLI を使用して testme-npd Docker イメージをファジングします。追加の欠陥を検出するのに必要な時間の増加に対応するため、Mayhemfileduration120 秒を指定するのを忘れないでください。 testme-npd バイナリで 2 つの欠陥を発見できるはずです。

🔍 確認 testme-npd のビルドとテスト

解答

修正済みファイル: testme-npd.zip

まず、testme 関数に null ポインター間接参照を行うコード スニペットを追加します。testme アプリケーションをファジングすると、入力テスト ケースが "null" だった場合に null ポインター間接参照のエラーを引き起こします。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int testme(char *buf, unsigned len)
{
  unsigned ok;

  if(!ok) // Defect: uninitialized use of ok.
    ok = len;

  if(buf[0] == 'b')
    if(buf[1] == 'u')
      if(buf[2] == 'g') {
        return abort(); // Defect: SIGABRT.
      }

  if(buf[0] == 'n')
    if(buf[1] == 'u')
      if(buf[2] == 'l')
        if(buf[3] == 'l') {
          int *p = NULL; // Defect: null pointer dereference
          int y = *p;
        }

  return 0;
}

次に、Dockerfile と同じディレクトリで Dockerfile コマンドを実行して、結果の Docker イメージを testme-npd としてタグ付けします。

docker build -f Dockerfile -t testme-npd .

次に、testme-npd Docker イメージを内部的な Mayhem Docker レジストリにプッシュします。

docker tag testme-npd tutorial.forallsecure.com:5000/forallsecure/testme-npd
docker push tutorial.forallsecure.com:5000/forallsecure/testme-npd

この例では、tutorial.forallsecure.com Mayhem デプロイメント、具体的にはポート 5000 の内部的な Docker レジストリに testme-npd Docker イメージをアップロードしました。Docker イメージを正常にアップロードするには、お使いの Mayhem デプロイメントの Docker レジストリに合わせて URL を修正する必要があります。

最後に、Mayhemfile が次のようになっていれば、Mayhem UI または Mayhem CLI を使用して、アップロードされた testme-npd Docker イメージに対して Mayhem ランを実行できたはずです。

image: $MAYHEM_DOCKER_REGISTRY/forallsecure/testme-npd:latest
duration: 120
project: forallsecure-testme-npd
target: testme-npd
cmds:
  - cmd: /mayhem/testme/v1/testme @@

最新のラン ページは次のように表示されるはずです。

testme-npd-run-page

おめでとうございます! Mayhem は不適切な入力検証の欠陥とともに、追加した null ポインター間接参照の欠陥も発見しました。Docker イメージを一からビルドし、脆弱性を追加して、Mayhem で検出できました。

✏️ まとめと振り返り

このレッスンでは、Docker イメージをビルドして Docker Hub にプッシュし、ファジングを行う方法を学びました。

このレッスンでは、Docker イメージをビルドして Mayhem のプライベートな Docker レジストリにプッシュし、ファジングを行う方法を学びました。

Docker イメージは Dockerfiles および docker build コマンドを使用してビルドできます。Docker イメージをビルドしたら、デプロイ済みの Mayhen インスタンスにある Docker レジストリにプッシュできます。Docker イメージを Mayhem に取り込みできるようになったら、Mayhem UI または Mayhem CLI を使用して Docker イメージに対してランを実行できます。


学習内容

1. ローカルな Docker イメージをビルドする
  • Docker を使用すると、ターゲット バイナリを含む独自のイメージを簡単にビルドできます。それには、Dockerfile を指定して docker build コマンドを実行するだけです。

    1
    2
    3
    4
    5
    6
    7
    FROM debian:buster-slim as builder
    RUN apt-get update && \
        apt-get install -y gcc make libc6-dbg && \
        rm -rf /var/lib/apt/lists/*
    WORKDIR /mayhem
    COPY src testme
    RUN cd testme && make
    
  • Dockerfile で次のコマンドが使用されているのがわかります。

    • FROM: 新規ビルド ステージを初期化し、その後の命令で使用するベース イメージを設定します。有効な Dockerfile は必ず FROM 命令で始まります。
    • RUN: 現在のイメージに重ねられた新しいレイヤーでコマンドを実行し、結果をコミットします。結果としてコミットされたイメージが Dockerfile の次のステップで使用されます。
    • WORKDIR: Dockerfile 内で後に続く RUNCMDENTRYPOINTCOPYADD 命令の作業ディレクトリを設定します。
    • COPY: 新規ファイルまたはディレクトリを からコピーし、コンテナーのファイルシステムのパス に追加します。
2. Docker イメージを Docker レジストリにプッシュする
  • ビルドした Docker イメージをパブリックな Docker Hub レジストリにプッシュできます。
  • Docker イメージが正常に Docker Hub にプッシュされたことを確認するには、Docker Hub の Web サイトに移動し、イメージ名を検索します。
  • ビルドした Docker イメージを Mayhem の内部的な Docker レジストリにプッシュできます。内部的な Docker レジストリは、すべての Mayhem デプロイメントに含まれています。
  • まず mayhem login コマンドを使用して Mayhem Docker レジストリにログインしてから、docker tag および docker push コマンドを使用して Docker イメージにタグを付け、プライベートな Mayhem Docker レジストリに アップロードします。
  • Docker イメージが正常に Mayhem Docker レジストリにプッシュされたことを確認するには、Mayhem UI 内の Mayhem Docker レジストリに移動します。
3. Mayhem UI から Docker イメージに対して Mayhem ランを実行する
  • Docker イメージが正常に Mayhem の内部的な Docker レジストリにアップロードされたら、Mayhem UI で新規ランの作成フローを使用して、アップロード済みの Docker イメージをファジングできます。
4. Mayhem CLI から Docker イメージに対して Mayhem ランを実行する
  • Docker イメージが正常に Mayhem の内部的な Docker レジストリにアップロードされたら、Mayhemfile を構成し、image パラメーターがアップロード済みの Docker イメージを指すよう設定します。その後、Mayhem CLI から mayhem run コマンドを実行してアップロード済みの Docker イメージをファジングできます。