一般的に、安全が必要なプログラムでは、そのプログラムが決めた前提条件と クライアントが同期していなければいけません。 よくある問題の 1 つとして、文字を出力する際に符号化指定を行わないと、Web アプリケーションに支障がでる点が挙げられます。 すべてのデータが信頼できる元からくる場合はかまいません。しかし、信頼できない 元からもデータがくるなら、信頼できない元が安全が必要なプログラムの予期でき ない別の符号化を使って、データを偽るかもしれません。 これがサイトにまたがる悪意ある攻撃のきっかけになります。詳しくは、 Section 4.9 を見てください。
CERT's tech tip on malicious code mitigation でこの文字符号化を指定しない
問題についてかなりわかりやすく解説していますので、ここで引用します。
Web ページの中には、文字符号化(HTTP の「charset」パラメタ)を定義していない
ところがたくさんあります。
HTML や HTTP の初期バージョンでは、文字符号化が定義されていないと、デフォルト
で ISO-8859-1 であると仮定していました。
実際に、ブラウザのデフォルトはさまざまだったので、デフォルトを ISO-8859-1
としてしまうのには無理がありました。
HTML version 4 では、文字符号化を指定していなければ、どの符号化を使っても
かまわないことになりました。 Web サーバがどの文字符号化を使うのか指定していないと、どの文字が特殊文字
なのかがわかりません。
文字符号化を指定していない Web ページは、たいていの場合うまく動作します。
それは文字集合のほとんどが、128 以下のバイト値に同じ文字を割り当てて
いるからです。
しかし、128 以上の値のどれが特殊文字なのでしょうか。
16 ビットの文字符号化方式には、「<」のような特殊文字を表示するのに、追加で
複数バイトを使っているものもあります。
ブラウザには、これを別の符号化として認識し、動作するものもあります。
これは「正しい」動作なのですが、悪意あるスクリプトを使った攻撃が、防ぎづらく
なってしまっています。
サーバはどのバイトシーケンスが特殊文字を現すのか、単純には判断できなくなり
ます。 たとえば、UTF-7 は「<」と「>」に対して、異なる符号化を提供しています。
またよく使われているブラウザのいくつかは、これらをタグの開始と終了として認識
するものもあります。
これはブラウザのバグではありません。
文字符号化が本当に UTF-7 なら、これは正しい動作です。
問題は、ブラウザとサーバが符号化で同期がとれていない状況に陥る可能性が
ある点です。
この問題を説明するのは厄介ですが、有り難いことに、HTML での解決策は簡単です。 HTML ヘッダに文字セットを下記の例のように設定するだけです。
<HTML> <HEAD> <META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <TITLE>HTML SAMPLE</TITLE> </HEAD> <BODY> <P>This is a sample HTML page </BODY> </HTML> |
技術的な観点からすると、文字符号化を HTTP プロトコルの出力の一部として設定 する方が、さらに良い解決策です。しかし、これを難しくしているライブラリが存在 します。 この解決策は技術的には優れています。クライアントに強制的にヘッダーを調べさせ、 ヘッダー中にあるMETA 情報を読んでわかる文字符号化を判定する必要がないからです。 もちろん、現実的には上記のような META 情報を読めなかったり、正しく扱え なかったりするブラウザは、市場では受け入れられていません。しかしそれは別問題 です。 いずれにしても、サーバが HTTP プロトコルの一部として「文字セット」に適切な 値を設定して送り出す必要があります。 残念ながら、この(技術的には優れた)解決方法を心からお薦めできません。 それは、古い HTTP/1.0 対応のクライアントには、明示的に指定してある charset パラメタを適切に扱えないものがあるからです。 HTTP/1.1の仕様では、クライアントがこのパラメタに従うように定めていますが、 それを実現するのは、ははなはだ疑わしいと思います。おそらく、正しい文字符号化 の利用を強制する手段として、その仕様を唯一の方法としてではなく、追加の方法 として使うことになるでしょう。