ファジィなファジング考

「ファジィ家電」って覚えていますか?たぶん、ファジィ理論に基いたファジイ制御をしてるってことで、洗濯機とか出てましたね。原理はよくわからんけど、なんか機械的にやるんじゃなくて、AI的に、「あいまい」に、なんかいい感じに洗濯してくれるとか。「マイナスイオン」とかと同様、ただの流行ではあったんでしょうな。それとも今は普通になっちゃったからあえて言わないのか。あ、理系出身のくせに「マイナスイオン」を標榜する製品開発に加担してたやつには、「プラスイオン」の天罰が下るであろう!

…閑話休題。

で、最近(でもないか)、セキュリティテストとしてファジングテストがもてはやされてますよね。自動車業界でも、某メーカーが下請けに、ファジングテストの実施を義務付けているとかなんとか。でも、個人的にはそういった風潮は行き過ぎというか、なんかファジング、過大評価されてね?と危惧を感じてしまう訳です。いや、もちろん一定の効果があるのは認めます。が、出荷前検査でそれをパスすればOKというのは、それは違うんじゃないの?ってことです。

当然、ただの言いがかりではなく、根拠のある話ですので、その根拠について考察していきましょう。

そもそも、ファジングテストとは何か?何をテストして(見つけて)くれるのか?
ファジングとは、データを大量に投入して、機械的にテストをする手法です。もともとセキュリティテストのための手法ではなく、単純にバグを発見するテクニックとして以前から使われていました。基本的にはブラックボックステスト、つまり、データを入力して動かし、その出力を見て正常かどうか判断します。
ということは、出力が「異常」かどうか判断できないと、テストが難しくなります。これ、あとで試験に出るので覚えておいてください(試験とテストがまぎらわしい)。
要は、プログラムが予測してない入力が来た時に、ちゃんとエラー処理してないと、おかしなことになる。それを、予測しないようなデータ(ファズデータ=「てきとー」なデータ?)をとにかくたくさん投入して、人海ならぬデータ海戦術で見つけだす、と。

ここで、ファジング成功の鍵となる大きなポイントは、「どうやって、そのファズデータを大量に生成するの?」です。ちゃんとバグによる異常なふるまいをつつき出してくれるようなデータでないといけない。このようなデータの生成方法としては、「ランダム生成」や、「突然変異」などがあります。「突然変異」の一手法であるビットフリッピング(BF)は、文字(やビット)をちょっと別の文字に置きかえるというもの。
例えば、「ソニー」を「ソニ一」に変えるみたいな。
…すみません。キム兄のネタ分かりにくいですね。もとい
「fuzz」という文字列を一部変えて「fuz_」にするようなものです。この入力を与えて読み取る側はおそらく文字列をパースするんですが、そこで変な文字列が入ってきたときにエラー処理でヘクると、落ちちゃったりする。落ちてくれれば、ファジングテストで見つけることができる、という訳です。

これが、普通のバグ探しならある程度うまくいくと思うんですが、セキュリティの脆弱性をテストする場合、意図的に脆弱性をつく攻撃ができるデータを入力しないと、挙動がおかしくなってくれない。つまりさっきのBFみたいなやり方では、脆弱性をつく攻撃が簡単にはできないのです。もちろん、バッファオーバーフローを見つけたければ、単純にバッファサイズをあふれさせるデータを入力させれば、落ちてはくれるかもしれません。でも、シェルコードを動かして「任意のプログラム実行」までいくためには、相当人為的にデータを工夫しないと難しいですよね。Web脆弱性検査やる人なら分かっていただけるかと思いますが、例えばSQLインジェクションを、HTTPリクエストに対するレスポンス(出力)で見てても、成功したかどうか分からないんじゃありません?

「ファジングがブラックボックスである」ことによる問題はもう一つあって、それはカバレッジ問題です。カバレッジとは、「そのテストによって、プログラムのあらゆるふるまいをカバーできたか」という指標で、「ソースプログラムで通ってないとこないよね」でもいいですが、なにせブラックボックスは中を見ないので、そもそも難しい。そしてファジングも、てきとーなデータを数撃っても、敵を全員倒せるかは誰にもわからない。
そんなファジングの弱点を克服しようとする試みも出てきていて、例えばシンボリック実行を使い、テストデータ候補を導出するという研究があります。シンボリック実行ツールはプログラムの指定した個所に到達するための入力値を算出してくれます。この技術は元々ソフトウェア業界ではあったものですが、これを使うと、プログラム中でフラグを出力している個所を指定して、求める入力を出してくれるので、CTF業界では知られてきていますね。そのシンボリック実行を使って、ある程度カバレッジを満たすようなテストデータを生成できるということなんですが…そこまでご親切にデータ生成したものって、はたしてそれは「ファジング」なの?という疑問は残ります…だって全然「あいまい」じゃないじゃない。

で、ですね(ここからが本題)。ファジングのことを書こうと思ったのは、先日SCIS2020で、車載に対するファジングの発表があったからです。

車載ECUへのファジング時におけるサイドチャネル情報を用いた異常動作検出手法
◎谷口亮介(立命館大学)、吉田康太(立命館大学)、久保田貴也(立命館大学)、汐崎充(立命館大学)、藤野毅(立命館大学)

車載というか、車の中の個々のコンピュータユニットであるECUに対するファジングで、さっき言ったように攻撃ができても反応がない場合に対する対策として、サイドチャネルを検出し、正常時との違いによりpositive/negativeを判定するというもの。これ、個人的には面白い着眼点だと思いました。うまくいけば、一見反応がないものでも攻撃成功してるか分かったらすごいじゃないですか。発表で扱っていたのはバッファオーバーフローだけですが、もし、仮に他の脆弱性でも同様にできたら、可能性が広がりそうです。
でも1個だけ気になる点があって…これ、車載のECUが対象なんですよね。質問時間がなくしそこねたんですが、たぶん個々のECUは\に対してファジングかけるってことですよね。ECUって、車1台につき100個以上あるんですよね。そのそれぞれのECUの特性をあらかじめ全部おさえた上で、更にファジング(大量のデータ…)で確認するのは、手間が大変そう…

ところで、完全余談ですが、タイトルの「ファジィ」の小さい「ィ」の使い方は、日本語では読み方が規定されていないのですが、こっちの方がなじみがあると思ったので使いました。個人的にこういうのはあまり使わないようにしてますが…最近はこういうの指摘する日本語ポリスの方もいなくなっちゃいましたかねえ。ガンダムの富野監督がよく使うイメージがあります。リ・ガズィやファ・ユイリィとかはまだわからんでもないけど、「ムーンレィス」の読み方は、よくわからん…