web-dev-qa-db-ja.com

ユーザーデータをHTML URLパラメータ値に挿入する前にURLエスケープしますか?

[〜#〜] owasp [〜#〜] からの提案:

ルール#5-信頼できないデータをHTML URLパラメータ値に挿入する前のURLエスケープ

ルール#5は、信頼できないデータをHTTP GETパラメータ値に入れたい場合に使用します。

_<a href="http://www.somesite.com?test=...ESCAPE UNTRUSTED DATA BEFORE PUTTING HERE...">link</a > 
_

被害者がエンコードされたURLをクリックすると、そのリンクをクリックします。ただし、サーバーがgetパラメータ値(PHPの_$_GET['name'];_など)を読み取る場合、プレーンテキストで読み取られます。 _url?name=alert%28123%29_の場合、_$_GET['name']_はalert(123)を返します。サーバーがブラウザで文字列を反映している場合でも、XSSは実行されます。

それで、上記の引用で示唆されているエンコーディングのポイントは何ですか?

3
Arka

これは、起こり得る将来の攻撃を防ぐためではありませんリンクをクリックします。代わりに、リンクが挿入されているthisページへの攻撃を防止します(同時に、リンクの正確さを保持します。これは、サーバーが値を正しくURLデコードするためです)。

ここでデータをエンコードしない場合、攻撃者は">[XSS]などを介してXSSを実行する可能性があります。

リンクをクリックした後、パラメーターが再びページに挿入された場合、挿入されたコンテキストに一致する予防的な問題を再度行う必要があります。

4
tim

エンコードのポイントはセキュリティに関連していません。リンクとHTMLが有効で整形式であることを確認するためだけです。特定の charsはqueryStringsでは使用できません (悪意のあるJSコマンドを形成するために通常必要な文字を含む)。

ブラウザーは一部の形式が正しくない(エスケープ不足、%22などでインライン化される)URLを解釈しようとするため、例はエスケープせずに機能する可能性がありますが、より複雑なスクリプトは「パーセントエンコード」を行わないとフラットになりますURI検索パラメーターに使用します。

0
dandavis

他の人がこれを提案している方法とは異なり、notはHTMLタイプのXSSインジェクションの防止を意味すると思います。私は、上位1000のWebサイトから支払われたXSSバグ報奨金からの一般化された例を示します。

あなたがJSONP APIを持っているとしましょう(それは、最初から恐ろしいアイデアです)。

Weather API

このJSONP APIは、CORSを使用せずに、Origin全体の天気を返します。CORSは、天気を取得したい場所に対してクエリを実行します。 JSONPは、次のようにスクリプトとしてロードすることを意味します。

_* http://mywebsite.com/use-weather-api.php *
<script>
function weatherCallback(data) { alert(data.weather) }
</script>
<script src='http://example.com/weather-api?place=$_GET["place"]&callback=weatherCallback'></script>
_

このスクリプトのコンテンツは、入力に基づいて生成され、コールバックを使用して応答を親コンテキストに渡します。たとえば、_$_GET["place"]_が_"london"_の場合:

_weatherCallback({"weather": "rainy"})
_

次に、関数weatherCallbackがAPIからのJSONペイロードを使用して呼び出され、天気が雨であることが通知されます。

カウンターポイント:HTMLインジェクション

入力に対してサニタイゼーションまたはコンテキストサニタイゼーションを行わないと仮定します。今、私たちができる最も単純で最も明白なXSSは、HTMLインジェクションを使用してXSSを取得する場所を送信することです。

_* http://mywebsite.com/use-weather-api.php?place='><script>alert('xss!')</script> *
<script>
function weatherCallback(data) { alert(data.weather) }
</script>
<script src='http://example.com/weather-api?place='><script>alert('xss!')</script>&callback=weatherCallback'></script>
_

ここで、パラメータを単純にHTMLに追加することにより、最後の行で、攻撃者が追加のスクリプトタグを生成する追加のHTMLを追加できるようにすることで、XSSとも呼ばれるWebページを制御する追加のコードを追加できるようにします。これは、上記の例として他のユーザーが提供したものの拡張バージョンです。

URLエンコードではこれは修正されません

ただし、この例の場合、URLエンコーディングを使用してHTMLエンコーディングを使用することで、このnotを解決する必要があります。 _$_GET["place"]_をurlencode($_GET["place"])に置き換えると、一部の文字がエスケープされない可能性があります。特に_'_(URLエンティティではないため)XSSを取得できます)

_* http://mywebsite.com/use-weather-api.php?place='onload='alert(1) *
<script>
function weatherCallback(data) { alert(data.weather) }
</script>
<script src='http://example.com/weather-api?place='onload='alert(1)'callback=weatherCallback'></script>
_

この場合、悪意のあるonLoadイベントを設定する別のパラメーターを_<script>_タグに挿入することにより、XSSに到達します。これを行うことができるのは、主要なHTML特殊文字がURLエンコードによってエスケープされないためです。

クエリパラメータインジェクション

今、完璧なHTMLサニタイゼーションがあるとしましょう。 HTMLサニタイザーが私たちに与える保証は、追加されたものが配置されたHTMLエンティティをエスケープして、以前の攻撃が失敗するのを防ぐことです。ただし、最後のトリックとして、URLコンテキストに注入します。

_* http://mywebsite.com/use-weather-api.php?place=london%26callback=alert# *
<script>
function weatherCallback(data) { alert(data.weather) }
</script>
<script src='http://example.com/weather-api?place=london&amp;callback=alert#callback=weatherCallback'></script>
_

この場合、HTMLの完全なサニタイズにもかかわらず、コンテキストURLのサニタイゼーションがないため、リクエストURIに追加のクエリパラメータを挿入することができました。 _&_は_&amp_にエンコードされますが、ブラウザのURLパーサーに到達するまでに_&_にデコードされることに注意してください。

「正しい」コールバックパラメータが_#_で「編集」されており、悪意のあるものが挿入されているため、生成されるスクリプトは次のようになります。

_alert({"weather": "rainy"})
_

Webページ(XSSなど)として任意の関数を呼び出すことができます。さらに進むことができ、多くの場合、関数呼び出しだけでなく、必要なJavaScriptをここに記述します。

_ alert('hello!');({"weather": "rainy"})
_

ここで、クエリパラメータはplace=london&amp;callback=alert('hello!')#callback=weatherCallbackです。

これは、urlencode、次にHTMLエンコードが重要な場合です。

じゃあどうすればいい?

これを手動で行わないでください。 MySpaceの時代ではなくなりました。 contextual sanitizationを提供するテンプレートシステムを使用します。これは、HTMLのどこに入力を配置するかを理解し、ほとんどの場合、適切なエスケープのシーケンスを自動的に使用して、悪意のあるコードインジェクションが発生しないようにします。今日は、HTML構文のURL構文について説明しましたが、 HTML内の_<script>_タグ内にURLがある場合があります。この場合、URLエスケープ、次にJavaScriptエスケープ、次にHTMLエスケープが必要です。めちゃくちゃです!

最近、ほとんどの優れたテンプレートシステムがそれを実行します。 PHPのデフォルトはそうではありませんが、使用できる他のオプションがあります。選択するオプションがXSSセーフであることを確認してください。

0
zemnmez