コンテンツにスキップ

ビギナー

ブラウザーでのコード テスト

準備完了! このレッスンでは、Mayhem UI から初めての Mayhem ランを実行する手順を説明します。


学習時間の目安: 15 分

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

  1. Mayhem UI から Docker イメージ (testme ターゲットを含む) に対して Mayhem ランを実行する。
  2. クラッシュを起こすテスト ケースを使用して欠陥を再現する。
  3. 修正/アップデートされた testme ターゲットに対してリグレッション テストを実行する。
  4. Mayhem UI から一般的な lighttpd Web サーバーに対して Mayhem ランを実行する。

レッスンを駆け足で

  1. Mayhem UI を使用して、Docker イメージ内のコンテナー化されたアプリケーションをファジングするには、以下の手順に従います。

    1. Mayhem デプロイメントにホストされた Mayhem UI にログインします。
    2. 新規 Mayhem ランの対象とする Docker イメージを選択します。
    3. ランの Mayhemfile を構成します。
    4. 新規 Mayhem ランを実行します。
  2. Mayhem UI から forallsecure/tutorial Docker イメージ内の testme ターゲットに対する Mayhem ランを作成し、次のように Mayhemfile を構成します。

    1
    2
    3
    4
    5
    6
    image: forallsecure/tutorial:latest
    duration: 90
    project: forallsecure-tutorial
    target: testme
    cmds:
      - cmd: /root/tutorial/testme/v1/testme @@
    
  3. Mayhem UI から $MAYHEM_DOCKER_REGISTRY/forallsecure/tutorial Docker イメージ内の更新された testme ターゲットに対して次の Mayhemfile 構成 (リグレッションテストのみ) を使用して別の Mayhem ランを実行します。

    1
    2
    3
    4
    5
    6
    7
    8
    image: $MAYHEM_DOCKER_REGISTRY/forallsecure/tutorial:latest
    duration: 90
    project: forallsecure-tutorial
    target: testme
    tasks:
      - name: regression_testing
    cmds:
      - cmd: /root/tutorial/testme/v2/testme @@
    

Docker イメージから新規 Mayhem ランを作成する

直感的に操作できる Web インターフェイスとして提供されている Mayhem UI を使用して、アプリケーション (ターゲット) の Mayhem セキュリティ テストを作成、管理、解析できます。Mayhem UI から Mayhem ランを開始し、パブリックな Docker Hub レジストリにアップロードされた Docker イメージ内のコンテナー化されたアプリケーションをテストできます。

直感的に操作できる Web インターフェイスとして提供されている Mayhem UI を使用して、アプリケーション (ターゲット) の Mayhem セキュリティ テストを作成、管理、解析できます。Mayhem UI から Mayhem ランを開始し、Mayhem の内部的な Docker レジストリにアップロードされた、またはパブリックな Docker Hub レジストリにホストされた Docker イメージ内のコンテナー化されたアプリケーションをテストできます。

方法は、次のようにとても簡単です。

  1. ご利用の Mayhem デプロイメントにホストされた Mayhem UI にログインします。
  2. 新規 Mayhem ランを作成する Docker イメージを選択します。
  3. ランのオプションを構成します。
  4. 新規 Mayhem ランを実行します。

仕組みをより詳しく見てみましょう。すぐに始められるよう、Docker Hub にホストされた Docker イメージを使用して事前構成済みの新規ランを作成するボタンが用意されています。この演習では、すでに取り上げた testme アプリケーションに対して Mayhem ランを実行します。

仕組みをより詳しく見てみましょう。すぐに始められるよう、Mayhem の Docker レジストリにホストされた Docker イメージを使用して事前構成済みの新規ランを作成するボタンが用意されています。この演習では、すでに取り上げた testme アプリケーションに対して Mayhem ランを実行します。

ボタンをクリックすると、次の画面が表示されます。

create-new-run-flow-dockerhub

create-new-run-flow

この画面で、新規コード テスト プロジェクトを作成し、新規 Mayhem ランを実行できます。新規 Mayhem ランを実行する手順には、大きくわけて次の 2 つのステップがあります。

  1. イメージの選択: Mayhem がコンテナー化されたターゲット アプリケーションのセキュリティ テストに使用する Docker イメージを指定します。パブリックな Docker Hub レジストリにあるイメージを選択します。

  2. 構成と実行: Mayhem ランのオプションを構成し、選択内容を確認してランを実行します。

  1. イメージの選択: Mayhem がコンテナー化されたターゲット アプリケーションのセキュリティ テストに使用する Docker イメージを指定します。プライベートな Mayhem Docker レジストリまたはパブリックな Docker Hub レジストリにあるイメージを選択します。

  2. 構成と実行: Mayhem ランのオプションを構成し、選択内容を確認してランを実行します。

基になる Mayhemfile で Mayhem ランがどのように指定されているかをより詳しく見るには、画面下部の [Show Mayhemfile] リンクをクリックします。次のような記述が表示されます。

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

Info

$MAYHEM_DOCKER_REGISTRY 変数は、ローカルな Mayhem Docker レジストリ (例: tutorial.forallsecure.com:5000) を表すのに使用されます。いっぽう、パブリックな Docker イメージの場合、URL は不要で、Docker Hub から直接プルされます。Mayhemfile の各構成オプションに関する完全なリファレンスについては「Mayhemfile Specification」ドキュメントを参照してください。

選択を確定したら、[Create project and run] をクリックして初めての Mayhem ランを実行します。Mayhem ランを実行すると、次のようにラン解析ページが表示されます。

first-run-docker

ラン解析ページには Mayhem ランの進捗が表示され、ランの実行期間が終了するまで自動更新され続けます。このとき、Mayhem はターゲット アプリケーションをテストし、潜在的なセキュリティ脆弱性を検出できるよう、できるだけ多くのテスト ケースを生成します。クラッシュや欠陥を発生させたテスト ケースは今後の参照のためにマークされます。

ラン解析ページの下部にスクロールすると、コンテナー化された testme ターゲットをテスト中に Mayhem が発見した欠陥の詳細情報や、さらにはテストで使用された個々のテスト ケースも表示されます。

この testme ターゲットには、潜在的な不適切な入力検証の欠陥があるようです。

Warning

ユーザーが実行した特定の Mayhem ランで生成されるテスト ケースのハッシュ/ID は、このチュートリアルに表示されているものとは異なる可能性があることに注意してください。

testme-defects

また、[Defects] から [Test Cases] にビューを切り替えると、Mayhem ランで生成された個々のテスト ケースが表示されます。このランでは、Mayhem は 2 つのテスト ケースを生成し、特定の欠陥を発生させました。

test-case-pane

よくできました。testme ターゲット バイナリに対して初めての Mayhem ランを実行し、欠陥を発見しました。

発見された欠陥が本物であることを確認するために、Mayhem が生成して保存したテスト ケースを使用して手動で testme バイナリを実行し、testme バイナリの欠陥が疑われる動作を再現することができます。そのために、ユーザーはテスト ケースをダウンロードできます。

生成済みのテスト ケースを使用して欠陥を再現する

クラッシュしたテスト ケースのうち 1 つの欠陥 ID (TDID-474151: Improper Input Validation) をクリックします。すると、選択した欠陥につながった生成済みテスト ケースを示す画面が表示されます。

test-case-analysis

また、記録された動作を再現するために、該当入力テスト ケースを使用して testme バイナリを再実行するのに必要なコマンドも表示されます。

./root/tutorial/testme/v1/testme <TESTCASE_ID>

そのため、testme バイナリと共にクラッシュを起こすテスト ケースをダウンロードして展開し、欠陥を再現するコマンドを実行すると、次のように表示されます。

~/tutorial/testme/v1# ./testme 318d86b978cf3774c6d38c5265b0daf19ab17dc49b25ebea42de273e64d4a05c
Aborted

Info

ダウンロード用に testme バイナリが提供されますが、これを実行するには Linux OS が必要です。Docker がインストールされていれば、Docker コンテナー自体の中でコンテナー化された testme ターゲットをテストできます。これを行う方法については、次のレッスン CLI テスト で説明します。

エラーが見つかりました。該当入力テスト ケースで欠陥が再現されたのがわかります。今度は、対象コードを修正し、testme バイナリを再コンパイルしてもう 1 度 Meyhem ランを実行し、欠陥 (および関連するテスト ケース) が修正されたことを確認しましょう。

リグレッション テストを実行して修正を確認する

Mayhem がターゲット アプリケーションのテストでテスト ケースを生成する際、その後に同じターゲットで Mayhem ランを実行する場合に備えてテスト ケースを保存します。こうすることで、Mayhem ランは以前に生成されたテスト ケースを活用して、ターゲット アプリケーションの現在の動作が変わったか (以前は成功したテスト ケースがクラッシュするようになったり、以前はクラッシュしたテスト ケースが成功するようになったりしたか) を確認できます。これをリグレッション テストと呼びます。

Info

Mayhem は、特定のオーナーの特定の <project>/<target> でその後 Mayhem ランを実行した場合、同じテスト スイートを再利用します。今回の例では、チュートリアルを実行している Mayhem ユーザー アカウントが所有する forallsecure-tutorial/testme のランでは、生成されたテスト スイートが再利用されます。

実際にどのように動作するか見てみましょう。先ほど testme アプリケーションをファジングし、不適切な入力検証の欠陥が見つかったことを思い出してください。

  1. CWE-20: 不適切な入力検証の欠陥

今度は基になっている欠陥を修正し、以前に生成されたテスト ケースを使用してターゲットをファジングするリグレッション テストを実行して、発見された欠陥が修正されたことを確認します。

修正された testme アプリケーションを見てみましょう。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <stdio.h>
#include <string.h>

int fuzzme(char *buf)
{
  if(buf[0] == 'b')
    if(buf[1] == 'u')
      if(buf[2] == 'g') {
        return 0; // Fixed: No more defect.
      }
  return 0;
}

int main(int argc, char *argv[])
{
  FILE *f;
  char buf[12];

  if(argc != 2){
    fprintf(stderr, "Must supply a text file\n");
    return -1;
  }
  f = fopen(argv[1], "r");
  if(f == NULL){
    fprintf(stderr, "Could not open %s\n", argv[1]);
    return -1;
  }
  if(fgets(buf, sizeof(buf), f) == NULL){
    fprintf(stderr, "Could not read from %s\n", argv[1]);
    return -1;
  }
  fuzzme(buf);
  return 0;
}

不適切な入力検証の欠陥を修正するには、行 9abort();return 0; に修正するだけで十分です。下のボタンをクリックして、修正済みの testme アプリケーションに対してリグレッション テストを実行しましょう。

新規ランの作成フローでページ下部の [Show Mayhemfile] リンクをクリックし、Mayhemfile が次のようになっていることを確認します。

1
2
3
4
5
6
7
8
image: index.docker.io/forallsecure/tutorial:latest
duration: 90
project: forallsecure-tutorial
target: testme
tasks:
  - name: regression_testing
cmds:
  - cmd: /root/tutorial/testme/v2/testme @@
1
2
3
4
5
6
7
8
image: $MAYHEM_DOCKER_REGISTRY/forallsecure/tutorial:latest
duration: 90
project: forallsecure-tutorial
target: testme
tasks:
  - name: regression_testing
cmds:
  - cmd: /root/tutorial/testme/v2/testme @@

用意が出来たら、最新の変更済み testme アプリケーションに対するリグレッション テストを開始します。

Mayhem ラン ページの下部にスクロールすると、テスト ケースごとにリグレッション テストの結果が表示されています。以前はクラッシュを起こしたテスト ケースと関連する欠陥が修正済みとしてマークされていることに注目してください。

regression-testing-ui.png

以上、よくできました。これで、Mayhem を使用してターゲット アプリケーションの欠陥を発見しただけでなく、修正版のターゲット バイナリおよび基になっているコードのテストで、欠陥に関連するテスト ケースが解決されたことを確認できました。

Tip

このテストとリグレッション テストのライフ サイクルを CI/CD パイプラインの中で自動化する方法については「統合」ページを参照してください。

現実的な演習: lighttpd Docker イメージをテストする

Lighttpd は、コンプライアンス、セキュリティ、柔軟性を考慮し、スピードを追究して最適化されたオープンソースの Web サーバーです。以前、lighttpd バージョン 1.4.15 にはいくつかの脆弱性があり、その後修正されました。

Mayhem Docker レジストリにある forallsecure/tutorial/lighttpd:1.4.15 Docker イメージに対して新規 Mayhem ランを作成し、バグをあぶりだせるかどうかやってみましょう。

Dockerhub にある forallsecure/lighttpd:1.4.15 Docker イメージに対して新規 Mayhem ランを作成し、バグをあぶりだせるかどうかやってみましょう。

手順

  1. Create New Run ページに移動します。

  2. テスト対象の Docker イメージとして forallsecure/lighttpd:1.4.15 を入力します。新規ランを作成するプロジェクトを指定します。

  3. Command(s) セクションに値 /usr/local/sbin/lighttpd -D -f /usr/local/etc/lighttpd.conf を入力します。最上位のタブ Command (1)Network Settings -> Network URLtcp://localhost:80Network Settings -> Network Timeout2 を指定します。オプションとして、テスト継続時間を 90 秒に変更できます。ページ下部の mayhem コマンドは次のように表示されるはずです。

    1
    2
    3
    4
    5
    mayhem run forallsecure/lighttpd:1.4.15 --owner myuser \
      --project forallsecure-tutorial \
      --target testme --docker --duration 90 \
      --cmd '/usr/local/sbin/lighttpd -D -f /usr/local/etc/lighttpd.conf' \
      --network-url tcp://localhost:80 --network-timeout 2
    

    Info

    Mayhem で lighttpd のようなネットワーク ターゲットを実行し、テストするには、Mayhemfile でネットワーク設定が構成されている必要があります。ネットワーク設定の詳細については「 Mayhemfile の構成」を参照してください。

  4. Create project and run をクリックして、lighttpd Docker イメージに対する新規 Mayhem ランを実行します。90 秒以内に lighttpd ターゲットの欠陥が発見されるはずです。

  1. Create New Run ページに移動します。

  2. イメージのソースとして Mayhem Docker Registry を選択し、forallsecure/tutorial/lighttpd Docker リポジトリを検索します。1.4.15 というタグが付けられた Docker イメージを選択し、[Next] をクリックして Mayhem ファイルを構成します。

  3. cmds の値として /usr/local/sbin/lighttpd -D -f /usr/local/etc/lighttpd.conf が指定され、Mayhemfile のプレビューが次のようになっていることを確認します。

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    image: $MAYHEM_DOCKER_REGISTRY/forallsecure/tutorial/lighttpd:1.4.15
    duration: 90
    project: forallsecure-tutoriallighttpd
    target: '1415'
    cmds:
      - cmd: /usr/local/sbin/lighttpd -D -f /usr/local/etc/lighttpd.conf
        network:
          url: tcp://localhost:80
          timeout: 2
          client: false
    

    Info

    Mayhem で lighttpd のようなネットワーク ターゲットを実行し、テストするには、Mayhemfile でネットワーク設定が構成されている必要があります。ネットワーク設定の詳細については「 Mayhemfile Specification」を参照してください。

  4. 新規ラン作成フローの最後に到達するまで [Next ] をクリックします。用意が出来たら、選択を確認して [Start Run] をクリックし、lighttpd Docker イメージに対する新規 Mayhem ランを実行します。90 秒以内に lighttpd ターゲットの欠陥が発見されるはずです。

🔍 確認lighttpd Docker イメージをテストする

解答

lighttpd:1.4.15 イメージに対して正常に Mayhem ランを実行できた場合、ラン ページは次のようにひょうじされます。

first-run-lighttpd

Mayhem が検出した内容を詳しく見てみましょう。[Analysis] および [Test Cases/Defects] ペインにスクロール ダウンします。

lighttpd-analysis-pane

以下のメトリクスを参照できます。

  • Defects Found: 1
  • Crashing Test Cases: 21
  • Runtime Errors: 0
  • Tests Run: 2,082,039
  • Tests Run Per Second: 2,761.32
  • Test Suite Size: 420
  • Edges Covered: 5,343

Mayhem ランの実行結果は、上記のようになるはずですが、まったく同じとはかぎりません。これは、Mayhem がターゲット バイナリをテストする際、同じターゲットでも、ファジングによるランダムな入力によってランのカバーするレベルが異なる可能性があるからです。

さらに、Test Cases ペインに移動すると、21 個のクラッシュするテスト ケースと発見された 1 個の固有の欠陥について、テスト スイート内の個々のテスト ケースに関する詳細情報があることがわかります。

lighttpd-crashing-test-cases

  1. Test Case ID: テスト ケース固有の識別子です。個々のテスト ケースの詳細と結果へのリンクも表示されています。
  2. Test Case Result: 入力テスト ケースの結果です。
  3. Defect Count: テスト ケースごとの検出された欠陥の数です。
  4. Defects: 結果として見つかった欠陥の数および見つかった欠陥の説明です。
  5. Time: Mayhem ラン実行中に発生したプログラムのクラッシュの時間です。
  6. Download: 個々のテスト ケースをダウンロードして保存するためのダウンロード ボタンです。

これで終わりです。さらに自由に操作して、lighttpd に対して生成されたテスト ケースに関して何がわかるか、また基になっているコードにどのような影響があるかを調べてみましょう。

最初のハンズオン レッスンを終えてお疲れさまでした。

✏️ まとめと振り返り

このレッスンでは、Mayhem UI を使用して初めての Mayhem ランを実行する手順を学びました。

Mayhem UI を使用すると、パブリックにアクセス可能な Docker イメージの取り込みと実行を簡単に行うことができます。必要な操作は、Create New Run ページに移動し、Docker イメージ ソースを選択し、実行用 Mayhemfile を構成して設定を確認し、ランを実行するだけです。

Mayhem UI を使用すると、プライベートまたはパブリックにアクセス可能な Docker イメージの取り込みと実行を簡単に行うことができます。必要な操作は、Create New Run ページに移動し、Docker イメージ ソースを選択し、実行用 Mayhemfile を構成して設定を確認し、ランを実行するだけです。


学習内容

1.Mayhem UI から testme ターゲットを含む Docker イメージに対して初めての Mayhem ランを実行する
  • Mayhem UI を使用すると、Mayhem の内部的な Docker レジストリにアップロードされた、またはパブリックな Docker Hub レジストリにホストされたコンテナー アプリケーション (ターゲット) の Mayhem ランの作成と管理を使いやすい Web インターフェイスで行うことができます。コンテナー化されたアプリケーションをテストするだけでなく、テスト結果の分析を参照することもできます。
    • 新規ランの作成プロセスには次の 3 つのステップがあります。
      1. イメージの選択: ファズ テストのために Mayhem に取り込む Docker イメージを選択し、Docker イメージの取り込み元として Mayhem のプライベートな Docker レジストリまたはパブリックな Docker Hub レジストリを指定します。
      2. Mayhemfile の作成: Mayhem ランを定義する Mayhemfile のオプションを構成します。
      3. Mayhem の実行: 選択を確認し、Mayhem ランを実行します。
2.クラッシュを起こすテスト ケースによって生成された欠陥を再現する
  • testme バイナリおよびクラッシュを起こすテスト ケースをダウンロードし、欠陥を再現するコマンドを実行すると、次のようなメッセージが出力されます。

    ~/tutorial/testme/v1# ./testme d1134fb406ea8ded0fe8c19dfdfd63cecea25f7e1cd7292e789d0841adfa9f12
    Floating point exception
    
3.修正された testme ターゲットに対してリグレッション テストを実行する
  • Mayhem は、ターゲット アプリケーションをテストするテスト ケースを生成する際、以降のテストで使用するためにテスト ケースを保存します。そうすることで、以降の Mayhem ランで以前生成されたテスト ケースを利用し、現在のランで欠陥が解決されているかを確認できます。これを リグレッション テスト と呼びます。
4.Mayhem UI から一般的な lighttpd Web サーバーに対して Mayhem ランを実行する
  • Lighttpd は、コンプライアンス、セキュリティ、柔軟性を考慮し、スピードを追究して最適化されたオープンソースの Web サーバーです。以前、lighttpd バージョン 1.4.15 にはいくつかの脆弱性があり、その後修正されました。
  • cmds/usr/local/sbin/lighttpd -D -f /usr/local/etc/lighttpd.conf が指定されていることを確認し、Mayhemfile のプレビューが次のようになっていることを確認します。
    image: $MAYHEM_DOCKER_REGISTRY/forallsecure/tutorial/lighttpd:1.4.15
    duration: 90
    project: forallsecure-tutoriallighttpd
    target: '1415'
    cmds:
      - cmd: /usr/local/sbin/lighttpd -D -f /usr/local/etc/lighttpd.conf
        network:
          url: tcp://localhost:80
          timeout: 2
          client: false