上級
Jazzer を使用した LibFuzzer インストゥルメンテーション付き Java ターゲット¶
libFuzzer インストゥルメンテーション付きで Java ターゲットをテストする必要がありますか? libFuzzer/Jazzer を使用して Java ターゲットをインストゥルメントし、Mayhem で実行ファイルをテストする方法を順を追って説明します。
学習時間の目安: 15 分
このレッスンを終了すると、以下のことができるようになります。
- キャッチされない例外の欠陥がある libFuzzer Java ターゲットをコンパイルし、ファジングする。
- インデックス境界外の欠陥がある libFuzzer Java ターゲットをコンパイルし、ファジングする。
レッスンを駆け足で
始める前に前提条件を確認します。
-
java-jazzer.tgz をダウンロードし、
java-jazzer
Docker イメージをビルドし、指定された Docker レジストリにプッシュします。docker build -t <DOCKERHUB_USERNAME>/java-jazzer . docker push <DOCKERHUB_USERNAME>/java-jazzer
docker build -t $MAYHEM_DOCKER_REGISTRY/forallsecure/java-jazzer . docker push $MAYHEM_DOCKER_REGISTRY/forallsecure/java-jazzer
-
Mayhem UI または Mayhem CLI で次の Mayhemfile を使用して
java-jazzer
Docker イメージに対して Mayhem ランを実行します。1 2 3 4 5 6 7
image: <DOCKERHUB_USERNAME>/java-jazzer:latest duration: 90 project: mayhem-examples target: java-jazzer cmds: - cmd: /usr/bin/jazzer_driver --cp=/usr/bin/MayhemIt.jar --target_class=mayhemit.MayhemIt libfuzzer: true
1 2 3 4 5 6 7
image: $MAYHEM_DOCKER_REGISTRY/forallsecure/java-jazzer:latest duration: 90 project: mayhem-examples target: java-jazzer cmds: - cmd: /usr/bin/jazzer_driver --cp=/usr/bin/MayhemIt.jar --target_class=mayhemit.MayhemIt libfuzzer: true
以下が必要です。
- Docker がインストールされていること
- 有効なインターネット接続 (Docker Hub ベース イメージをプルするため)
ワン クリック テスト¶
下のボタンをクリックしてスタンドアロンの Java ターゲットのテストを開始します。最終確認ページに到達するまで [Next] をクリックし、[Start Run] をクリックします。
次のようなラン ページが表示されます。
Mayhem による libFuzzer Java ターゲットのテストを確認したので、次に、どのように libFuzzer Java ターゲットがビルドされたのかを順を追って説明します。
Jazzer を使用した LibFuzzer Java ターゲットのテスト¶
ファイル: java-jazzer.tgz
がインストールされて
上記の java-jazzer.tgz
をダウンロードして展開し、次のバグのある MayhemIt.java
プログラムを見てみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
2 つの関数 fuzzerInitialize
および fuzzerTestOneInput
があるのがわかります。fuzzerInitialize
関数は、任意の状態初期化処理を行うことを可能にし、fuzzerTestOneInput
は jazzer ファザーのエントリポイントとして機能し、テスト用にランダム値を挿入します。特に、入力 data
が "bug" の場合、キャッチされない例外の欠陥でプログラムがキャッシュします。
次に java-jazzer
がどのようにビルドされるかを見てみましょう。関連する Dockerfile
を見ると、以下のビルド プロセスがあるのがわかります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
- 行 1: 必要な java 依存関係を収集するため、
fuzzers/jazzer:0.9.1-openjdk11
ベース イメージがインポートされています。 - 行 2: Docker コンテナーに
MayhemIt.java
ソース ファイルがコピーされています。 - 行 5-10:
javac
コンパイラを使用してMayhemIt.jar
ファイルがコンパイルされています。 - 行 14: ビルドされた Docker イメージのデフォルト実行ファイルとして
--cp=/usr/bin/MayhemIt.jar
および--target_class=mayhemit.MayhemIt
パラメーター付きで/usr/bin/jazzer_driver
実行ファイルが設定されています。
次に、docker build
および docker push
コマンドを使用して、Docker イメージをビルドして Docker Hub レジストリにプッシュする必要があります。
次に、docker build
および docker push
コマンドを使用して、Docker イメージをビルドして Mayhem サーバーにプッシュする必要があります。$MAYHEM_DOCKER_REGISTRY
は、プライベートな Mayhem Docker レジストリの URL を表します。
docker build -t <DOCKERHUB_USERNAME>/java-jazzer .
docker push <DOCKERHUB_USERNAME>/java-jazzer
docker build -t $MAYHEM_DOCKER_REGISTRY/forallsecure/java-jazzer .
docker push $MAYHEM_DOCKER_REGISTRY/forallsecure/java-jazzer
Info
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>/java-jazzer
Docker イメージを検索します。Mayhemfile
が次のようになっていることを確認します。
新しく作成した Docker イメージをプライベートな Mayhem Docker レジストリに正常にプッシュしたら、Mayhem UI から新規ランを作成し、forallsecure/java-jazzer
Docker イメージを検索します。Mayhemfile
が次のようになっていることを確認します。
1 2 3 4 5 6 7 |
|
1 2 3 4 5 6 7 |
|
新規ラン作成フローの最終確認ページに到達するまで [Next] をクリックし、[Start Run] をクリックして Mayhem ランを実行します。次のようなラン ページが表示されます。
おめでとうございます! LibFuzzer Java ターゲットのテストが成功しました。
⚡ 現実的な演習: mayhemit-out-of-bounds
LibFuzzer Java ターゲットのコンパイルとテスト¶
キャッチされない例外の欠陥がある libFuzzer Java ターゲットのビルドおよびテスト方法がわかったところで、ソース コードを修正して配列境界外の欠陥を検出できるかどうかやってみましょう。
ファイル: mayhemit-out-of-bounds-unsolved.zip
手順
MayhemIt.java
ソース コードを変更し、最大長の制約およびインデックス境界外欠陥を追加します。
1 2 3 4 5 6 7 8 9 |
|
docker build
コマンドを使用してDockerfile
を再ビルドし、結果の Docker イメージを<DOCKERHUB_USERNAME>/java-libfuzzer-mayhemit-out-of-bounds
としてタグ付けします。docker push
コマンドを使用してパブリックな Docker Hub レジストリに<DOCKERHUB_USERNAME>/java-libfuzzer-mayhemit-out-of-bounds
Docker イメージをプッシュします。- Mayhem UI または Mayhem CLI を使用して
<DOCKERHUB_USERNAME>/java-libfuzzer-mayhemit-out-of-bounds
Docker イメージをファジングします。Mayhemfile
が適切に設定されていることを確認します。
docker build
コマンドを使用してDockerfile
を再ビルドし、結果の Docker イメージを$MAYHEM_DOCKER_REGISTRY/java/libfuzzer/mayhemit-out-of-bounds
としてタグ付けします。docker tag
およびdocker push
コマンドを使用してプライベートな Mayhem Docker レジストリに$MAYHEM_DOCKER_REGISTRY/java/libfuzzer/mayhemit-out-of-bounds
Docker イメージをプッシュします。- Mayhem UI または Mayhem CLI を使用して
$MAYHEM_DOCKER_REGISTRY/java/libfuzzer/mayhemit-out-of-bounds
Docker イメージをテストします。Mayhemfile
が適切に設定されていることを確認します。
🔍 確認mayhemit-out-of-bounds
LibFuzzer Java ターゲットのコンパイルとテスト¶
解答
模範解答: mayhemit-out-of-bounds-solved.zip
まず、fuzzerTestOneInput
関数をファジングしたとき、入力テスト ケース "bug" がインデックス境界外エラーを発生させるよう、インデックス境界外エラーのスニペットを追加します。これは、input.length() < 5
の場合にだけ if 文に進むからです。変数 x
に input.charAt(10)
を設定しようとすると、配列の境界外エラーが発生します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
次に、Dockerfile
と同じディレクトリで docker build
コマンドを実行し、結果の Docker イメージに <DOCKERHUB_USERNAME>/java-libfuzzer-mayhemit-out-of-bounds
というタグを付けます。
次に、Dockerfile
と同じディレクトリで docker build
コマンドを実行し、結果の Docker イメージに $MAYHEM_DOCKER_REGISTRY/java/libfuzzer/mayhemit-out-of-bounds
というタグを付けます。
docker build -f Dockerfile -t <DOCKERHUB_USERNAME>/java-libfuzzer-mayhemit-out-of-bounds .
docker build -f Dockerfile -t $MAYHEM_DOCKER_REGISTRY/java/libfuzzer/mayhemit-out-of-bounds .
次に、<DOCKERHUB_USERNAME>/java-libfuzzer-mayhemit-out-of-bounds
Docker イメージにタグを付けてパブリックな Docker Hub レジストリにプッシュします。
次に、$MAYHEM_DOCKER_REGISTRY/java/libfuzzer/mayhemit-out-of-bounds
Docker イメージにタグを付けてプライベートな Mayhem Docker レジストリにプッシュします。
docker push <DOCKERHUB_USERNAME>/java-libfuzzer-mayhemit-out-of-bounds
docker push $MAYHEM_DOCKER_REGISTRY/tutorial/java/libfuzzer/mayhemit-out-of-bounds
別の方法として、付属の Makefil を使用し、
MAYHEM_DOCKER_REGISTRY` 環境変数を設定して次のコマンドを実行することで、簡単に結果の Docker イメージをビルドし、プッシュすることもできます。
make build
make push
最後に、Mayhem UI または Mayhem CLI を使用して、アップロードされた <DOCKERHUB_USERNAME>/java-libfuzzer-mayhemit-out-of-bounds
Docker イメージに対して Mayhem ランを実行します。Mayhemfile
は次のようになっているはずです。
最後に、Mayhem UI または Mayhem CLI を使用して、アップロードされた $MAYHEM_DOCKER_REGISTRY/java/libfuzzer/mayhemit-out-of-bounds
Docker イメージに対して Mayhem ランを実行します。Mayhemfile
は次のようになっているはずです。
1 2 3 4 5 6 7 |
|
1 2 3 4 5 6 7 |
|
最終的なラン ページは次のように表示されるはずです。
おめでとうございます! Mayhem がインデックス境界外の欠陥を発見しました。スクラッチから libFuzzer Java ターゲットをビルドし、Mayhem を使用してバグを検出できました。
✏️ まとめと振り返り¶
このレッスンでは、Mayhem で libFuzzer Java ターゲットをファジングする方法を学びました。
学習内容
1. キャッチされない例外の欠陥がある libFuzzer Java ターゲットをコンパイルし、テストする。
-
ソース コードには次の欠陥が含まれているはずです:
1 2 3 4 5 6 7 8 9
if (input.length() >= 3) { if (input.charAt(0) == 'b') { if (input.charAt(1) == 'u') { if (input.charAt(2) == 'g') { throw new RuntimeException("Made it to the bug!"); } } } }
-
libFuzzer Java ターゲットをファジングするには、次の
Dockerfile
およびMayhemfile
を使用して Java プログラムを含む Docker イメージをビルドし、Mayhem でファジングを実行します。1 2 3 4 5 6 7 8 9 10 11 12 13 14
FROM fuzzers/jazzer:0.9.1-openjdk11 COPY MayhemIt.java . # Build MayhemIt.jar RUN mkdir -p build && \ javac -d build MayhemIt.java && \ cd build && \ jar cvf MayhemIt.jar * && \ mv MayhemIt.jar /usr/bin/MayhemIt.jar && \ rm -rf build # Set to fuzz! ENTRYPOINT [] CMD [ "/usr/bin/jazzer_driver", "--cp=/usr/bin/MayhemIt.jar", "--target_class=mayhemit.MayhemIt" ]
1 2 3 4 5 6 7
image: <DOCKERHUB_USERNAME>/java-jazzer:latest duration: 90 project: mayhem-examples target: java-jazzer cmds: - cmd: /usr/bin/jazzer_driver --cp=/usr/bin/MayhemIt.jar --target_class=mayhemit.MayhemIt libfuzzer: true
1 2 3 4 5 6 7
image: $MAYHEM_DOCKER_REGISTRY/forallsecure/java-jazzer:latest duration: 90 project: mayhem-examples target: java-jazzer cmds: - cmd: /usr/bin/jazzer_driver --cp=/usr/bin/MayhemIt.jar --target_class=mayhemit.MayhemIt libfuzzer: true
2. インデックス境界外の欠陥の欠陥がある libFuzzer Java ターゲットをビルドし、ファジングする。
-
ソース コードには次の欠陥が含まれているはずです:
1 2 3 4 5 6 7 8 9
if (input.length() >= 3 && input.length() < 5) { if (input.startsWith("b", 0)) { if (input.startsWith("u", 1)) { if (input.startsWith("g", 2)) { char x = input.charAt(10); } } } }
-
libFuzzer Java ターゲットをファジングするには、次の
Dockerfile
およびMayhemfile
を使用して Java プログラムを含む Docker イメージをビルドし、Mayhem でファジングを実行します。1 2 3 4 5 6 7 8 9 10 11 12 13 14
FROM fuzzers/jazzer:0.9.1-openjdk11 COPY MayhemIt.java . # Build MayhemIt.jar RUN mkdir -p build && \ javac -d build MayhemIt.java && \ cd build && \ jar cvf MayhemIt.jar * && \ mv MayhemIt.jar /usr/bin/MayhemIt.jar && \ rm -rf build # Set to fuzz! ENTRYPOINT [] CMD [ "/usr/bin/jazzer_driver", "--cp=/usr/bin/MayhemIt.jar", "--target_class=mayhemit.MayhemIt" ]
1 2 3 4 5 6 7
image: <DOCKERHUB_USERNAME>/java-libfuzzer-mayhemit-out-of-bounds:latest duration: 90 project: mayhem-examples target: mayhemit-out-of-bounds cmds: - cmd: /usr/bin/jazzer_driver --cp=/usr/bin/MayhemIt.jar --target_class=mayhemit.MayhemIt libfuzzer: true
1 2 3 4 5 6 7
image: $MAYHEM_DOCKER_REGISTRY/java/libfuzzer/mayhemit-out-of-bounds:latest duration: 90 project: mayhem-examples target: mayhemit-out-of-bounds cmds: - cmd: /usr/bin/jazzer_driver --cp=/usr/bin/MayhemIt.jar --target_class=mayhemit.MayhemIt libfuzzer: true