Hatena::ブログ(Diary)

葉っぱ日記 このページをアンテナに追加

2004-11-20

[] その1  その1を含むブックマーク

2004年10月30日に京都で話をした内容を、改めて書き直してみます。発表資料をそのまま公開したのでは、おそらく意味不明な箇所が多すぎますので。

なお、「Unicodeって何?」「UTF-8って何?」といった予備知識については、発表時には簡単ながらも一応触れたのですが、ここでは省略しています。

質問や突っ込みはここでのコメントよりもopenmyaMLのほうが反応しやすいでしょう。

では、はじまりはじまり。

文字列処理とセキュリティ 文字列処理とセキュリティを含むブックマーク

プログラム内で文字列処理を誤った際に引き起こされるセキュリティ上の問題としては、「バッファオーバーフロー」と「危険な文字列のチェック漏れ」に大別できます。もちろん、文字列処理によるセキュリティ問題の要因はこの2つだけではないでしょうが、この2つを防ぐことにより、多くの問題が対策できるのではないかと思います。

バッファオーバーフロー

多くのアプリケーションで発生しているバッファオーバーフローは、ほとんどの場合、アプリケション内で文字列およびそれを受け入れる変数の長さを適切に管理していないことに起因します。逆に言えば、文字列および変数の長さを適切に管理さえできれば、大半のバッファオーバーフローを防ぐことができます。

本稿に興味を示すような方にいまさらバッファオーバーフローのメカニズムや危険性を説明する必要はないでしょうし、最近ではバッファオーバーフローを防ぐ有用なツール類も増えてきていますので、本稿ではバッファオーバーフローを防ぐ手段よりも、どのような場合にバッファオーバーフローを起こしやすいかに重点を置いて説明しています。

危険な文字列のチェック漏れ

セキュリティを考慮しなければならないプログラムにとって、外部から入力された文字列のチェックというのは、基本中の基本であり、ほとんどのプログラムにおいて必須の行為だといえます。しかしながら、Unicode を扱う場合、外部からやってきた文字列を正確にチェックし、不適切な文字列をフィルタリングするためには、これまでの strcmp() のような単純なバイト列の比較だけでは不充分であり、Unicode 特有の事情を考慮しながらの各文字の適切なチェックが必要となります。

UTF-16での注意点 UTF-16での注意点を含むブックマーク

ドキュメント上の "Unicode" という単語の意味に注意

特に Microsoft のドキュメントに多いのですが、文脈によって "Unicode" という単語が純粋にUnicodeを指している場合と、エンコーディングとしての UTF-16 (もしくは UCS-2)を指している場合とがありますので、混乱しないように注意が必要です。

1文字が必ずしも16ビット固定ではない

これもまた、Microsoft の古いドキュメントに多いのですが、Unicode の1文字は16ビット固定であるかのような印象を受けるドキュメントをよく目にします。ところが、現実にはそうではありません。

UTF-16 は、基本的な文字(BMP)については 16ビット固定で表現し、それ以外の文字はサロゲートペアという方法で4バイトで表現するというエンコーディングです。UCS-2 は、BMPのみを扱う16ビット固定のエンコーディングです。

Unicode はバージョン 3.1 まではBMP以外に文字を定めていなかったため、UTF-16 と UCS-2 はほとんど等価なものでした。

現在では、BMP 以外にも文字が追加され、それらの文字は UTF-16 においては1文字を4バイトで表現されます。UCS-2 のみをサポートすると明言した場合、すなわち扱えるデータをUCS-2に制限した場合、1文字はすべて16ビットの固定長となります。

ただし、UCS-2のみの場合でも自分で作成したアプリケーションと外側との境界においては、各文字がBMP内に納まっているかを確認するようにしましょう。入ってくるデータが正当な範囲内であるのかをチェックするのはもちろんのこと、出ていくデータ、ライブラリ関数に渡すデータにも非BMPの文字が含まれないようにするべきです。あなたのコードが「無害」と判断したデータは、それを受け取る次段では実は有害なデータであるかも知れません。

また、サロゲートされないBMPの文字だけを使っている場合でも、Unicode では文字の合成、分解が定義されており、特定の文字に対して、合成済みの文字を使って1文字で表わすこともあれば、1つの基底文字に1つ以上の結合文字を組み合わせて表現することもあります。

例えばは、合成済みの文字を使って U+304Cの単一文字で表わすこともできますし、基底文字と結合用の濁点を組み合わせて U+304B U+3099 と表わすこともできます。これはUTF-16 だけでなく、UCS-2 であっても当てはまります。

これらの理由により、1文字が16ビット固定であると思い込んだ場合、見かけ上の文字数と実際のバイト数の不一致により、思わぬところで文字列を切ってしまう、文字数に対してバッファ領域が足りない、などの問題を起こす可能性があります。

文字数とバイト数の違いに注意

ドキュメント類によって、バッファサイズなどが Unicode の文字数単位で指定されている場合と、バイト数で指定されている場合が混在しています。これらを混乱することによるバッファオーバーフローには注意が必要です。

また、複雑なエンコーディングにより、バイト数でバッファサイズを指定したときに、文字の途中で文字列が分断されることも考えられますので、その点についても注意が必要です。


(続く)

ripjyrripjyr 2004/11/20 21:03 を 公開あり〜