信頼できない入力文字列を受け取るアプリケーションの多くは、文字列に含まれる文字データに基づいた入力値のフィルタや検証メカニズムを採用している。
たとえば、クロスサイトスクリプティング(XSS)の脆弱性を回避する戦略のひとつとして、<script>タグの入力を禁止するという方法がある。このようなブラックリスト方式のメカニズムは、セキュリティ上の戦略の一部としては有用だが、入力値を完全に無害化することはできない。実装するのであれば、入力を正規化した後にこの手の検証を行わなければならない。
Java SE 6における文字情報は Unicode標準バージョン4.0 [Unicode 2003]に、Java SE 7における文字情報は Unicode標準バージョン6.0.0 [Unicode 2011] に基づく。
Unicode Standard [Davis 2008] Annex 15は、Unicodeの正規化形式(Normalization Form)について以下のように規定している。
処理系が文字列を正規化形式で保持する場合、等価な文字列は一意のバイナリ表現を持つことが保証される。
正規化形式KCとKDを任意のテキストに対してむやみに用いてはいけない。これらの正規化形式は多くの書式上の差異を削除してしまうため、レガシーの文字セットとの間で双方向の変換を妨げる。書式情報を追加しておかない限り、テキストの意味上重要な差異を削除してしまうかもしれない。これらの正規化形式は大文字や小文字への変換と考えるとわかりやすい。本質的な意味を特定する上では役に立つ場合もあるかもしれないが、テキストに変更を加えることは常に適切であるとは限らない。制限された文字セットの間ではもっと自由に使えるかもしれない。
任意の形式にエンコードされた文字列に対して入力値検査を行う、最も適した正規化形式は、KC(NFKC)である。入力データをKCに標準化すれば、入力フォームに求められる入力形式との比較を安全に行うことができる。
違反コード
以下の違反コードでは、文字列を標準化する前に検証を試みている。このやり方では、山括弧 "<" と ">" が含まれるかどうかのチェックでこれと等価なUnicode表現を検知できないため、本来拒否すべき入力を検知することができない。
// String s はユーザに制御されているかもしれない // NFKC では \uFE64 は < に、\uFE65 は > に標準化される String s = "\uFE64" + "script" + "\uFE65"; // 検証する Pattern pattern = Pattern.compile("[<>]"); // 山括弧かどうかのチェック Matcher matcher = pattern.matcher(s); if (matcher.find()) { // ブラックリストに登録されたタグを見つけた場合の処理 throw new IllegalStateException(); } else { // ... } // 標準化する s = Normalizer.normalize(s, Form.NFKC);
normalize()メソッドはUnicodeテキストを等価な合成形式もしくは分解形式に変換する。これによりテキストの検索が容易になる。normalize()メソッドは、Unicode標準 Annex 15 に規定されている標準正規化形式をサポートしている。
適合コード
以下の適合コードでは、文字列を検証する前に標準化を行っている。山括弧に相当する文字列表現は、正規化された山括弧に変換される。その結果、入力値検査は悪意のある入力を正しく検出することができ、IllegalStateException例外をスローする。
String s = "\uFE64" + "script" + "\uFE65"; // 文字列を標準化する s = Normalizer.normalize(s, Form.NFKC); // 文字列を検証する Pattern pattern = Pattern.compile("[<>]"); Matcher matcher = pattern.matcher(s); if (matcher.find()) { // ブラックリストに登録されているタグを発見した throw new IllegalStateException(); } else { // ... }
リスク評価
入力値を標準化する前に検証すると、攻撃者は入力値フィルタや他のセキュリティメカニズムを回避できるかもしれない。結果として任意のコード実行につながる恐れがある。
ルール | 深刻度 | 可能性 | 修正コスト | 優先度 | レベル |
---|---|---|---|---|---|
IDS01-J | 高 | 中 | 中 | P12 | L1 |
関連ガイドライン
ISO/IEC TR 24772:2010 | Cross-site scripting [XYT] |
MITRE CWE | CWE-289. Authentication bypass by alternate name |
CWE-180. Incorrect behavior order: Validate before canonicalize |
参考文献
[API 2006] |
[Davis 2008] |
[Weber 2009] |
翻訳元
これは以下のページを翻訳したものです。
IDS01-J. Normalize strings before validating them (revision 78)