はじめに
ドローンのソフトウェア開発しています。イチノです。
Atheris を触ったのでメモ書きです。 Atheris は、プログラムの実行経路に応じたテスト用データを生成する Fuzzing ツールです。
Fuzzing とは、プログラムに問題の有りそうなデータやランダムなデータを渡して、プログラムのバグを探す脆弱性検査です。Fuzzing で WebRTC の脆弱性を発見したなんていう事例も有ります。
WebRTC Security, Fuzzing, and more! - YouTube
Fuzzing に関する詳しい説明は IPA の資料をご覧ください。
脆弱性対策:ファジング:IPA 独立行政法人 情報処理推進機構
Atheris のインストールと使い方を以下に記載しています。
インストール
Atheris は、 Linux, macOS に対応しています。
pip3 install atheris
Atheris の準備
例として、bytes を UTF-8 の str へ変換する処理を Fuzzing します。 来たものを UTF-8 へ変換するコードをそのまま実装したものがこちら。 converter.py として保存します。
# converter.py def bytes_to_utf_8(b): return b.decode('utf_8')
Fuzzing の検証コードは、こちらです。 Atheris から渡されたデータを converter.bytes_to_utf_8 へ渡す処理を TestConverter として実装しています。 fuzzing.py として保存します。
# fuzzing.py import atheris import sys # Atheris によるカバレッジを利かしたいモジュールを import with atheris.instrument_imports(): import converter # Fuzzing 対象へデータを受け渡し def TestConverter(data): return converter.bytes_to_utf_8(data) atheris.Setup(sys.argv, TestConverter) # Fuzzing の開始 atheris.Fuzz()
Atheris による Fuzzing の実行
fuzizng.py を実行すると、次のような結果が出ます。
$ python3 fuzzing.py INFO: Instrumenting converter INFO: Instrumenting base64 INFO: Instrumenting struct INFO: Using built-in libfuzzer WARNING: Failed to find function "__sanitizer_acquire_crash_state". WARNING: Failed to find function "__sanitizer_print_stack_trace". WARNING: Failed to find function "__sanitizer_set_death_callback". INFO: Running with entropic power schedule (0xFF, 100). INFO: Seed: 692311049 INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes INFO: A corpus is not provided, starting from an empty corpus #2 INITED cov: 1 ft: 1 corp: 1/1b exec/s: 0 rss: 35Mb === Uncaught Python exception: === UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd1 in position 0: unexpected end of data Traceback (most recent call last): File "fuzzing.py", line 10, in TestConverter return converter.bytes_to_utf_8(data) File "/home/user/converter.py", line 4, in bytes_to_utf_8 return b.decode('utf_8') ==14145== ERROR: libFuzzer: fuzz target exited SUMMARY: libFuzzer: fuzz target exited MS: 4 ChangeByte-ChangeBit-CrossOver-ChangeByte-; base unit: adc83b19e793491b1c6ea0fd8b46cd9f32e592fc 0xd1, \321 artifact_prefix='./'; Test unit written to ./crash-c314f8c1fa13e1afa11c8716c7bce6dbf02d09aa Base64: 0Q==
こんな感じで、問題の有るデータを crash-*
というファイルへ保存しておいてくれます。
見つかったデータに対して修正コードを書いてから、修正します。
例えば、 decode の例外発生時は空文字を返す修正を converter.py に施します。
# converter.py def bytes_to_utf_8(b): try: return b.decode('utf_8') except UnicodeDecodeError: return ''
再度、python3 fuzzing.py
を実行すると、エラーは発生しなくなります。
さいごに
Atheris を使って Fuzzing を実施してバグを引き起こすデータを発見できました。また、見つかったデータに対して有効な修正を施せたことを確認できました。
オプティムでは、ロボティクス事業や様々な事業で活躍していただくエンジニアを募集中です。ご応募お待ちしております。