Articles

10分でわかるCORS、XSS、CSRFの例

この記事は、既存のWebセキュリティ標準、最も一般的なWeb攻撃、およびそれらを防止する方法についての入口になるはずです。 最後に、Samy がどのように、そしてなぜ皆のヒーローであったのかがわかります(Rupert Murdoch を除いて、だと思いますが)。

CORS がドメイン website.com で利用可能なサーバーで構成されている場合、AJAX で要求されたそのドメインからのリソースは、その同じドメインから提供される資産から開始される必要があります。
CORS

言い換えると、domain-b.com で CORS を有効にし、ドメイン domain-b.com からの GET 要求のみを許可するように構成すると、domain-a.com でホストされている Web サイトでキャンバス内の https://domain-b.com/images/example.png で使用できる画像を使用したい場合、ほとんどの訪問者にはその画像が読み込まれないということです。
CORS によって保護されたリソースは、CORS policy を尊重しないツールまたはブラウザによって要求された場合でも利用できます。

CORS の設定

CORS はデフォルトで無効になっており、XHR で異なる起源のリソースにアクセスできない CORS を設定する適切なサーバー ハンドラが存在しないことを意味します。 基本的に、何もしないか、特定のドメインに対してのみ CORS を有効にすると、Web ブラウザが CORS policy.
を尊重しているため、リソースにアクセスしようとするすべての AJAX リクエストは拒否されるでしょう。 VueJS アプリケーションが http://localhost:8080 でホストされ、http://localhost:8000 で NodeJS サーバー アプリケーションにアクセスしようとすると、2 つの異なる ORIGINS (PROTOCOL, HOST, PORT の組み合わせ) であるために “No Access-Control-Allow-Origin header is present” が表示されます。

VueJS の開発モードでの CORS 問題のクールな修正は、次のように vue.config.js ファイルで devServer プロキシを設定することです。

module.exports = { ... devServer: { proxy: 'http://localhost:8000', }, ...}
フルスクリーン モードに入る フルスクリーン モードを終了

CORS を製品で設定するには、OPTIONS 要求に適したリスナーを追加します。 そのリスナーは、応答 200no body と共に送信しますが、希望する CORS ポリシーを定義する Headers を付加する必要があります。

Access-Control-Allow-Origin: https://domain-b.comAccess-Control-Allow-Methods: GET
Enter fullscreen mode Exit fullscreen mode

CORS を設定する方法の詳細については https://enable-cors.org/index.html を、CORS policyに深く潜るには https://livebook.manning.com/book/cors-in-action/part-1/

XSS

XSS とは Cross Site Scripting のことで、攻撃の種類としては注入型が挙げられます。 2017年にOWASPが確認した脆弱性トップ10のうち、7番目に挙げられています。 クロスサイトスクリプティングは、攻撃者が信頼できるWebサイトに悪意のあるスクリプトを注入する手法です。 (セクション更新、Sandorさんありがとう) このような攻撃は3種類あります。

  1. Stored XSS – 保護されておらずサニタイズされていないユーザー入力から発生する脆弱性で、データベースに直接保存され、他のユーザーに表示されます
  2. Reflected XSS – Webページで直接使用されるURLから保護されておらずサニタイズされていない値から発生する脆弱性
  3. DOM based XSS – 反射型XSSと類似しています。 Web ページで直接使用される URL から保護されておらず、サニタイズもされていない値です。 Stored XSS

    ここで、攻撃の例を挙げます。 攻撃者はあなたのウェブサイトに来て、コメントフィールドやユーザー名フィールドのような保護されていない入力フィールドを見つけ、期待される値の代わりに悪意のあるスクリプトを入力します。 その後、その値が他のユーザーに表示されるたびに、悪意のあるコードが実行されます。 悪意のあるスクリプトは、他のウェブサイトからお客様のアカウントにアクセスしようとしたり、DDoS攻撃などに巻き込まれたりする可能性があります。

    XSS example

    2.Reflected XSS

    Reflected XSSは、攻撃者がそのような脆弱性のあるページを発見したときに起こる攻撃で、例えば、

    想定していたURL。 https://mywebpage.com/search?q=javascript
    悪意のあるURL。 https://mywebpage.com/search?q=<script>alert('fortunately, this will not work!')</script>

    <body>...<div> showing results for keyword <script> document.write(window.location.href.substr(window.location.href.indexOf('q=') + 2))</script></div>......JavaScript results......</body>
    フルスクリーン モードに入る フルスクリーン モードを終了する

    発見後、攻撃者はユーザーにその悪質な URL をクリックさせるよう誘導し、ほら、そうだ。 ユーザーの機密データが搾取されます。

    geekforgeeks.com が提供する例で示す攻撃のライフサイクル:

    Reflected XSS example

    3. DOM ベースの XSS

    この種の攻撃は反射型と同じですが、悪質な URL 部分がサーバーにまったく送信されない点が違います。 上記の例では、

    期待される URL。 https://mywebpage.com/search?q=javascript
    malicious URL (reflected XSS): https://mywebpage.com/search?q=<script>alert('fortunately, this will not work!')</script>
    悪意のある URL (DOM-based XSS): https://mywebpage.com/search#q=<script>alert('fortunately, this will not work!')</script>

    違いは、?の代わりに#という文字が使用されていることです。 ブラウザは URL の # 以降の部分をサーバーに送信しないので、クライアント コードに直接渡します。

    保護

    ユーザーが入力でき、アプリで使用されるすべての値 (サーバー側またはクライアント側のいずれか) は信頼できないデータとして処理されるべきで、したがって使用前に処理しなければなりません! サーバー アプリとクライアント アプリで安全性チェックを行う必要があります。
    ドキュメントに示されているように、VueJS 自身は変数から値を取得する前に文字列をエスケープします。 新しいバージョンの Angular も暗黙的に文字列をエスケープするので、Vanilla JS、JQuery または同様のものを使用している場合、文字列エスケープを手動で実装する必要があります。

    信頼できないデータの処理には、以下に示す 3 つの最も一般的なアプローチがあり、処理する必要のあるフィールドの実際のタイプによって最適な方法が異なります。

    1.文字列検証

    検証は、ユーザーが一連のルールを定義し、次に進む前にこれらのルールを満たすために信頼されないデータを要求する方法です。 この方法は、数値値、ユーザー名、電子メール、パスワード、および具体的な構文規則のセットを持つ同様のフィールドに適しています。

    独自のバリデーターを書くことを検討する前に、フレームワークに既存のライブラリがないか確認します。 String escape

    Escapeメソッドは、ユーザーが句読点を使用できるようにする場合に便利なメソッドです。 このメソッドは文字列を調べて、< > のような特殊文字を探し、適切なHTML文字実体名に置き換えます。

    function escapeText(text) { return text.replace(/&/g, '&amp;') .replace(/</g, '&lt;') .replace(/>/g, '&gt;') .replace(/"/g, '&quot;')}
    Enter fullscreen mode Exit fullscreen mode

    繰り返しますが、自分で書く前に既存のライブラリをチェックしてください。

    3. String sanitization

    Sanitizing string is used when you allow some HTML tags in their comments, articles or similar as. サニタイズメソッドは、テキストを調べて指定したHTMLタグを探し、それらを削除します。 この方法を使用する最も一般的なライブラリの 1 つは Google Closure です。
    この方法はリソースが高く、有害と考えられるので、選択する前にもっと調べてください。

    Webブラウザー(どのバージョンから利用可能なソースがない、IEは2014年にこの問題を修正。

    XSSに関するより詳細な情報と、信頼できないデータを大量に回転させる場合にアプリケーションを適切に保護する方法については、XSS防止に関するOWASPチートシートをご覧ください。

    CSRF

    Cross Site Request Forgery (CSRF) は、悪意のある Web サイト、電子メール、ブログ、インスタント メッセージ、またはプログラムが、ユーザーの Web ブラウザに、そのユーザーが認証されている他の信頼できるサイトで不要なアクションを実行させると発生する攻撃の一種です。

    ATTACK

    例えば、ユーザーが保護されていない証券取引所のウェブアプリケーションにログインしていて、認証にセッションクッキーかJWTクッキーを使っているとしましょう。 攻撃者はまた、あなたのサービスを使用し、あなたのAPIがどのように動作するかをチェックすることができます。 攻撃者はユーザーを騙して、API https://www.stockexchange.com/users/withdraw?how_much=all&address=MY_ADDRESS (ひどいAPI設計。聞かないでください)にリクエストを送るスクリプトを実行させます。 リクエストは、リクエストごとに認証ペイロードを送信するブラウザから実行されるので、あなたのstockexchangeウェブサーバーは、ユーザーを正常に認証し、取引を実行し、騙されたユーザーは、バックグラウンドですべてが起こったので、それに気づくことなく、すべての残高を失うことになります。 視覚的表現(出典 miro.medium.com)
    CSRF attack

    保護

    幸いにも、このWeb攻撃を防ぐための実装が容易なパターンが存在します。 最も一般的なパターンの1つは、CSRF tokenの使用である。 基本的な手順は次のとおりです。

    1. 各ユーザーのリクエストに対して一意のトークン、いわゆる CSRF token を生成します。
    2. これをサーバーで安全に保管し、レスポンスのペイロードとしてユーザーに返送します。
    3. ユーザーが状態を変更する*リクエストを実行しようとすると、ペイロードとしてリクエストとともに CSRF token を送信する。
    4. サーバー側でそのリクエストを実行する前に、CSRF token が存在し、それが有効であるかどうかをチェックします。

      モダンなブラウザを使用する訪問者だけを対象にしている場合は、セッション Cookie の SameSite 属性に依存できます (Gergely に感謝)。

      より深く掘り下げるには、CSRF に関する OWASP のチートシートをチェックしてください。

      BONUS

      2005年に XSS の脆弱性を利用して MySpace を停止したワームの作者の Samy についての短いドキュメンタリーで、 MySpace の CSRF 防衛を通過しています。
      https://youtu.be/DtnuaHl378M

      Samy のワームに関する詳細
      https://samy.pl/myspace/tech.html