フロントエンドセキュリティ(3):クロスサイトスクリプティング(XSS)の防止

1.XSSを防ぐ方法

XSS攻撃には2つの要素があります。

  • 攻撃者は悪意のあるコードを送信します。

  • ブラウザは悪意のあるコードを実行します。

最初の要素について:ユーザー入力の過程でユーザーが入力した悪意のあるコードを除外できますか?

入力フィルター

ユーザーが送信すると、入力はフロントエンドによってフィルタリングされてから、バックエンドに送信されます。これは可能ですか?答えは仕方がない。攻撃者がフロントエンドフィルタリングをバイパスしてリクエストを直接作成すると、悪意のあるコードが送信される可能性があります。次に、フィルタリングのタイミングを変更します。バックエンドは、データベースに書き込む前に入力をフィルタリングしてから、「安全な」コンテンツをフロントエンドに返します。これは実行可能ですか?例を見てみましょう。通常のユーザーが5 <7のコンテンツを入力しましたが、データベースに書き込まれる前にエスケープされ、5 <7になりました。問題は、提出段階では、コンテンツをどこに出力するかわからないということです。

この「コンテンツをどこに出力するかわからない」には、2つの意味があります。

  1. ユーザーの入力コンテンツがフロントエンドとクライアントに同時に提供される場合があり、escapeHTML()が渡されると、クライアントによって表示されるコンテンツが文字化けします(5 <7)。

  2. フロントエンドでは、位置が異なれば必要なコードも異なります。

  • 5 <7 HTMLスプライシングページとして使用すると、通常どおり表示できます。
<div title="comment">5 &lt; 7</div>
  • 5 <7がAjaxを介して返され、JavaScript変数に割り当てられると、フロントエンドによって取得された文字列がエスケープ文字になります。このコンテンツは、Vueなどのテンプレートの表示に直接使用することも、コンテンツの長さの計算に直接使用することもできません。タイトルやアラートなどには使用できません。

したがって、入力側のフィルタリングは特定のXSS問題を解決できる場合もありますが、多くの不確実性と文字化けの問題が発生します。XSS攻撃を防ぐ場合は、このような方法は避けてください。

もちろん、番号、URL、電話番号、電子メールアドレスなどの明確な入力タイプの場合でも、入力をフィルタリングする必要があります。

入力フィルタリングは完全に信頼できるものではないため、「ブラウザが悪意のあるコードを実行しないようにする」ことでXSSを防止する必要があります。この部分は2つのカテゴリに分けられます。

  • HTMLでのインジェクションを防止します。

  • JavaScriptの実行時に悪意のあるコードが実行されないようにします。

ストレージとリフレクションXSS攻撃を防ぐ

保存されたXSSとリフレクティブXSSは両方ともサーバーから削除され、応答HTMLに挿入されます。攻撃者によって書き込まれた「データ」は「コード」に埋め込まれ、ブラウザーによって実行されます。

これらの2つの脆弱性を防ぐための2つの一般的な方法があります。

  • 純粋なフロントエンドレンダリングに変更して、コードとデータを分離します。

  • HTMLを完全にエスケープします。

純粋なフロントエンドレンダリング

純粋なフロントエンドレンダリングのプロセス:

  1. ブラウザは最初に静的HTMLをロードしますが、これにはビジネス関連のデータは含まれていません。

  2. 次に、ブラウザはHTMLでJavaScriptを実行します。

  3. JavaScriptはAjaxを介してビジネスデータを読み込み、DOMAPIを呼び出してページ上でデータを更新します。

純粋なフロントエンドレンダリングでは、ブラウザに明確に伝えます。以下に設定するコンテンツは、テキスト(.innerText)、属性(.setAttribute)、またはスタイル(.style)などです。ブラウザは簡単にだまされて、予期しないコードを実行することはありません。ただし、純粋なフロントエンドレンダリングでは、DOMタイプのXSSの脆弱性を回避するためにも注意を払う必要があります(onloadイベントやhrefのjavascript:xxxなど。以下の「DOMタイプのXSS攻撃の防止」セクションを参照してください)。 。多くの内部および管理システムでは、純粋なフロントエンドレンダリングが非常に適切です。ただし、高いパフォーマンス要件またはSEO要件のあるページの場合、HTMLのスプライシングの問題に直面する必要があります。

HTMLをエスケープする

HTMLのスプライシングが必要な場合は、適切なエスケープライブラリを使用して、HTMLテンプレートの挿入ポイントを完全にエスケープする必要があります。doT.js、ejs、FreeMarkerなどの一般的に使用されるテンプレートエンジンには、通常、HTMLエスケープのルールが1つだけあります。これは、文字&<> "'/をエスケープすることで、実際に特定のXSSを再生できます。保護機能は完全ではないため、XSS保護対策を改善するには、より完全で詳細なエスケープ戦略を使用する必要があります。たとえば、Javaプロジェクトでは、一般的に使用されるエスケープライブラリはorg.owasp.encoderです。次のコード引用は公式を使用しますorg.owasp.encoderからの指示。

<!-- HTML 标签内⽂字内容 --> 
<div><%= Encode.forHtml(UNTRUSTED) %></div> 
<!-- HTML 标签属性值 --> 
<input value="<%= Encode.forHtml(UNTRUSTED) %>" /> 
<!-- CSS 属性值 -->
 <div style="width:<= Encode.forCssString(UNTRUSTED) %>"> 
 <!-- CSS URL --> 
 <div style="background:<= Encode.forCssUrl(UNTRUSTED) %>"> 
 <!-- JavaScript 内联代码块 --> 
 <script> var msg = "<%= Encode.forJavaScript(UNTRUSTED) %>"; alert(msg); </script> 
 <!-- JavaScript 内联代码块内嵌 JSON --> 
 <script> var INITIAL_STATE = JSON.parse('<%= Encoder.forJavaScript(data.to_json) %>'); </script> 
 <!-- HTML 标签内联监听器 --> 
 <button onclick="alert('<%= Encode.forJavaScript(UNTRUSTED) %>');"> click me </button>
 <!-- URL 参 数 --> 
 <a href="/search?value=<%= Encode.forUriComponent(UNTRUSTED) %>&order=1#top"> 
 <!-- URL 路 径 --> 
 <a href="/page/<%= Encode.forUriComponent(UNTRUSTED) %>"> 
 <!--URL. 注意:要根据项⽬情况进⾏过滤,禁⽌掉 "javascript:" 链接、⾮法 scheme 等 --> 
 <a href='<%= urlValidator.isValid(UNTRUSTED) ? Encode.forHtml(UNTRUSTED) : "/404" %>'>link </a>

ただし、HTMLのエンコードは非常に複雑であり、対応するエスケープルールをさまざまなコンテキストで使用する必要があります。

DOMタイプのXSS攻撃を防ぐ

DOMタイプのXSS攻撃は、実際にはWebサイトのフロントエンドのJavaScriptコードが十分に厳密ではなく、信頼できないデータがコードとして実行されることです。.innerHTML、.outerHTML、document.write()を使用する場合は特に注意してください。信頼できないデータをHTMLとしてページに挿入しないでください。ただし、.textContent、.setAttribute()などを使用してみてください。

Vue / Reactテクノロジースタックを使用し、v-html関数とdangerlySetInnerHTML関数を使用しない場合、フロントエンドレンダリング段階でinnerHTMLとouterHTMLのXSSの隠れた危険を回避できます。

location、onclick、onerror、onload、onmouseoverなどのDOM内のインラインイベントリスナー、タグのhref属性、JavaScriptのeval()、setTimeout()、setInterval()などはすべて動作できます。コードとしての文字列。信頼できないデータが文字列にスプライスされてこれらのAPIに渡されると、セキュリティリスクが発生しやすいため、回避してください。

<!-- 内联事件监听器中包含恶意代码 --> 
![](https://awps-assets.meituan.net/mit-x/blog-images-bundle-2018b/3e724ce0.data:image/png,) 
<!-- 链接内包含恶意代码 --> 
<a href="UNTRUSTED">1</a> 
<script> 
// setTimeout()/setInterval() 中调⽤恶意代码 
setTimeout("UNTRUSTED") 
setInterval("UNTRUSTED") 
// location 调⽤恶意代码
location.href = 'UNTRUSTED' 
// eval() 中调⽤恶意代码 
eval("UNTRUSTED") </script>

これらのアイテムをプロジェクトで使用する場合は、信頼できないデータを文字列に連結しないようにしてください。

その他のXSS予防策

注意深くエスケープすることで、ページをレンダリングしてJavaScriptを実行するときにXSSが発生するのを防ぐことができますが、それでも開発上の注意だけに頼るだけでは十分ではありません。XSSのリスクと結果を減らすことができるいくつかの一般的なシナリオを次に示します。

1.コンテンツセキュリティポリシー

厳密なCSPは、XSS防止において次の役割を果たすことができます。

  • 複雑な攻撃ロジックを防ぐために、外部ドメインコードをロードすることは禁止されています。

  • 外部ドメインからの送信は禁止されています。Webサイトが攻撃された後、ユーザーデータが外部ドメインに漏洩することはありません。

  • インラインスクリプトの実行は禁止されています(ルールはより厳密であり、現在GitHubで使用されていることがわかっています)。

  • 不正なスクリプトの実行は禁止されています(新機能、Googleマップモバイルバージョンが使用されています)。

  • レポートを適切に使用すると、XSSを時間内に発見でき、問題をできるだけ早く修正するのに役立ちます。

2.入力コンテンツの長さの制御

信頼できない入力の場合、妥当な制限が必要です。XSSの起動を完全に防ぐことはできませんが、XSS攻撃の難易度を上げることができます。

3.その他の安全対策

  • HTTPのみのCookie:JavaScriptは、機密性の高いCookieを読み取ることを禁じられています。攻撃者は、XSS登録を完了した後でもこのCookieを盗むことはできません。

  • 検証コード:ユーザーになりすまして危険な操作を送信するスクリプトを防止します。

おすすめ

転載: blog.csdn.net/imagine_tion/article/details/110952024