web-dev-qa-db-ja.com

ダブルエンコーディングでXSSサニタイザーをバイパスするのはいつ、なぜですか。

/<>:"'などの特殊文字を二重にエンコードする、または異なるエンコードスキームを使用するなど、XSSサニタイザーをバイパスするさまざまな方法についてさまざまなサイトを読みました。

ただし、これらのサイトのほとんどは、これらの攻撃が機能する理由とその場合について説明していません。たとえば、現代のブラウザは特殊文字をURLエンコードしますが、cURLはそれを行いません。したがって、cURL(またはBurp Proxy)を使用してPoCを作成することはできません。

ブラウザーが入力データ(POSTとGETの両方)をエンコードして処理する方法と、一般的な(PHP)Webアプリケーションがこれらを処理する方法について、誰かが非常に詳細な説明を提供できますか? PHPでのわずかな経験から(大学在学中)、エンコーディングやセキュリティの実践などについてさえ考えることなく、$_POST["query"]のようなパラメータにアクセスしていました。

25
XII

1回(B)および2回(C)でエンコードされたこのペイロード例(A)を見てみましょう。

_A. <script> alert(1) </script>
B. %3Cscript%3E alert(1) %3C%2Fscript%3E
C. %253Cscript%253E alert(1) %253C%252Fscript%253E
_

変数がエンコードされているかどうかについて、アプリケーションのさまざまな部分がさまざまな仮定をしている場合、二重エンコードを使用してXSSフィルターをバイパスできます。たとえば、次の脆弱なコードを考えてみましょう:

_$input = htmlentities($_GET["query"]);
echo urldecode($input);
_

このコードは、ペイロードが(Bのように)単一にエンコードされている場合、ペイロードをブロックします。 PHP URLは、デフォルトでGET変数をデコードします(BをAに変換します)。そのため、_<_および_>_は、中和するhtmlentitiesに渡されますただし、代わりにCで送信すると、htmlentitiesを変更せずに通過するBにデコードされたURLになります。エコーされる前に再度URLデコードされるため、危険なペイロードAになります。

したがって、ここでのバグは、URLデコードの別のレイヤーafter XSSフィルターがあることです。このように2行が隣接している場合、問題は非常に明白です。しかし、これら2つは別々のモジュールにあるため、検出が困難です。どの文字列がURLエンコードされているかを追跡するのは難しいので、確実に追加のデコードを投入するのは魅力的です。結局のところ、通常はエンコードされていないデータには影響しません。

PHPマニュアル は実際にこれについて警告します:

警告:スーパーグローバル_$_GET_および_$_REQUEST_はすでにデコードされています。 _$_GET_または_$_REQUEST_の要素でurldecode()を使用すると、予期しない危険な結果になる可能性があります。

私の意見では、マニュアルはここでは十分に慎重ではありません-XSSのフィルタリング後に信頼できないデータをデコードすることは、それがどこから来たとしても危険です。フィルタリングした後は、データの変更に十分注意してください。

詳細については、 [〜#〜] owasp [〜#〜] を参照してください。

33
Anders