上級
Honggfuzz を使用してインストゥルメントされた C/C++ ターゲット¶
Honggfuzz インストゥルメンテーション付きで C/C++ ターゲットをコンパイルする必要がありますか? このレッスンでは、Mayhem で C/C++ honggfuzz ターゲットをコンパイルし、テストする方法を手順を追って説明します。
学習時間の目安: 15 分
このレッスンを終了すると、以下のことができるようになります。
- 不適切な入力検証の欠陥がある C honggfuzz ターゲットをコンパイルし、ファジングする。
- 不適切な入力検証の欠陥がある C++ honggfuzz ターゲットをコンパイルし、ファジングする。
レッスンを駆け足で
始める前に前提条件を確認します。
-
c-honggfuzz-gcc.tgz をダウンロードし、
c-honggfuzz-gcc
Docker イメージをビルドし、指定された Docker レジストリにプッシュします。docker build -f Dockerfile -t <DOCKERHUB_USERNAME>/c-honggfuzz-gcc . docker push <DOCKERHUB_USERNAME>/c-honggfuzz-gcc
docker build -f Dockerfile -t $MAYHEM_DOCKER_REGISTRY/forallsecure/c-honggfuzz-gcc . docker push $MAYHEM_DOCKER_REGISTRY/forallsecure/c-honggfuzz-gcc
-
Mayhem UI または Mayhem CLI で次の Mayhemfile を使用して
forallsecure/c-honggfuzz-gcc
Docker イメージに対して Mayhem ランを実行します。1 2 3 4 5 6 7
image: <DOCKERHUB_USERNAME>/c-honggfuzz-gcc:latest duration: 90 project: mayhem-examples target: c-honggfuzz-gcc cmds: - cmd: /mayhemit honggfuzz: true
1 2 3 4 5 6 7
image: $MAYHEM_DOCKER_REGISTRY/forallsecure/c-honggfuzz-gcc:latest duration: 90 project: mayhem-examples target: c-honggfuzz-gcc cmds: - cmd: /mayhemit honggfuzz: true
以下が必要です。
- Docker がインストールされていること
- 有効なインターネット接続 (Docker Hub ベース イメージをプルするため)
ワン クリック テスト¶
次のボタンをクリックし、Create New Run フローの最後で Start Run をクリック して honggfuzz インストゥルメンテーション付き C ターゲットのテストを開始します。Mayhemfile
はすでに用意されているため、何も設定する必要はありません。
Mayhem ランが始まると、次のようなラン ページが表示されます。
すばらしい! Mayhem が honggfuzzを使用してインストゥルメントされた C ターゲットをファジングできることを確認したので、次に、たった今 Mayhem ランを実行した honggfuzz ターゲットをコンパイルし、テストする方法を順を追って説明します。
Honggfuzz インストゥルメンテーション付き C ターゲットのコンパイルとテスト¶
ファイル: c-honggfuzz-gcc.tgz
上記の c-honggfuzz-gcc.tgz
をダウンロードして展開し、次の mayhemit.c
のソース コードを見てみましょう。
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 |
|
ソース コードは通常の main
関数ではなく、HF_ITER
関数を使用してバイト配列を受け取り、ターゲット関数 mayhemit
のファジングに使用していることに気づくでしょう。入力が "bug" の場合、プログラムは不適切な入力検証のエラーでクラッシュします。
Note
honggfuzz を使用する場合、ASAN スタイル (LLVMFuzzerTestOneInput) または HF_ITER スタイルの 2 つのタイプのファザー エントリポイントがあります。詳細については honggfuzz persistent fuzzing に関する公式ドキュメントを参照してください。
Dockerfile
を見ると、c-honggfuzz-gcc
ターゲットのコンパイル プロセスがわかります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
- 行 1: 必要な honggfuzz 依存関係を提供するため、
fuzzers/honggfuzz:1.9
ベース イメージがインポートされています。 - 行 2: Docker コンテナーに
mayhemit.c
ソース ファイルがコピーされています。 - 行 3:
hfuzz-gcc
C コンパイラを使用して honggfuzz インストゥルメンテーション付きで C ターゲットがコンパイルされています。 - 行 5:
debian:buster-slim
ベース イメージがインポートされ、直前のビルド ステージからコンパイル済みのmayhemit
バイナリがhonggfuzz
ファザー (および関連する依存関係) とともにコピーされています。 - 行 17: Docker コンテナーのデフォルト実行ファイルとして
/mayhemit
実行ファイルが設定されています。
Note
行 5-13 の処理はマルチステージ ビルドと呼ばれ、構築される Docker イメージを最適化したり、サイズをスリム化したりするために行われます。さらに、honggfuzz ドライバーは honggfuzz コンパイルされたバイナリと同じバージョンでなければなりません。そのため、直前のビルド ステージから honggfuzz
実行ファイルをコピーすることで、バイナリをコンパイルしたものと同じバージョンの honggfuzz が使用されることを保証します。
次に、<DOCKERHUB_USERNAME>/c-honggfuzz-gcc
Docker イメージをビルドし、Docker Hub レジストリにプッシュする必要があります。
次に、forallsecure/c-honggfuzz-gcc
Docker イメージをビルドし、Mayhem Docker レジストリにプッシュする必要があります。
docker build -f Dockerfile -t <DOCKERHUB_USERNAME>/c-honggfuzz-gcc .
docker push <DOCKERHUB_USERNAME>/c-honggfuzz-gcc
docker build -f Dockerfile -t $MAYHEM_DOCKER_REGISTRY/forallsecure/c-honggfuzz-gcc .
docker push $MAYHEM_DOCKER_REGISTRY/forallsecure/c-honggfuzz-gcc
情報
mayhem login
コマンドを使用して内部的な Mayhem Docker レジストリの URL を検索し、次のコマンドを使用して DOCKER_REGISTRY
環境変数を設定できます:
export DOCKER_REGISTRY=tutorial.forallsecure.com:5000
DOCKER_REGISTRY
環境変数に自身の Mayhem Docker レジストリ URL を設定する必要があります。
新しく作成した Docker イメージを Docker Hub レジストリに正常にプッシュしたら、Mayhem UI から新規ランを作成し、<DOCKERHUB_USERNAME>/c-honggfuzz-gcc
Docker イメージを検索します。Mayhemfile
が次のようになっていることを確認します。
新しく作成した Docker イメージをプライベートな Mayhem Docker レジストリに正常にプッシュしたら、Mayhem UI から新規ランを作成し、forallsecure/c-honggfuzz-gcc
Docker イメージを検索します。Mayhemfile
が次のようになっていることを確認します。
1 2 3 4 5 6 7 |
|
1 2 3 4 5 6 7 |
|
新規ラン作成フローの最終確認ページに到達するまで [Next] をクリックし、[Start Run] をクリックして Mayhem ランを実行します。次のようなラン ページが表示されます。
おめでとうございます! Mayhem で C Honggfuzz ターゲットのテストが成功しました。
⚡ 現実的な演習: Honggfuzz インストゥルメンテーション付き C++ ターゲットのコンパイルとテスト¶
honggfuzz インストゥルメンテーション付き C ターゲットのコンパイルおよびテスト手順がわかったので、次に、同じことを C++ ターゲットに対して行うことができるか、やってみましょう。
ファイル: cpp-honggfuzz-gcc.tgz
手順
Dockerfile
およびdocker build
コマンドを使用してDocker イメージをビルドし、結果を<DOCKERHUB_USERNAME>/cpp-honggfuzz-gcc
としてタグ付けします。docker tag
およびdocker push
コマンドを使用してパブリックな Docker Hub レジストリに<DOCKERHUB_USERNAME>/cpp-honggfuzz-gcc
Docker イメージをプッシュします。-
Mayhem UI または Mayhem CLI を使用して
<DOCKERHUB_USERNAME>/cpp-honggfuzz-gcc
Docker イメージをファジングします。Mayhemfile
が適切に設定されていることを確認します。 -
Dockerfile
およびdocker build
コマンドを使用してDocker イメージをビルドし、結果をforallsecure/cpp-honggfuzz-gcc
としてタグ付けします。 docker tag
およびdocker push
コマンドを使用して内部的な Mayhem Docker レジストリにforallsecure/cpp-honggfuzz-gcc
Docker イメージをプッシュします。- Mayhem UI または Mayhem CLI を使用して
forallsecure/cpp-honggfuzz-gcc
Docker イメージをテストします。Mayhemfile
が適切に設定されていることを確認します。
🔍 確認 Honggfuzz インストゥルメンテーション付き C++ ターゲットのコンパイルとテスト¶
解答
まず、mayhemit.cpp
プログラムのソース コードを見てみましょう。
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 |
|
c-honggfuzz-gcc
ターゲットのソース コードと比較したとき、extern "C"
キーワードが使用されているという違いがあることに気づいたかもしれません。extern "C"
キーワードは、C++ の関数名に C リンケージを持たせ、クライアントの C コードが関数の宣言だけを含む C 互換ヘッダー ファイルを使用して関数にリンク (使用) できるようにします。
次に、対応する Dockerfile を確認します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
行 1 で、以前と同じように fuzzers/honggfuzz:1.9
ベース イメージをインポートし、行 3 で、今度は hfuzz-g++
コンパイラを使用して Honggfuzz インストゥルメンテーション付き C++ ターゲットをコンパイルしていることがわかります。その後、行 5 に進むと、コンパイルされた mayhemit
バイナリおよび honggfuzz
ファザーが (その依存関係とともに) debian:buster-slim
ベース イメージに基づく次のステージ ビルドにコピーされています。結果として、この Dockerfile
はマルチステージ ビルドになり、結果の Docker イメージのディスク領域が最適化されます。
次に、Dockerfile
と同じディレクトリで docker build
コマンドを実行し、結果の Docker イメージに <DOCKERHUB_USERNAME>/cpp-honggfuzz-gcc
とタグ付けします。
次に、Dockerfile
と同じディレクトリで docker build
コマンドを実行し、結果の Docker イメージに forallsecure/cpp-honggfuzz-gcc
とタグ付けします。
docker build -f Dockerfile -t <DOCKERHUB_USERNAME>/cpp-honggfuzz-gcc .
docker build -f Dockerfile -t $MAYHEM_DOCKER_REGISTRY/forallsecure/cpp-honggfuzz-gcc .
次に、<DOCKERHUB_USERNAME>/cpp-honggfuzz-gcc
Docker イメージを Docker Hub レジストリにプッシュします。
次に、forallsecure/cpp-honggfuzz-gcc
Docker イメージをプライベートな Mayhem Docker レジストリにプッシュします。
docker push <DOCKERHUB_USERNAME>/cpp-honggfuzz-gcc
docker push $MAYHEM_DOCKER_REGISTRY/forallsecure/cpp-honggfuzz-gcc
最後に、Mayhem UI または Mayhem CLI を使用して、アップロードされた <DOCKERHUB_USERNAME>/cpp-honggfuzz-gcc
Docker イメージに対して Mayhem ランを実行します。Mayhemfile
は次のようになっているはずです。
最後に、Mayhem UI または Mayhem CLI を使用して、アップロードされた forallsecure/cpp-honggfuzz-gcc
Docker イメージに対して Mayhem ランを実行します。Mayhemfile
は次のようになっているはずです。
1 2 3 4 5 6 7 |
|
1 2 3 4 5 6 7 |
|
Mayhem ランを開始すると、次のようなラン ページが表示されるはずです。
おめでとうございます! Mayhem が不適切な入力検証の欠陥を発見しました。スクラッチから honggfuzz C++ ターゲットをビルドし、Mayhem を使用してバグを検出できました。
✏️ まとめと振り返り¶
このレッスンでは、Honggfuzz インストゥルメンテーション付きで C/C++ ターゲットをコンパイルし、Mayhem でファジングする方法を学びました。
学習内容
1. 不適切な入力検証の欠陥がある C honggfuzz ターゲットをコンパイルし、テストする。
-
ソース コードには次の欠陥が含まれているはずです:
1 2 3 4 5 6 7 8 9 10
int mayhemit(char *buf, unsigned len) { if(len >= 3) if(buf[0] == 'b') if(buf[1] == 'u') if(buf[2] == 'g') { abort(); // Defect: SIGABRT. } return 0; }
-
C honggfuzz ターゲットをファジングするには、次の
Dockerfile
およびMayhemfile
を使用して C プログラムを含む Docker イメージをビルドし、Mayhem でファジングを実行します。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
FROM fuzzers/honggfuzz:1.9 COPY mayhemit.c . RUN hfuzz-gcc mayhemit.c -o /mayhemit FROM debian:buster-slim COPY --from=0 /mayhemit . COPY --from=0 /usr/local/bin/honggfuzz /usr/local/bin/honggfuzz COPY --from=0 /usr/lib/x86_64-linux-gnu/libunwind-ptrace.so.0 /usr/lib/x86_64-linux-gnu/libunwind-ptrace.so.0 COPY --from=0 /usr/lib/x86_64-linux-gnu/libunwind-x86_64.so.8 /usr/lib/x86_64-linux-gnu/libunwind-x86_64.so.8 COPY --from=0 /usr/lib/x86_64-linux-gnu/libbfd-2.31.1-system.so /usr/lib/x86_64-linux-gnu/libbfd-2.31.1-system.so COPY --from=0 /usr/lib/x86_64-linux-gnu/libopcodes-2.31.1-system.so /usr/lib/x86_64-linux-gnu/libopcodes-2.31.1-system.so COPY --from=0 /usr/lib/x86_64-linux-gnu/libunwind.so.8 /usr/lib/x86_64-linux-gnu/libunwind.so.8 RUN mkdir /testsuite && echo seed > /testsuite/seed # Set to fuzz! ENTRYPOINT ["honggfuzz", "-f", "/testsuite", "--"] CMD ["/mayhemit"]
1 2 3 4 5 6 7
image: <DOCKERHUB_USERNAME>/c-honggfuzz-gcc:latest duration: 90 project: mayhem-examples target: c-honggfuzz-gcc cmds: - cmd: /mayhemit honggfuzz: true
1 2 3 4 5 6 7
image: $MAYHEM_DOCKER_REGISTRY/forallsecure/c-honggfuzz-gcc:latest duration: 90 project: mayhem-examples target: c-honggfuzz-gcc cmds: - cmd: /mayhemit honggfuzz: true
2. 不適切な入力検証の欠陥がある C++ honggfuzz ターゲットをコンパイルし、ファジングする。
-
ソース コードには次の欠陥が含まれているはずです:
1 2 3 4 5 6 7 8 9 10
int mayhemit(char *buf, unsigned len) { if(len >= 3) if(buf[0] == 'b') if(buf[1] == 'u') if(buf[2] == 'g') { abort(); // Defect: SIGABRT. } return 0; }
-
C honggfuzz ターゲットをファジングするには、次の
Dockerfile
およびMayhemfile
を使用して C プログラムを含む Docker イメージをビルドし、Mayhem でファジングを実行します。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
FROM fuzzers/honggfuzz:1.9 COPY mayhemit.cpp . RUN hfuzz-g++ mayhemit.cpp -o /mayhemit FROM debian:buster-slim COPY --from=0 /mayhemit . COPY --from=0 /usr/local/bin/honggfuzz /usr/local/bin/honggfuzz COPY --from=0 /usr/lib/x86_64-linux-gnu/libunwind-ptrace.so.0 /usr/lib/x86_64-linux-gnu/libunwind-ptrace.so.0 COPY --from=0 /usr/lib/x86_64-linux-gnu/libunwind-x86_64.so.8 /usr/lib/x86_64-linux-gnu/libunwind-x86_64.so.8 COPY --from=0 /usr/lib/x86_64-linux-gnu/libbfd-2.31.1-system.so /usr/lib/x86_64-linux-gnu/libbfd-2.31.1-system.so COPY --from=0 /usr/lib/x86_64-linux-gnu/libopcodes-2.31.1-system.so /usr/lib/x86_64-linux-gnu/libopcodes-2.31.1-system.so COPY --from=0 /usr/lib/x86_64-linux-gnu/libunwind.so.8 /usr/lib/x86_64-linux-gnu/libunwind.so.8 RUN mkdir /testsuite && echo seed > /testsuite/seed # Set to fuzz! ENTRYPOINT ["honggfuzz", "-f", "/testsuite", "--"] CMD ["/mayhemit"]
1 2 3 4 5 6 7
image: <DOCKERHUB_USERNAME>/cpp-honggfuzz-gcc:latest duration: 90 project: mayhem-examples target: cpp-honggfuzz-gcc cmds: - cmd: /mayhemit honggfuzz: true
1 2 3 4 5 6 7
image: $MAYHEM_DOCKER_REGISTRY/forallsecure/cpp-honggfuzz-gcc:latest duration: 90 project: mayhem-examples target: cpp-honggfuzz-gcc cmds: - cmd: /mayhemit honggfuzz: true