バッファオーバーフロー

 近年わりと聞くようになったセキュリティ関連のバグで、Windows Updateの更新ってほぼ全部この「バッファオーバーフロー」対策ばっかりだな~と思うのですが、今の現場で触ってるソースも古いソースで「バッファオーバーフロー」しそうな危ない実装が多数で、先日のトラブルの絡みで直そうとかいう話に。

 正直、気の遠くなるような話である。

 どういうときに「バッファオーバーフロー」するのかと言うと、詳しく説明しているページはいっぱいあるので詳細はそちらに譲るが、例えば

"test"

という文字列があったとして、この情報を保持するのに何バイトの領域が必要かというと、半角英数の文字は1文字1バイトなので、計5バイト必要になる。

プログラムをまったく知らないのに「えっ4バイトでは?」と思ったあなたはなかなか鋭い。

C言語では文字列がどこで終わるのか?という情報を文字列自体が持っていないので、データの末尾に空データ(0もしくはnull。サイズは1バイト)を付加することで文字列の終端を認識しているのである。よって、4文字+null1バイトで計5バイトになるというわけである。

 で、C言語の標準的な文字列操作関数というのは

問題1)文字列データの末尾に必ずnullが入っているのを前提に動作する

ところが

・文字列データの末尾nullが入るかどうかはコーディング次第である。コーディングミスをするとnullが入っておらず文字列の末尾が識別できないデータがくる可能性が発生する

という危険な状況になる。自分が作るプログラムだけで閉じていればまだ何とかなるが、人が作ったプログラムと連結するとかいう話になると、バグでおかしなデータが飛んでくる可能性がある。そしていったん壊れたデータがくるとこちらも影響を受けてデータを破壊して動作がおかしくなることになる。

次に重大な問題は

問題2)編集文字列を格納する領域は、関数を呼ぶ前に使用者があらかじめ確保して関数を呼ぶことを前提にしている

という点である。だから

・使用者が誤ってきちんと領域確保せずに関数を呼び出すとその関数は何も考えずにその領域にデータをセットしてメモリを破壊する

ということになる。例えば

sprintf(str, "%d", num);

とかやってstrという文字列領域にnumという数字を埋め込む処理をする場合、numという数字は最大何桁になるかわからない。32bitCPUの時代には数値というと32bitになるので最大「4294967296」となって最大文字数は10文字になる。なのでstrの文字列領域にはnullも含めて11バイトの領域が必要になる。

 ところが最近のサーバマシンは64bitになったので、数字も64bitに増えて最大が「18446744073709551616」20桁。きちんと文字列の領域に21バイト取ってますか?という話になる。


 でだ、実際そんな最大幅をきちんと予見してきちんと領域確保して処理してるプログラムなんてほとんどないのだ。そういうわけでメモリ転送する処理は全部見直さないといけないことになる。で、業務系プログラムというのは大半(8割くらい?)はデータの制御処理、それも文字列操作で占められているので、実質これまで作った膨大なソースの8割を全部見直さないといけなくなるわけだね。


 そういうわけでこの辺の処理はパンドラの函とでも呼ぶべき禁忌の領域だったわけである。
 ふう
[PR]
by namizusi | 2006-01-18 12:56 | プログラム


<< 予想通り 【ツキカミ】PCの設定を書き換... >>