バンドルカードに Fuzzing してみた

これはカンム Advent Calendar 2020 の20日目の記事です。昨日は achiku の 2020年をesaで振り返る でした。

今秋行われた Go Conference'20 in Autumn SENDAI にて ymotongpoo 氏の Goにおけるfuzzingとproperty based testing というトークを聞いて、自社で運用しているサービスに適用してみたいなと思い試してみました。

カンムは バンドルカード というサービスを提供しています。いわゆるカードなのですが、そのサーバーはHTTPではないプロトコルをしゃべります。今回はこのサーバーに Fuzzing してみます。プロトコルの詳細は同僚の hiroakis が Builderscon で行った発表の資料に詳しいので興味があればそちらを御覧ください: クレジットカードの通信プロトコル ISO8583 と戦う

Fuzzing とは何かは Wikipedia をご参照ください: ファジング

やる

今回は dvyukov/go-fuzz を使います。本当はネットワーク越しに fuzz を与えるのが理想ですが、めんどくさかったのでとりあえずプロトコルパーサーに fuzz を食わせる形にしました。

シンプルに以下のようなFuzz関数をパースする関数と同じパッケージに定義しました(本当はもう少し前処理が必要だったりした)。あとは go-fuzz-build go-fuzz を実行するだけです。

func Fuzz(data []byte) int {
    _, err := Parse(data)
	if err != nil {
		return 0
	}
    return 1
}

結果

go-fuzz を実行すると以下のような出力が確認できます。crashers: 1 となっているので crash させることができる fuzz が見つかったことがわかりますね。

$ go-fuzz
2020/12/20 23:36:52 workers: 4, corpus: 1 (3s ago), crashers: 1, restarts: 1/0, execs: 0 (0/sec), cover: 0, uptime: 3s
2020/12/20 23:36:55 workers: 4, corpus: 1 (6s ago), crashers: 1, restarts: 1/0, execs: 0 (0/sec), cover: 0, uptime: 6s
2020/12/20 23:36:58 workers: 4, corpus: 1 (9s ago), crashers: 1, restarts: 1/0, execs: 0 (0/sec), cover: 0, uptime: 9s
2020/12/20 23:37:01 workers: 4, corpus: 1 (12s ago), crashers: 1, restarts: 1/0, execs: 0 (0/sec), cover: 0, uptime: 12s
2020/12/20 23:37:04 workers: 4, corpus: 1 (15s ago), crashers: 1, restarts: 1/0, execs: 0 (0/sec), cover: 0, uptime: 15s

crashers/ に crash させることができた fuzz やそのときのエラーメッセージが出力されるので確認してみます。今回は slice の out of range という初歩的なやつでした。簡単に見つかって便利です。

$ cat crashers/f60d2a2f7993d5825671faef6f38d5d8a0c34130.output
panic: runtime error: slice bounds out of range [:28265] with capacity 1024

goroutine 1 [running]:
...
exit status 2

さいごに

即直しました。

画像1

これでバンドルカードのシステムが少し安全になりました。

お手元にパーサーやらネットワークサーバーやらがあったらとりあえず Fuzzing してみると楽しいバグが見つかるかもしれません。

明日はアドベントカレンダーはデザイナーの konoc さんです。

この記事が気に入ったらサポートをしてみませんか?