上級
AFL インストゥルメンテーション付き Rust ターゲット¶

テスト対象は Google の AFL を使用してインストゥルメントされた Rust ターゲットですか? このレッスンでは、AFL インストゥルメンテーション付きで Rust ターゲットをビルドし、結果のバイナリを Mayhem でテストする方法を順を追って説明します。
学習時間の目安: 15 分
このレッスンを終了すると、以下のことができるようになります。
- 不適切な入力検証の欠陥がある AFL インストゥルメンテーション付き Rust ターゲットをコンパイルし、ファジングする。
- インデックス境界外の欠陥がある AFL インストゥルメンテーション付き Rust ターゲットをコンパイルし、ファジングする。
レッスンを駆け足で
始める前に前提条件を確認します。
-
rust-afl.tgz をダウンロードし、
rust-aflDocker イメージをビルドし、指定された Docker レジストリにプッシュします。docker build -t <DOCKERHUB_USERNAME>/rust-afl . docker push <DOCKERHUB_USERNAME>/rust-afldocker build -t $MAYHEM_DOCKER_REGISTRY/forallsecure/rust-afl . docker push $MAYHEM_DOCKER_REGISTRY/forallsecure/rust-afl -
Mayhem UI または Mayhem CLI で次の Mayhemfile を使用して
forallsecure/rust-aflDocker イメージに対して Mayhem ランを実行します。1 2 3 4 5 6 7
image: <DOCKERHUB_USERNAME>/rust-afl:latest duration: 90 project: mayhem-examples target: rust-afl cmds: - cmd: /mayhemit/target/debug/mayhemit afl: true1 2 3 4 5 6 7
image: $MAYHEM_DOCKER_REGISTRY/forallsecure/rust-afl:latest duration: 90 project: mayhem-examples target: rust-afl cmds: - cmd: /mayhemit/target/debug/mayhemit afl: true
以下が必要です。
- Docker がインストールされていること
- 有効なインターネット接続 (Docker Hub ベース イメージをプルするため)
ワン クリック テスト¶
下のボタンをクリックして AFL インストゥルメンテーション付き Rust ターゲットのテストを開始します。最終確認ページに到達するまで [Next] をクリックし、[Start Run] をクリックします。
次のようなラン ページが表示されます。
Mayhem による AFL インストゥルメンテーション付き Rust ターゲットのテストを確認したので、次に、どのように Rust ターゲットがビルドされたかを順を追って説明します。
AFL インストゥルメンテーション付き Rust ターゲットのテスト¶
ファイル: rust-afl.tgz
上記の rust-afl.tgz をダウンロードして展開し、次のバグのある mayhemit.rs プログラムを見てみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | |
ソース ファイルの先頭でプログラムに外部クレート afl ライブラリがインポートされ、3 つの主要な関数 main および fuzz! があることがわかります。
main 関数はプログラムへのエントリポイントして機能し、afl クレートによって提供される fuzz! 関数が含まれています。この関数は、標準入力からバイト列を読み取ってロジックにバイト列を渡します。特に、バイト列が "bug" である場合、abort() 関数が初期化され、不適切な入力検証の欠陥を発生させます。
次に rust-afl がどのようにビルドされるかを見てみましょう。関連する Dockerfile を見ると、以下の処理があるのがわかります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
- 行 1: 必要な Rust 依存関係を収集するため、
rust:1.44-busterベース イメージがインポートされています。 - 行 2:
aflクレート ライブラリがインストールされています。 - 行 3: Docker コンテナーに
mayhemit.rsソース ファイルがコピーされています。 - 行 4-9: (
aflクレートによって提供される) AFL cargo サブコマンドが使用され、mayhemit.rsソース コードがmayhemitRust 実行ファイルにコンパイルされています。 - 行 14: ビルドされた Docker イメージのデフォルト実行ファイルとして
/mayhemit/target/debug/mayhemit実行ファイルが定義されています。
次に、docker build および docker push コマンドを使用して、Docker イメージをビルドして Docker Hub にプッシュする必要があります。
次に、docker build および docker push コマンドを使用して、Docker イメージをビルドして Mayhem サーバーにプッシュする必要があります。$DOCKER_REGISTRY は、内部的な Mayhem Docker レジストリの URL を表します。
docker build -t <DOCKERHUB_USERNAME>/rust-afl .
docker push <DOCKERHUB_USERNAME>/rust-afl
docker build -t $MAYHEM_DOCKER_REGISTRY/forallsecure/rust-afl .
docker push $MAYHEM_DOCKER_REGISTRY/forallsecure/rust-afl
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>/rust-afl Docker イメージを検索します。Mayhemfile が次のようになっていることを確認します。
新しく作成した Docker イメージをプライベートな Mayhem Docker レジストリに正常にプッシュしたら、Mayhem UI から新規ランを作成し、forallsecure/rust-afl Docker イメージを検索します。Mayhemfile が次のようになっていることを確認します。
1 2 3 4 5 6 7 | |
1 2 3 4 5 6 7 | |
Note
ファイル入力を使用してターゲットをファジングするよう Mayhem に指示する @@ などのパラメーターなしで /mayhemit/target/debug/mayhemit が cmd に設定されていることを確認します。これは、Rust の afl クレートが標準入力だけを使用してファジングを行うからです。詳細については Rust Fuzz Book を参照してください。
新規ラン作成フローの最終確認ページに到達するまで [Next] をクリックし、[Start Run] をクリックして Mayhem ランを実行します。次のようなラン ページが表示されます。
おめでとうございます! Mayhem での AFL インストゥルメンテーション付き Rust ターゲットのテストが成功しました。
⚡ 現実的な演習: mayhemit-out-of-bounds AFL インストゥルメンテーション付き Rust ターゲットのコンパイルとテスト¶
不適切な入力検証の欠陥がある Rust ターゲットのビルドおよびテスト方法がわかったところで、ソース コードを修正してインデックス境界外の欠陥を検出できるかどうかやってみましょう。
ファイル: mayhemit-out-of-bounds-unsolved.zip
手順
mayhemit.rsソース コードを変更して最大長の制約を追加し、次のようにインデックス境界外欠陥を追加します。
1 2 3 4 5 6 7 8 9 10 11 12 | |
docker buildコマンドを使用してDockerfileを再ビルドし、結果の Docker イメージを<DOCKERHUB_USERNAME>/rust-afl-mayhemit-out-of-boundsとしてタグ付けします。docker pushコマンドを使用してパブリックな Docker Hub レジストリに<DOCKERHUB_USERNAME>/rust-afl-mayhemit-out-of-boundsDocker イメージをプッシュします。- Mayhem UI または Mayhem CLI を使用して
<DOCKERHUB_USERNAME>/rust-afl-mayhemit-out-of-boundsDocker イメージをファジングします。Mayhemfileが適切に設定されていることを確認します。
docker buildコマンドを使用してDockerfileを再ビルドし、結果の Docker イメージを$MAYHEM_DOCKER_REGISTRY/rust-afl-mayhemit-out-of-boundsとしてタグ付けします。docker pushコマンドを使用してプライベートな Mayhem Docker レジストリに$MAYHEM_DOCKER_REGISTRY/rust-afl-mayhemit-out-of-boundsDocker イメージをプッシュします。- Mayhem UI または Mayhem CLI を使用して
$MAYHEM_DOCKER_REGISTRY/rust-afl-mayhemit-out-of-boundsDocker イメージをテストします。Mayhemfileが適切に設定されていることを確認します。
🔍 確認mayhemit-out-of-bounds AFL インストゥルメンテーション付き Rsut ターゲットのコンパイルとテスト¶
解答
模範解答: mayhemit-out-of-bounds-solved.zip
まず、fuzz! 関数をファジングしたとき、入力テスト ケース "bug" がインデックス境界外エラーを発生させるよう、最大長の制約 data.len() < 5 および誤った呼び出し data[10] を追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
次に、Dockerfile と同じディレクトリで docker build コマンドを実行し、結果の Docker イメージに <DOCKERHUB_USERNAME>/rust-afl-mayhemit-out-of-bounds というタグを付けます。
次に、Dockerfile と同じディレクトリで docker build コマンドを実行し、結果の Docker イメージに $MAYHEM_DOCKER_REGISTRY/rust-afl-mayhemit-out-of-bounds というタグを付けます。
docker build -f Dockerfile -t <DOCKERHUB_USERNAME>/rust-afl-mayhemit-out-of-bounds .
docker build -f Dockerfile -t $MAYHEM_DOCKER_REGISTRY/rust-afl-mayhemit-out-of-bounds .
次に、$MAYHEM_DOCKER_REGISTRY/rust-afl-mayhemit-out-of-bounds Docker イメージにタグを付けてパブリックな Docker Hub レジストリにプッシュします。
次に、$MAYHEM_DOCKER_REGISTRY/rust-afl-mayhemit-out-of-bounds Docker イメージにタグを付けてプライベートな Mayhem Docker レジストリにプッシュします。
docker push <DOCKERHUB_USERNAME>/rust-afl-mayhemit-out-of-bounds
docker push $MAYHEM_DOCKER_REGISTRY/rust-afl-mayhemit-out-of-bounds
別の方法として、付属の Makefil を使用し、MAYHEM_DOCKER_REGISTRY` 環境変数を設定して次のコマンドを実行することで、簡単に結果の Docker イメージをビルドし、プッシュすることもできます。
make build
make push
最後に、Mayhem UI または Mayhem CLI を使用して、アップロードされた <DOCKERHUB_USERNAME>/rust-afl-mayhemit-out-of-bounds Docker イメージに対して Mayhem ランを実行します。Mayhemfile は次のようになっているはずです。
最後に、Mayhem UI または Mayhem CLI を使用して、アップロードされた $MAYHEM_DOCKER_REGISTRY/rust-afl-mayhemit-out-of-bounds Docker イメージに対して Mayhem ランを実行します。Mayhemfile は次のようになっているはずです。
1 2 3 4 5 6 7 | |
1 2 3 4 5 6 7 | |
最終的なラン ページは次のように表示されるはずです。
おめでとうございます! Mayhem がインデックス境界外の欠陥を発見しました。スクラッチからベース実行ファイル AFL インストゥルメンテーション付き Rust ターゲットをビルドし、Mayhem を使用してバグを検出できました。
✏️ まとめと振り返り¶
このレッスンでは、AFL インストゥルメンテーション付き Rust ターゲットを Mayhem でファジングする方法を学びました。
学習内容
1.不適切な入力検証の欠陥がある AFL インストゥルメンテーション付き Rust ターゲットをビルドし、テストする。
-
ソース コードには次の欠陥が含まれているはずです:
1 2 3 4 5 6 7 8 9 10 11
fn main() { fuzz!(|data: &[u8]| { if data[0] == 'b' as u8 { if data[1] == 'u' as u8 { if data[2] == 'g' as u8 { process::abort(); } } } }); } -
AFL インストゥルメンテーション付き Rust ターゲットをファジングするには、次の
DockerfileおよびMayhemfileを使用して Rust プログラムを含む Docker イメージをビルドし、Mayhem でファジングを実行します。1 2 3 4 5 6 7 8 9 10 11 12 13 14
FROM rust:1.44-buster as rust-target RUN cargo install afl --version 0.7.0 COPY mayhemit.rs . RUN export USER=root && \ cargo new mayhemit && \ cd mayhemit && \ mv /mayhemit.rs src/main.rs && \ echo afl = '"0.4"' >> Cargo.toml && \ cargo afl build RUN mkdir /testsuite && echo seed > /testsuite/seed # Set to fuzz! ENTRYPOINT ["cargo", "afl", "fuzz", "-i", "/tmp", "-o", "/out"] CMD ["/mayhemit/target/debug/mayhemit"]1 2 3 4 5 6 7
image: <DOCKERHUB_USERNAME>/rust-afl:latest duration: 90 project: mayhem-examples target: rust-afl cmds: - cmd: /mayhemit/target/debug/mayhemit afl: true1 2 3 4 5 6 7
image: $MAYHEM_DOCKER_REGISTRY/forallsecure/rust-afl:latest duration: 90 project: mayhem-examples target: rust-afl cmds: - cmd: /mayhemit/target/debug/mayhemit afl: true
2.インデックス境界外の欠陥がある AFL インストゥルメンテーション付き Rust ターゲットをビルドし、テストする。
-
ソース コードには次の欠陥が含まれているはずです:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
fn main() { fuzz!(|data: &[u8]| { if data.len() >= 3 && data.len() < 5 { if data[0] == 'b' as u8 { if data[1] == 'u' as u8 { if data[2] == 'g' as u8 { let x; x = data[10]; } } } } }); } -
AFL インストゥルメンテーション付き Rust ターゲットをファジングするには、次の
DockerfileおよびMayhemfileを使用して Rust プログラムを含む Docker イメージをビルドし、Mayhem でファジングを実行します。1 2 3 4 5 6 7 8 9 10 11 12 13 14
FROM rust:1.44-buster as rust-target RUN cargo install afl --version 0.7.0 COPY mayhemit.rs . RUN export USER=root && \ cargo new mayhemit && \ cd mayhemit && \ mv /mayhemit.rs src/main.rs && \ echo afl = '"0.4"' >> Cargo.toml && \ cargo afl build RUN mkdir /testsuite && echo seed > /testsuite/seed # Set to fuzz! ENTRYPOINT ["cargo", "afl", "fuzz", "-i", "/tmp", "-o", "/out"] CMD ["/mayhemit/target/debug/mayhemit"]1 2 3 4 5 6 7
image: <DOCKERHUB_USERNAME>/rust-afl-mayhemit-out-of-bounds:latest duration: 90 project: mayhem-examples target: mayhemit-out-of-bounds cmds: - cmd: /mayhemit/target/debug/mayhemit afl: true1 2 3 4 5 6 7
image: $MAYHEM_DOCKER_REGISTRY/rust-afl-mayhemit-out-of-bounds:latest duration: 90 project: mayhem-examples target: mayhemit-out-of-bounds cmds: - cmd: /mayhemit/target/debug/mayhemit afl: true

