セキュリティに関する考慮事項: 国際的な機能
このトピックでは、国際サポート機能に関連するセキュリティに関する考慮事項について説明します。 これを出発点として使用し、テクノロジ固有のセキュリティに関する考慮事項については、関心のある国際的なテクノロジのドキュメントを参照してください。
このトピックは、次のセクションで構成されています。
- 文字変換関数のセキュリティに関する考慮事項
- 比較関数のセキュリティに関する考慮事項
- ファイル名内の文字セットのセキュリティに関する考慮事項
- 国際化ドメイン名のセキュリティに関する考慮事項
- ANSI 関数のセキュリティに関する考慮事項
- Unicode 正規化のセキュリティに関する考慮事項
文字変換関数のセキュリティに関する考慮事項
MultiByteToWideChar および WideCharToMultiByte は、ANSI と Unicode の間で文字を変換するために最も一般的に使用される Unicode および文字セット関数です。 これらの関数は、入力バッファーと出力バッファーの要素を異なる方法でカウントするため、セキュリティ リスクを引き起こす可能性があります。 たとえば、 MultiByteToWideChar は 、バイト単位でカウントされた入力バッファーを受け取り、変換された文字を Unicode 文字でサイズ設定されたバッファーに格納します。 アプリケーションでこの関数を使用する場合は、バッファーオーバーランを回避するためにバッファーのサイズを正しく設定する必要があります。
WideCharToMultiByte は、既定で 1252 などのコード ページの "最適" マッピングに設定されます。 ただし、この種類のマッピングでは、同じ文字列を複数表現できるため、アプリケーションが攻撃に対して脆弱になる可能性があります。 たとえば、英大文字 A と二号 ("Ä") は、ラテン文字 A ("A") にマップされる場合があります。アジア言語の Unicode 文字はスラッシュ ("/") にマップされる場合があります。 セキュリティの観点から、WC_NO_BEST_FIT_CHARS フラグを使用することをお勧めします。
5022x (iso-2022-x) コード ページなど、一部のコード ページは、同じ文字列を複数表現できるため、本質的に安全ではありません。 適切に記述されたコードは Unicode 形式でセキュリティ チェックを実行しますが、これらの種類のコード ページはアプリケーションの攻撃の影響を拡大するため、可能であれば回避する必要があります。
比較関数のセキュリティに関する考慮事項
文字列比較では、セキュリティの問題が発生する可能性があります。 すべての比較関数は若干異なるため、1 つの関数で 2 つの文字列が等しいと報告される場合もあれば、別の関数で異なると見なされる場合があります。 アプリケーションで文字列を比較するために使用できる関数を次に示します。
- lstrcmpi。 ロケールの規則に従って、大文字と小文字を区別せずに 2 つの文字列を比較します。 関数は、最初の文字を相互にチェックし、2 番目の文字を相互にチェックして文字列を比較します。次のように、不等値が見つかるか、文字列の末尾に達します。
- lstrcmp。 lstrcmpi と同様の手法を使用して文字列を比較します。 唯一の違いは、 lstrcmp が大文字と小文字を区別する文字列比較を実行することです。
- CompareString、 CompareStringEx (Windows Vista 以降)。 アプリケーション指定のロケールで文字列比較を実行します。 CompareStringEx は CompareString に似ていますが、ロケール識別子ではなくロケール名でロケールを識別します。 これらの関数は lstrcmpi および lstrcmp に似ていますが、ユーザーが選択したロケールではなく特定のロケールで動作する点が異なります。
- CompareStringOrdinal (Windows Vista 以降)。 2 つの Unicode 文字列を比較して、バイナリの等価性をテストします。 大文字と小文字を区別しないオプションを除き、この関数はバイナリ以外のすべての等価性を無視し、言語 的な並べ替え スキームで重みが与えられないコード ポイントを含め、すべてのコード ポイントの等価性をテストします。 このトピックで説明する他の比較関数では、すべてのコード ポイントが等しいかどうかをテストするわけではありません。
- FindNLSString、 FindNLSStringEx (Windows Vista 以降)。 別の Unicode 文字列で Unicode 文字列を見つけます。 FindNLSStringEx は FindNLSString に似ていますが、ロケール識別子ではなくロケール名でロケールを識別する点が除きます。
- FindStringOrdinal (Windows 7 以降)。 別の Unicode 文字列内の 1 つの Unicode 文字列を検索します。 アプリケーションでは、言語以外のすべての比較に FindNLSString の代わりにこの関数を使用する必要があります。
lstrcmpi や lstrcmp と同様に、CompareString は文字列を文字ごとに評価します。 ただし、多くの言語には、従来のスペイン語の 2 文字要素 "CH" など、複数文字の要素があります。 CompareString はアプリケーションによって提供されるロケールを使用して複数文字の要素を識別し、lstrcmpi と lstrcmp はスレッド ロケールを使用するため、同じ文字列が等しいと比較されない場合があります。
CompareString は未定義の文字を無視するため、非常に異なる多くの文字列ペアに対して 0 (等しい文字列を示します) が返されます。 文字列には、任意の文字にマップされない値が含まれている場合や、アプリケーションのドメイン外のセマンティクスを持つ文字 (URL の制御文字など) が含まれている場合があります。 この関数を使用するアプリケーションでは、エラー ハンドラーとテスト文字列を提供して、使用する前に有効であることを確認する必要があります。
注意
Windows Vista 以降の場合、 CompareStringEx は CompareString に似ています。 セキュリティの問題は、これらの機能と同じです。
同様のセキュリティの問題は、暗黙的な比較を行う 関数 (FindNLSString など) に適用されます。 設定されているフラグによっては、 FindNLSString を呼び出して別の文字列内の 1 つの文字列を検索する結果が大きく異なる場合があります。
注意
Windows Vista 以降の場合、 FindNLSStringEx は FindNLSString に似ています。 セキュリティの問題は、これらの機能と同じです。
ファイル名内の文字セットのセキュリティに関する考慮事項
日本語システムで使用される Windows コード ページと OEM 文字セットには、円記号 (\) ではなく円記号 (¥) が含まれています。 したがって、Yen 文字は NTFS および FAT ファイル システムでは禁止されている文字です。 Unicode を日本語のコード ページにマッピングする場合、変換関数は円記号 (U+005C) と通常の Unicode 円記号 (U+00A5) の両方を同じ文字にマップします。 セキュリティ上の理由から、通常、アプリケーションでは、FAT ファイル名として使用するために変換される可能性がある Unicode 文字列で文字 U+00A5 を許可しないでください。
国際化ドメイン名のセキュリティに関する考慮事項
国際化ドメイン名 (IDN) は、ネットワーク ワーキング グループ RFC 3490: アプリケーションでのドメイン名の国際化 (IDNA) で指定されています。 この標準では、さまざまなセキュリティの問題が導入されています。
異なるスクリプトの特定の文字を表すグリフは、似ているか、同一のように見える場合があります。 たとえば、多くのフォントでは、キリル小文字 A ("a") はラテン小文字 A ("a") と区別できません。 "example.com" と "example.com" は 2 つの異なるドメイン名であり、1 つは名前にラテン小文字 A、もう 1 つはキリル小文字 A であることを視覚的に伝える方法はありません。悪意のないホスト サイトでは、この視覚的あいまいさを使用して、スプーフィング攻撃で別のサイトのふりをすることができます。
IDNA が IDN に対して許可する拡張文字セットは、特定のスクリプト内でスプーフィングの可能性もあります。 たとえば、 ハイフンマイナス ("-" U+002D)、ハイフン ("—" U+2010)、改行しないハイフン ("-" U+20 11)、図のダッシュ ("\u2012" U+2012)、en dash ("–" U+2013)、マイナス記号 ("-" U+2212)。
特定の互換性コンポジションから同様の問題が発生します。 たとえば、1 つの Unicode 文字 NUMBER TWENTY FULL STOP ("20"、U+249B) は "20" に変換されます。(U+0032 U+0030 U+002E) NamePrep ステップで、Punycode に変換する前。 つまり、このコンポジションはピリオド (完全停止) を挿入します。 このような構成にはスプーフィングの可能性があります。
IDN に異なるスクリプトを混在させる場合、スプーフィングや詐欺的な意図を示すわけではありません。 テクニカル レポート #36: Unicode のセキュリティに関する考慮事項 では、スクリプトの組み合わせを含む適切な IDN の例をいくつか示します。 例: XML-Документы.com ("1Документы" はロシア語で "documents") です。
スプーフィング攻撃は IDN に限定されません。 たとえば、"rnicrosoft.com" は "microsoft.com" によく似ていますが、ASCII 名です。 さらに、名前の破損によってスプーフィング攻撃が行われる可能性があります。 既知のブランド名の後に追加のラベルを追加したり、セキュリティで保護された URL のパスにブランド名を含めたりすると、IDN の使用に関係なく、初心者のユーザーが混乱する可能性があります。 一部のロケールでは、IDN が必要であり、これらの名前の Punycode 形式は受け入れられません。これは、名前がちんぷんちくのように見えるのでです。
ここで説明するセキュリティの問題と、IDNA に関連するその他の多数の問題の詳細については、「 Technical Report #36: Unicode セキュリティに関する考慮事項」を参照してください。 このレポートでは、IDNA 関連のセキュリティ問題に関する詳細な説明と共に、アプリケーション内の IDN の疑いを処理するための提案を提供します。
ANSI 関数のセキュリティに関する考慮事項
注意
可能であれば、グローバル化されたアプリケーション 、特に新しいアプリケーションで Unicode を使用することをお勧めします。 ANSI 関数は、Unicode を使用しない理由 (Unicode をサポートしていない古いプロトコルへの準拠など) をオーバーライドしている場合にのみ使用する必要があります。
GetLocaleInfo や GetCalendarInfo などの多くの各国語サポート (NLS) 関数には、それぞれ特定の ANSI バージョンがあり、この場合は GetLocaleInfoA と GetCalendarInfoA です。 アプリケーションで Unicode ベースのオペレーティング システム (Windows NT、Windows 2000、Windows XP、Windows Vista など) で ANSI バージョンの関数を使用すると、関数が失敗したり、未定義の結果が生成されたりする可能性があります。 このようなオペレーティング システムで ANSI 関数を使用する魅力的な理由がある場合は、アプリケーションによって渡されるデータが ANSI に対して有効であることを確認してください。
Unicode 正規化のセキュリティに関する考慮事項
Unicode 正規化は文字列の形式を変更できるため、通常、セキュリティ メカニズムまたは文字検証アルゴリズムは正規化後に実装する必要があります。 たとえば、ファイル名を受け入れるがパス名を受け入れない Web インターフェイスを持つアプリケーションを考えてみましょう。 全角 U+FF43 U+FF1A U+FF3C U+FF57 U+FF49 U+FF4E U+FF44 U+FF4F U+FF57 U+FF53 U+0063 U+FF53 (c : \ w i n d o w s)
が U+0063 U+0 に変更 フォーム KC 正規化を使用した U+003C U+0077 U+0069 U+006E U+0064 U+006F U+0077 U+0073 (c:\windows)
。 アプリケーションが正規化を実装する前にコロン文字と円記号の有無をテストすると、結果が意図しないファイル アクセスになる可能性があります。
Unicode 正規化はオペレーティング システムをセキュリティで保護する要素ですが、正規化は包括的なセキュリティ ポリシーに代わるものではありません。
関連トピック