More Related Content
More from Tetsuya Hasegawa (20)
ファジングでOSS、3rdPartyのバグを見つけよう
- 1. ファジング(Fuzzing)を実践、プロジェクト適用する人向けの資料です。
ファジングでOSS・3rdPartyのバグを見つけよう
1. ファジングとは 1
1.1 ファジングツール 1
1.1.1 ファズ 1
1.1.2 ファジングツール 1
1.2 ファジングの効果 2
1.3 ファジングの課題 2
2. 代表的なファジングツール 2
3. ファジング実践 3
3.1 AFL 3
3.1.1 環境構築 3
3.1.2 ファジング 3
3.1.3 結果確認 5
3.2 OSS-Fuzz 7
3.2.1 環境構築 7
新規プロジェクトをOSS-Fuzzに統合する 7
ローカル環境でお試し 8
参考文献 9
あとがき 10
1. ファジングとは
検査対象のソフトに様々なデータ(Fuzz)を入力し、その挙動を確認することでバグや脆弱性を検出するブラックボックステス
トの一つである。
ファジングでは例えば、ソフトやコンポーネントに極端に長い文字列や通常用いないような制御コードを入力し挙動を観察す
る。その結果、予期しない異常動作、再起動等が発生した場合に何らかの問題がある可能性が高いと判断できる。
1.1 ファジングツール
1.1.1 ファズ
ファズとは試験対象のソフトに入力する「問題を引き起こしそうなデータ」である。ファズはファジング対象によって様々なもの
がある。例えば、サーバー向けの場合はパケット、画像処理ソフト向けの場合は画像になる。
1.1.2 ファジングツール
ファジングはツールを用いて行うことが一般的である。ファジングツール(ファザーとも言う)は主に3つの機能を備えてい
る。「①ファズの生成」、「②ファズの入力」、「③ファジング対象の挙動確認」である。ファジングツールでは①~③を自動的
に繰り返し行うことでバグを検出する。
1
- 4. ● 試験対象がライブラリの場合
試験対象のライブラリをラップするテストハーネスから間接的に試験する。
● ソースコードがない場合
afl-QEMU上でバイナリを実行する。
● 試験対象ソフトが複数の引数を必要とする場合
ファズを分割する or 一つの引数を試験対象にして他を固定値にする。
ファズの分割が若干複雑なため、後者がおすすめ。
(参考)ファズの分割
https://github.com/google/fuzzing/blob/master/docs/split-inputs.md
マルチスレッドやマスター/スレーブによる並列実行も可能。
試験対象のソースコードがあり、実行形式の場合の基本的な手順を以下に示す。
ビルドして
# CC=/usr/local/bin/afl-gcc CFLAGS="AFL_HARDEN=1” ./configure --disable-shared
# make clean all
ファジングする。コマンドライン引数やファイルを入力に指定することもできる。
# afl-fuzz -i testcase_dir -o findings_dir /path/to/program [...params...]
# afl-fuzz -i testcase_dir -o findings_dir /path/to/program @@
testcase_dirには適当なテストケース(遺伝的アルゴリズムのシード)を入れておく。
「echo -n '' > testcase_dir/hoge」 でも問題は無いが、適切なシードを入れておいたほうがよい。
シードの例は「afl-2.52b/testcases」にある。
testcases/
├── archives
│ ├── common
│ └── exotic
├── images
├── multimedia
├── others
│ ├── js
│ │ └── small_script.js
│ │ if (1==1) eval('1');
│ ├── sql
│ │ └── simple_queries.sql
│ │ create table t1(one smallint);
│ │ insert into t1 values(1);
│ │ select * from t1;
│ ├── text
│ └── xml
│ └── small_document.xml
└── README.testcases
例)dhclientのファジングをする。
# /home/hasegawa/dhcp/dhcp-4.3.6/client
# mkdir test_in
# echo -n 'hoge' > test_in/hello
# CC=/usr/local/bin/afl-gcc CFLAGS="AFL_HARDEN=1” ./configure --disable-shared
# make clean all
4
- 5. # afl-fuzz -i test_in -o test_out ./dhclient
途中経過の画面を以下に示す。
全部終わるのに数日以上かかるため下記がある程度増えたら止める。
進捗状況:favored paths(重要なパス)やexec speed(消化スピード)、fuzzing strategy yields
バグ状況:crashed、hang
各項目の詳細はREADME参照。
3.1.3 結果確認
プロットして結果を確認して全体像を見る。
# afl-plot test_out/ plot/
5
- 6. クラッシュ解析ツールを使う。
# cp afl-***/experimental/crash_triage/triage_crashes.sh .
# ./triage_crashes.sh test_out/ dhclient
NGになった出力を確認する。
この例だと特殊文字でハングしているようです。
# cd test_out/
# ls -1
id:000000,src:000000,op:arith8,pos:1,val:+14
id:000001,src:000000,op:arith8,pos:1,val:+25
id:000002,src:000000,op:arith8,pos:2,val:-25
id:000003,src:000000,op:arith8,pos:2,val:+26
# cat “id:000003,src:000000,op:arith8,pos:2,val:+26”
ho�eroot
# hexdump “id:000003,src:000000,op:arith8,pos:2,val:+26”
0000000 6f68 6581
0000004
# cat “id:000003,src:000000,op:arith8,pos:2,val:+26” | ./dhclient
⇒事象再現
6
- 8. FROM gcr.io/oss-fuzz-base/base-builder #clangツールチェーンを使用するベースイメージ
MAINTAINER xxxxx@yyyy.jp #代表者
RUN set -e;
apt-get update &&
apt-get -y --no-install-recommends install libicu-dev
apt-utils git curl wget unzip tar;
apt-get -y clean #依存関係をインストール
# Get *your* source code here. #必要なソースをチェックアウト
RUN git clone --depth 1 --single-branch --branch master
https://github.com/xxx/yyy.git
WORKDIR yyyy #build.shのカレントディレクトリ
COPY build.sh $SRC/ #build.shのコピー
3. プロジェクト名/build.sh を作成する。
ファジング対象をビルドするスクリプト。build.shはDockerfileからビルドされたイメージ内で実行される。
#!/bin/bash -eu
./configure
make clean
make -j$(nproc) all
cp a.out $OUT/ #アーティファクトを格納するディレクトリ。バイナリやファズのシード等もここに入れる。
● ローカル環境でお試し
“infra/helper.py”を使ってローカル環境でOSS-Fuzzできる。
GCP、JenkinsやClusterFuzzと統合しないでOSS-Fuzzだけ使うイメージ。
#cloneして、自分のプロジェクトをprojectに追加(例:libxml2をファジングする)
8
- 9. #git clone https://github.com/google/oss-fuzz.git
# cp -rf /home/hasegawa/libxml2 oss-fuzz/project
# cd oss-fuzz
# PROJECT_NAME=libxml2
#Dockerビルドして
# python infra/helper.py build_image $PROJECT_NAME
# python infra/helper.py build_fuzzers --sanitizer address --sanitizer coverage
$PROJECT_NAME
#ファザーの実行
# python infra/helper.py run_fuzzer $PROJECT_NAME libxml2_xml_read_memory_fuzzer
#カバレッジのチェック(-sanitizerにcoverageを設定している場合)
python infra/helper.py coverage $PROJECT_NAME libxml2_xml_read_memory_fuzzer
参考文献
文献1 Google, Google Security Blog
https://security.googleblog.com/2019/02/open-sourcing-clusterfuzz.html
文献2 IPA, 脆弱性対策:ファジング
https://www.ipa.go.jp/security/vuln/fuzzing.html
文献3 IPA, 製品の品質を確保する「セキュリティテスト」に関するレポート
https://www.ipa.go.jp/files/000009390.pdf
文献4 Google, Fuzzing
https://github.com/google/fuzzing/tree/master/docs
9