コンテンツにスキップ

上級

ベース実行ファイル Ada ターゲット

ada-logo

テスト対象はインストゥルメンテーションされていない、またはベース実行ファイルの Ada ターゲットでしょうか? このレッスンでは、Mayhem を使用して Ada ターゲットをテストする方法を順を追って説明します。

学習時間の目安: 15 分

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

  1. 不適切な入力検証の欠陥があるベース実行ファイル Ada ターゲットをビルドし、テストする。
  2. インデックス境界外の欠陥があるベース実行ファイル Ada ターゲットをビルドし、テストする。

以下が必要です。

  • Docker がインストールされていること
  • 有効なインターネット接続 (Docker Hub ベース イメージをプルするため)

ワン クリック テスト

下のボタンをクリックしてベース実行ファイル Ada ターゲットのテストを開始します。最終確認ページに到達するまで [Next ] をクリックし、[Start Run] をクリックします。

次のようなラン ページが表示されます。

ada-base-executable-run

Mayhem によるベース実行ファイル Ada ターゲットのテストを確認したので、次に、どのように Ada ターゲットがビルドされたのかを順を追って説明します。

ベース実行ファイル Ada ターゲットのテスト

ファイル: ada-base-executable.tgz

上記の ada-base-executable.tgz をダウンロードして展開し、次のバグのある mayhemit.adb プログラムを見てみましょう。

 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
35
36
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Command_Line;
with Ada.Assertions;
with GNAT.Exception_Actions;

procedure Mayhemit is
  Length : Integer := 128;
  Input : String (1 .. Length);
  Fd : File_Type;
  Filename : aliased String := Ada.Command_Line.Argument(1);
  procedure FuzzTest (Input : String) is
    Zero : Integer := 0;
    One : Integer := 1;
    Answer : Integer := 0;
  begin
    if Input (Input'First .. Input'First) = "b" then
      if Input (Input'First + 1 .. Input'First + 1) = "u" then
        if Input (Input'First + 2 .. Input'First + 2) = "g" then
          raise Ada.Assertions.Assertion_Error;
          -- Answer := One / Zero;
        end if;
      end if;
    end if;
  end FuzzTest;
begin

  Open (File => Fd,
        Mode => In_File,
        Name => Filename);
  Get_Line (Fd, Input, Length);
  FuzzTest(Input);

exception
  when Occurence : others  =>
     GNAT.Exception_Actions.Core_Dump (Occurence);
end Mayhemit;

ソース コードの先頭でさまざまなモジュールがインポートされ、Mayhemit および FuzzTest の 2 つのプロシージャがあることがわかります。

Mayhemit プロシージャはプログラムへのメイン エントリとして機能し、ファイル入力を処理するいっぽう、FuzzTest プロシージャは入力が "bug" であるかをチェックします。入力が "bug" である場合、プログラムはアサーションにより、不適切な入力検証の欠陥でクラッシュします。

次に ada-base-executable がどのようにビルドされるかを見てみましょう。関連する Dockerfile を見ると、以下の処理があるのがわかります。

1
2
3
4
5
6
7
FROM tomekw/ada-gnat
COPY mayhemit.adb .
RUN gnatmake -o /mayhemit mayhemit.adb

# Set to fuzz!
ENTRYPOINT []
CMD ["/mayhemit", "@@"]
  • 行 1: 必要な Ada 依存関係を収集するため、tomekw/ada-gnat ベース イメージがインポートされています。
  • 行 2: Docker コンテナーに mayhemit.adb ソース ファイルがコピーされています。
  • 行 3: gnatmake コンパイラを使用して mayhemit.adb ソース コードが mayhemit 実行ファイルにコンパイルされています。
  • 行 6: Docker コンテナーのデフォルト実行ファイルとして /mayhemit @@ コマンドが設定されています。

次に、docker build および docker push コマンドを使用して、Docker イメージをビルドして Mayhem サーバーにプッシュする必要があります。

次に、docker build および docker push コマンドを使用して、Docker イメージをビルドして Mayhem サーバーにプッシュする必要があります。$DOCKER_REGISTRY は、プライベートな Mayhem Docker レジストリの URL を表します。

docker build -f Dockerfile -t <DOCKERHUB_USERNAME>/ada-base-executable .
docker push <DOCKERHUB_USERNAME>/ada-base-executable
docker build -f Dockerfile -t $MAYHEM_DOCKER_REGISTRY/forallsecure/ada-base-executable .
docker push $MAYHEM_DOCKER_REGISTRY/forallsecure/ada-base-executable

情報

mayhem login コマンドを使用して内部の Mayhem Docker レジストリ URL を検索し、次のコマンドを実行して DOCKER_REGISTRY 環境変数を設定できます。

export DOCKER_REGISTRY=tutorial.forallsecure.com:5000
ここでは、サンプルの Mayhem Docker レジストリ URL を指定していますが、ユーザー自身の Mayhem Docker レジストリ URL を DOCKER_REGISTRY 環境変数に設定する必要があります。

新しく作成した Docker イメージをパブリックな Docker Hub レジストリに正常にプッシュしたら、Mayhem UI から新規ランを作成し、<DOCKERHUB_USERNAME>/ada-base-executable Docker イメージを検索します。Mayhemfile が次のようになっていることを確認します。

新しく作成した Docker イメージをプライベートな Mayhem Docker レジストリに正常にプッシュしたら、Mayhem UI から新規ランを作成し、forallsecure/ada-base-executable Docker イメージを検索します。Mayhemfile が次のようになっていることを確認します。

1
2
3
4
5
image: <DOCKERHUB_USERNAME>/ada-base-executable:latest
project: mayhem-examples
target: ada-base-executable
cmds:
  - cmd: /mayhemit @@
1
2
3
4
5
image: $MAYHEM_DOCKER_REGISTRY/forallsecure/ada-base-executable:latest
project: mayhem-examples
target: ada-base-executable
cmds:
  - cmd: /mayhemit @@

新規ラン作成フローの最終確認ページに到達するまで [Next ] をクリックし、[Start Run] をクリックして Mayhem ランを実行します。次のようなラン ページが表示されます。

ada-base-executable-run

おめでとうございます! ベース実行ファイル Ada ターゲットのテストが成功しました。

現実的な演習: mayhemit-out-of-bounds ベース実行ファイル Ada ターゲットのコンパイルとテスト

不適切な入力検証の欠陥がある Ada ターゲットのビルドおよびテスト方法がわかったところで、ソース コードを修正してインデックス境界外の欠陥を検出できるかどうかやってみましょう。

ファイル: mayhemit-out-of-bounds-unsolved.zip

手順

  • Answer 変数を空の文字列として初期化し、インデックス境界外の欠陥を追加するよう mayhemit.adb ソース コードを変更します。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
procedure Mayhemit is
Length : Integer := 3;
Input : String (1 .. Length);
Fd : File_Type;
Filename : aliased String := Ada.Command_Line.Argument(1);
procedure FuzzTest (Input : String) is
  Zero : Integer := 0;
  One : Integer := 1;
  Answer : String := "";
begin
  if Input (Input'First .. Input'First) = "b" then
    if Input (Input'First + 1 .. Input'First + 1) = "u" then
      if Input (Input'First + 2 .. Input'First + 2) = "g" then
        -- raise Ada.Assertions.Assertion_Error; also works.
        Answer := Input (Input'First + 10 .. Input'First + 10);
      end if;
    end if;
  end if;
end FuzzTest;
  • docker build コマンドを使用して Dockerfile を再ビルドし、結果の Docker イメージを <DOCKERHUB_USERNAME>/ada-base-executable-mayhemit-out-of-bounds としてタグ付けします。

  • docker tag および docker push コマンドを使用して内部的な Mayhem Docker レジストリに <DOCKERHUB_USERNAME>/ada-base-executable-mayhemit-out-of-bounds Docker イメージをプッシュします。

  • Mayhem UI または Mayhem CLI を使用して <DOCKERHUB_USERNAME>/ada-base-executable-mayhemit-out-of-bounds Docker イメージをファジングします。Mayhemfile が適切に設定されていることを確認します。

  • docker build コマンドを使用して Dockerfile を再ビルドし、結果の Docker イメージを $MAYHEM_DOCKER_REGISTRY/ada-base-executable-mayhemit-out-of-bounds としてタグ付けします。

  • docker tag および docker push コマンドを使用して内部的な Mayhem Docker レジストリに $MAYHEM_DOCKER_REGISTRY/ada-base-executable-mayhemit-out-of-bounds Docker イメージをプッシュします。

  • Mayhem UI または Mayhem CLI を使用して $MAYHEM_DOCKER_REGISTRY/ada-base-executable-mayhemit-out-of-bounds Docker イメージをテストします。Mayhemfile が適切に設定されていることを確認します。

🔍 確認 mayhemit-out-of-bounds ベース実行ファイル Ada ターゲットのコンパイルとテスト

解答

解答: mayhemit-out-of-bounds-solved.zip

まず、Answer 変数を string 型として設定します。次に、Answer 変数にインデックスが行 7 で指定された最大長によって期待される範囲外の string 文字を設定することでインデックス境界外の欠陥を追加します。

これによって、FuzzTest プロシージャをファジングしたとき、Answer 変数の最大長が 3 に設定されているいっぽうで Answer 変数にインデックス 11 (Input'First + 10) が設定されているため、入力テスト ケース "bug" はインデックス境界外エラーを発生させます。

 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
35
36
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Command_Line;
with Ada.Assertions;
with GNAT.Exception_Actions;

procedure Mayhemit is
  Length : Integer := 3;
  Input : String (1 .. Length);
  Fd : File_Type;
  Filename : aliased String := Ada.Command_Line.Argument(1);
  procedure FuzzTest (Input : String) is
    Zero : Integer := 0;
    One : Integer := 1;
    Answer : String := "";
  begin
    if Input (Input'First .. Input'First) = "b" then
      if Input (Input'First + 1 .. Input'First + 1) = "u" then
        if Input (Input'First + 2 .. Input'First + 2) = "g" then
          -- raise Ada.Assertions.Assertion_Error; also works.
          Answer := Input (Input'First + 10 .. Input'First + 10);
        end if;
      end if;
    end if;
  end FuzzTest;
begin

  Open (File => Fd,
        Mode => In_File,
        Name => Filename);
  Get_Line (Fd, Input, Length);
  FuzzTest(Input);

exception
  when Occurence : others  =>
    GNAT.Exception_Actions.Core_Dump (Occurence);
end Mayhemit;

次に、Dockerfile と同じディレクトリで docker build コマンドを実行するとともに、結果の Docker イメージに <DOCKERHUB_USERNAME>/ada-base-executable-mayhemit-out-of-bounds というタグを付けます。

次に、Dockerfile と同じディレクトリで docker build コマンドを実行するとともに、結果の Docker イメージに ada-base-executable-mayhemit-out-of-bounds というタグを付けます。

docker build -f Dockerfile -t <DOCKERHUB_USERNAME>/ada-base-executable-mayhemit-out-of-bounds .
docker build -f Dockerfile -t ada-base-executable-mayhemit-out-of-bounds .

次に、<DOCKERHUB_USERNAME>/ada-base-executable-mayhemit-out-of-bounds Docker イメージにタグを付けて内部的な Mayhem Docker リポジトリにプッシュします。

次に、ada-base-executable-mayhemit-out-of-bounds Docker イメージにタグを付けて内部的な Mayhem Docker リポジトリにプッシュします。

docker push <DOCKERHUB_USERNAME>/ada-base-executable-mayhemit-out-of-bounds
docker push tutorial.forallsecure.com:5000/ada-base-executable-mayhemit-out-of-bounds

注意

ここでは ada-base-executable-mayhemit-out-of-bounds Docker イメージを tutorial.forallsecure.com Mayhem デプロイメントのポート 5000 にある内部的な Docker レジストリにアップロードしています。Docker イメージを正常にアップロードするには、お使いの Mayhem デプロイメントの Docker レジストリの URL に変更する必要があります。

または、付属の Makefile を使用し、MAYHEM_DOCKER_REGISTRY 環境変数を設定して次のコマンドを実行することで、簡単に Docker イメージをビルドしてプッシュすることもできます。

make build
make push

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

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

1
2
3
4
5
6
image: <DOCKERHUB_USERNAME>/ada-base-executable-mayhemit-out-of-bounds
duration: 90
project: mayhem-examples
target: mayhemit-out-of-bounds
cmds:
  - cmd: /mayhemit @@
1
2
3
4
5
6
image: $MAYHEM_DOCKER_REGISTRY/ada-base-executable-mayhemit-out-of-bounds
duration: 90
project: mayhem-examples
target: mayhemit-out-of-bounds
cmds:
  - cmd: /mayhemit @@

最終的なラン ページは次のようになります。

mayhemit-out-of-bounds-run

おめでとうございます! Mayhem は追加されたインデックス境界外の欠陥を検出しました。ベース実行ファイル Ada ターゲットをスクラッチからビルドし、Mayhem を使用して脆弱性を発見することができました。

✏️ まとめと振り返り

このレッスンでは、Mayhem でベース実行ファイル Ada ターゲットをファジングする方法を学びました。


学習内容

1. 不適切な入力検証の欠陥があるベース実行ファイル Ada ターゲットをコンパイルし、テストする。
  • ソース コードには次の欠陥が含まれているはずです:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    procedure Mayhemit is
    Length : Integer := 128;
    Input : String (1 .. Length);
    Fd : File_Type;
    Filename : aliased String := Ada.Command_Line.Argument(1);
    procedure FuzzTest (Input : String) is
      Zero : Integer := 0;
      One : Integer := 1;
      Answer : Integer := 0;
    begin
      if Input (Input'First .. Input'First) = "b" then
        if Input (Input'First + 1 .. Input'First + 1) = "u" then
          if Input (Input'First + 2 .. Input'First + 2) = "g" then
            raise Ada.Assertions.Assertion_Error;
            -- Answer := One / Zero;
          end if;
        end if;
      end if;
    end FuzzTest;
    

  • ベース実行 Ada ターゲットをコンパイルしてファジングするには、次の Dockerfile および Mayhemfile を使用して Ada プログラムを含む Docker イメージをビルドし、Mayhem でファジングを実行します。

    1
    2
    3
    4
    5
    6
    7
    FROM tomekw/ada-gnat
    COPY mayhemit.adb .
    RUN gnatmake -o /mayhemit mayhemit.adb
    
    # Set to fuzz!
    ENTRYPOINT []
    CMD ["/mayhemit", "@@"]
    

    1
    2
    3
    4
    5
    image: <DOCKERHUB_USERNAME>/ada-base-executable:latest
    project: mayhem-examples
    target: ada-base-executable
    cmds:
      - cmd: /mayhemit @@
    
    1
    2
    3
    4
    5
    image: $MAYHEM_DOCKER_REGISTRY/forallsecure/ada-base-executable:latest
    project: mayhem-examples
    target: ada-base-executable
    cmds:
      - cmd: /mayhemit @@
    
2. インデックス境界外の欠陥の欠陥があるベース実行ファイル Ada ターゲットをコンパイルし、ファジングする。
  • ソース コードには次の欠陥が含まれているはずです:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    procedure Mayhemit is
    Length : Integer := 3;
    Input : String (1 .. Length);
    Fd : File_Type;
    Filename : aliased String := Ada.Command_Line.Argument(1);
    procedure FuzzTest (Input : String) is
        Zero : Integer := 0;
        One : Integer := 1;
        Answer : String := "";
    begin
        if Input (Input'First .. Input'First) = "b" then
          if Input (Input'First + 1 .. Input'First + 1) = "u" then
            if Input (Input'First + 2 .. Input'First + 2) = "g" then
              -- raise Ada.Assertions.Assertion_Error; also works.
              Answer := Input (Input'First + 10 .. Input'First + 10);
              end if;
          end if;
        end if;
    end FuzzTest;
    begin
    

  • ベース実行 Ada ターゲットをコンパイルしてファジングするには、次の Dockerfile および Mayhemfile を使用して Ada プログラムを含む Docker イメージをビルドし、Mayhem でファジングを実行します。

    1
    2
    3
    4
    5
    6
    7
    FROM tomekw/ada-gnat
    COPY mayhemit.adb .
    RUN gnatmake -o /mayhemit mayhemit.adb
    
    # Set to fuzz!
    ENTRYPOINT []
    CMD ["/mayhemit", "@@"]
    

    1
    2
    3
    4
    5
    6
    image: <DOCKERHUB_USERNAME>/ada-base-executable-mayhemit-out-of-bounds
    duration: 90
    project: mayhem-examples
    target: ada-base-executable-mayhemit-out-of-bounds
    cmds:
      - cmd: /mayhemit @@
    
    1
    2
    3
    4
    5
    6
    image: $MAYHEM_DOCKER_REGISTRY/ada-base-executable-mayhemit-out-of-bounds:latest
    duration: 90
    project: mayhem-examples
    target: ada-base-executable-mayhemit-out-of-bounds
    cmds:
      - cmd: /mayhemit @@