uchan note

プログラミングや電子工作の話題を書きます

ファジングツール syzkaller は何を検査するものなの?

OSSセキュリティ技術の会 第七回勉強会 に参加してきました。 syzkaller が何を,どうやって検査するのか,原理を忘れないうちにメモします。

ファジング

ファジングはプログラム解析手法の 1 つです。入力値をいろいろ変えて与えてみてバグが発生するかどうかをテストします。 バグ=脆弱性バグではありませんが,バグがあれば脆弱性に繋がる可能性があり,脆弱性を見つけたい人たち(防御側および攻撃側)に人気があるそうです。

「入力」にはさまざまなものがあり得ます。Linuxコマンドラインツールであればコマンドライン引数や標準入力,ファイル,ネットワークなどが入力経路として一般的かと思います。 今回の OSS セキュリティ技術の会で取り上げられていた Linux カーネルに対するファジングツールである syzkaller(濁らせずに「シスコーラー」と読むらしい)は,Linuxシステムコールを色々な引数で呼んでみてバグを検査します。

システムコールとファジング

Linuxシステムコールは 300 個程度あり,それぞれが 1 つから 6 つの引数を取ります。 一般的には,システムコールの引数をランダムに与えて実行してみると成功するか失敗しますが,いずれにしてもカーネルパニックになるのではなく,システムコールの呼び出し元プロセスに制御が戻ることになるでしょう。 例えば open() に存在しないファイルパスを指定したら ENOENT になるはずです。

しかし,中には特定の引数値で呼び出すとカーネルパニックや,カーネルパニックに至らないまでも不正なメモリ書き込みなどの良くない症状が現れることがあります。 syzkaller が見つけようとしているのはそのようなシステムコールと引数の組み合わせです。

分岐命令

if や for,switch,3 項演算子 など,プログラムには多数の分岐命令が存在します。 未知のバグは普段は通らない実行パスに潜んでいる可能性が高いということで,syzkaller は実行パスの網羅性を高めるように入力値を変化させる努力をしているようです。

その手法の詳細までは調べていませんが,おそらく,入力値を変異させてみて実行パスの網羅性が上がった変異を「良い変異」ということで次回以降も採用してみる,みたいなことをしているんじゃないでしょうか。 なんだか,成績が良かった遺伝子を残して進化させる「遺伝的アルゴリズム」みたいですね。

このように,より多くの実行パスを通るように入力値を変えてプログラムを実行しまくるのがファジングの主目的です。

バグ検出

実行パスを変えただけではバグを効率的に捉えることができません。 もちろん,カーネルパニックのような重大な症状が出れば簡単にバグを認識できるでしょう。 しかし,その瞬間にはエラーにならないような些細なバグ,例えば壊れたポインタを用いたメモリアクセスとかバッファオーバーランなどは検出が遅れるか,まったく検出できない可能性があります。

そこで,ファジングで実行パスの網羅性を上げつつ他のバグ検出手法を併用することになります。 勉強会の 1 個目の発表 Linux カーネルのファジングツール syzkaller/syzbot によれば,syzkaller では KASAN や UBSAN などの各種サニタイザーを用いてバグ検出を行っているようです。

まとめ

ファジングとは入力値(syzkaller であればシステムコールの引数値)を変化させてみてバグを検出する手法です。 入力値を変化させることでバグを含んだ実行パスを通るようにすることを期待しており,syzkaller では実行パスの網羅率を上げる工夫が組み込まれています。 実行パスを増やしただけではバグの検出が漏れる可能性が高いです。各種サニタイザーを使えばより多くのバグ候補を検出できます。