6

XSS 攻撃を防ぐために文字列のエンコードを検討しています。現在、ホワイトリスト アプローチを使用したいと考えています。ホワイトリスト外の文字はすべてエンコードされます。現在、「(」のようなものを代わりに「(」を出力しています。私たちが知る限り、これでほとんどの XSS を防ぐことができます。

問題は、私たちには多くの国際的なユーザーがいて、サイト全体が日本語の場合、エンコーディングが帯域幅を大量に消費することです. 基本的な ASCII セット外の文字は脆弱性ではなく、エンコードする必要がない、またはエンコードする必要がある ASCII セット外の文字があると言って差し支えありませんか?

4

2 に答える 2

11

エンコーディングをhtmlentities() / htmlspecialcharsに渡すだけで(かなり)簡単になるかもしれません

echo htmlspecialchars($string, ENT_QUOTES, 'utf-8');

しかし、これで十分かどうかは、印刷するもの (および場所) によって異なります。

参照:
http://shiflett.org/blog/2005/dec/googles-xss-vulnerability
http://jimbojw.com/wiki/index.php?title=Sanitizing_user_input_against_XSS
http://www.erich-kachel.de /?p=415 (ドイツ語。英語で似たようなものを見つけたら -> 更新) 編集: ドイツ語に堪能でなくても要点を理解できると思います ;) 文字列

javascript:eval(String.fromCharCode(97,108,101,114,116,40,39,88,83,83,39,41))
htmlentities() を変更せずに渡します。今のようなものを考えてみましょう
<a href="<?php echo htmlentities($_GET['homepage']); ?>"
どちらが送信します
<a href="javascript:eval(String.fromCharCode(97,108,101,114,116,40,39,88,83,83,39,41))">
ブラウザに。要するに、
href="javascript:eval(\"alert('XSS')\")"
htmlentities() は要素のコンテンツに対しては仕事をしますが、属性にはあまり適していません。

于 2009-04-30T01:05:06.797 に答える
5

一般に、はい、「安全」であるためにASCII以外のものに依存することができますが、考慮すべきいくつかの非常に重要な警告があります。

  1. クライアントに送信するものがUTF-8としてタグ付けされていることを常に確認してください。これは、エラーページのコンテンツのいずれかがユーザー入力から生成された場合、すべてのエラーページを含め、すべてのページに「Content-Type:text / html; charset=utf-8」と明示的に示すヘッダーがあることを意味します。(多くの人は404ページをテストするのを忘れ、そのページに見つからないURLをそのまま含めます)
  2. クライアントに送信するものが有効なUTF-8であることを常に確認してください。これは 、ユーザーから受信したバイトを単純にユーザーに戻すことはできないことを意味します。バイトをUTF-8としてデコードし、htmlエンコードXSS防止を適用してから、書き戻すときにUTF-8としてエンコードする必要があります。

これらの2つの警告の最初の警告は、クライアントのブラウザが高文字の文字を含む大量の文字を表示したり、ローカルのマルチバイト文字セットにフォールバックしたりしないようにすることです。そのローカルマルチバイト文字セットには、防御できない有害なASCII文字を指定する複数の方法がある場合があります。これに関連して、特定のブラウザのいくつかの古いバージョン-、すなわち-ページがUTF-7であることを検出することに少し熱心でした。これにより、XSSの可能性に終わりはありません。これを防ぐために、発信する「+」記号をHTMLでエンコードすることをお勧めします。これは、適切なContent-Typeヘッダーを生成しているときは過度の妄想ですが、将来誰かがカスタムヘッダーをオフにするスイッチを切り替えたときにあなたを救うでしょう。(たとえば、不適切に構成されたキャッシングリバースプロキシをアプリの前に配置したり、追加のバナーヘッダーを挿入したりすることで、出力が既に書き込まれている場合、phpではHTTPヘッダーを設定できません)

2つ目は、UTF-8で「過度に短い」シーケンスを指定できるためです。これは、現在の仕様では無効ですが、古いブラウザではASCII文字として解釈されます。(ウィキペディアの内容を参照してください)また、誰かがリクエストに1つの不良バイトを挿入する可能性があります。このパックをユーザーに渡すと、一部のブラウザが不良バイトとその後の1つ以上のバイトの両方を「?」に置き換える可能性があります。または他の「これを理解できなかった」文字。つまり、1つの不良バイトが原因で、一部の良好なバイトも飲み込まれる可能性があります。出力しているものをよく見ると、出力から1〜2バイトを消去できた攻撃者がXSSを実行できる場所がおそらくどこかにあります。

于 2009-05-19T12:14:12.027 に答える