Writing Secure Codeを読んで。

実は、某本*1 と この本 を悩みに悩みあげ、この本を買ってしまった。
ちなみに買うときは
http://www.amazon.co.jp/exec/obidos/ASIN/4891004460/studiokingyo-22
http://studiokingyo.fc2web.com/dxlib/shiryou/book.html
から買ってくれると嬉しい。mousugude amazon gift ken wo moraerukarada.
このページからたどって買ってくれたら きっと貴方にはイイ事あるかも!!? (祝福)


閑話休題・・・


まず、共感したのは「関数の外は悪の巣窟」みたいな事が書かれていたことだった。
私もライブラリを組むときは意識している。
私は一つ一つの関数を作る時、目的に応じて「関数に渡す引数を信用しつつ信用しない」ことにしている。
関数の引数を指定するのは所詮 人と言う事にあるのだ。


第一に関数内部に処理するデータの情報をすべて渡すのが筋だと思う。
このポリシーを見事に踏み倒してくれる悪の関数として挙げるとしたら私はstrcat(dest,src)にするだろう。
この関数の特にあくどい所を上げると

  • destが有効なバッファのサイズがstrcat関数内部には分からない点

が最有力である。
また、細かいかもしれないが

  • srcの有効なバッファのサイズはいくらかが関数内部には分からない
  • destが何バイト文字列が入っているかが関数内部には分からない(以下は関数内部でstrlenでもすれば良いだろうが・・・念のため。)
  • srcが何バイトの文字列が入っているかが関数内部には分からない

と、いった点がある。
これらはすべてセキュリティーホールにつながると私は考える。
非公開、inline展開するならいざ知らず公開関数(C言語の標準関数)がこのようなチェック無しの無責任な処理をしてはいけないと考える。


第二に関数外部から流れてきたデータが製作者の意図をはずれたデータの場合の対策が大切だ。
例えば・・・時間を表す変数として23が実質上上限のchar型の変数があるとしよう。*2
私なら、マイナスになったとか。24以上になったりにするとバグが発生すると考えるのが筋だと考える。
開発者側が引数指定で間違う場合もあるだろうし、通信するプログラムであれば正規のデータが途中で改竄されてソフトを混乱させるを意図としてそのようなデータがで流れて来る事もあるだろう。

そう言うときにitoaとかsprintfとか使って文字列にした場合、
その文字列に必要なバッファが3byteで良いと思っていたのがオーバーフローしてしまったと言う事になりかねない。
え?127が最大だから問題無い?昔の私ならそう思いそうだ・・・
今の私なら昔の私に
このバカチンが〜!!!  川`0´)/☆#T。T) アウッ!
と胸を張って言える。^^;*3

また、それらの通信するプログラムで送られて来て得たデータは信用しないのが筋だ。*4
例えば、

  • 送られて来たデータからmallocするバッファのサイズを指定する
  • クライアントソフトウェアに指示を伝える(しっかり状態遷移対策していればOK)*5

は もってのほかだ!!!

前者は改竄されてUINT_MAXになっていたら・・・メモリ一杯一杯の値になっていたら・・
後者は状態が破綻をきたしてなんらかの不具合が・・・(恐ろしい結果もありうる)
と、
開発者の意図とした動作が出来なくなってしまう。

私がまず、この本を読んで思った事は以上だ。
次回はこれらの対策をするためのコーディングスタイルについて書こうと思う。

関連:http://d.hatena.ne.jp/studiokingyo/20040620#p3



久々に断言系の語尾を沢山使って書いたが・・・実は(((( ;゜д゜))))ものだったりするのデースケドガー^^;

*1:http://d.hatena.ne.jp/studiokingyo/20050221#p1 http://d.hatena.ne.jp/studiokingyo/20050128#p3

*2:unsigned charだとマイナスの対策が無くなるだけ楽だが、ここはバグ条件を増やし、身近なところにセキュリティーホールの源がある事を明示するためにcharとする。

*3:NULL文字分も考慮して上げないとネ・・・また-128ってのもありえるし

*4:もちろん条件によってはここまで徹底する必要な無い

*5:HTMLのJavaScriptActiveX等がこれにあたる。確かに既存の問題を解決するために作った規格だろうが、私は好きではない。このせいで安全性チェック処理等でソフトウェア自体が重くなってしまうのだから・・・