JSホモロジー戦略とCSRFの詳細な説明

JSホモロジー戦略とCSRFの詳細な説明

概要

この記事には主に 3 つのキーワードが含まれています。

  • 同一生成元ポリシー (SOP)
  • クロスサイトリクエストフォージェリ (CSRF)
  • クロスオリジンリソース共有 (CORS)

同一生成元ポリシー (SOP)

相同

まず、同じオリジンが何を意味するのかを説明します。プロトコル、ドメイン名、ポートがすべて同じであり、それが同じオリジンです。

URL相同
https://niconico.comベンチマーク
https://niconico.com/spirit o
https://sub.niconico.com/spirit x
http://niconico.com/spirit x
https://niconico.com:8080/spirit x

制限

クロスドメインの問題が発生する理由は、SOP のさまざまな制限によるものです。しかし、具体的に何が制限されているのでしょうか?

SOP が「非同一オリジンのリソースの取得を制限する」という意味だと言うなら、それは間違いです。最も単純な例は、画像、CSS、JS ファイルなどのリソースを参照するときにクロスドメインが許可されることです。

SOP が「クロスドメイン リクエストを禁止する」という意味だと言う場合、これも間違いです。本質的に、SOP はクロスドメイン リクエストを禁止するのではなく、リクエスト後のリクエストの応答を傍受します。これにより、後述するCSRFが発生します。

実際、SOP は単一の定義ではなく、状況に応じて異なる解釈が行われます。

  • クッキー、DOM、JavaScript の名前付きスコープを制限する
  • iframe、画像、その他のリソースに対するコンテンツ操作を制限する
  • Ajaxリクエストの制限、より正確にはAjaxレスポンス結果の操作の制限は、基本的に前のものと同じです。

実際のアプリケーションで遭遇する可能性のある 3 つの例を以下に示します。

  • Ajaxを使用して他のクロスドメインAPIをリクエストする、最も一般的な状況、フロントエンド初心者の悪夢
  • iframeは親ページと通信し、発生率は比較的低く、解決策は理解しやすい
  • クロスドメイン画像(<img>からの画像など)を操作する場合、キャンバス上の画像を操作するとこの問題が発生します。

SOPがない場合:

  • ブラウザで複数のタブを開くと、データが漏洩します。
  • iframeを使用して銀行のウェブサイトを開くと、ウェブサイトのコンテンツを自由に読み取ることができ、ユーザーが入力したコンテンツを取得できます。
  • より攻撃的なCSRF

クロスドメインをバイパス

SOP はセキュリティをもたらしますが、ドメイン間の要求がある場合があるため、ある程度のトラブルも生じます。スペースの制限とインターネット上に関連記事が多数あるため、ここではクロスドメインの問題の解決策について詳しく説明せず、いくつかのキーワードのみを示します。

アヤックスの場合

  • jsONPの使用
  • バックエンド CORS 構成
  • バックエンドリバースプロキシ

iframeの場合

  • 情報を伝達するにはlocation.hashまたはwindow.nameを使用します
  • postMessageの使用

クロスサイトリクエストフォージェリ (CSRF)

簡単な説明

CSRF(クロスサイトリクエストフォージェリ)は一般的な攻撃方法です。これは、A ウェブサイトが正常にログインした後、Cookie が正常に保存されることを意味します。他のウェブサイト B は、何らかの方法で A ウェブサイトのインターフェイスを呼び出して操作し、A インターフェイスは要求時に自動的に Cookie を取得します。

前述のように、SOP は htmltag を通じてリソースをロードすることができ、また、SOP はインターフェース要求をブロックせず、要求結果を傍受します。CSRF はこれら 2 つを利用します。

したがって、SOP は CSRF を防止する方法として使用することはできません。

GET リクエストの場合、<img> 内に直接配置して、誰にも気付かれずにクロスドメイン インターフェイスをリクエストできます。

POST リクエストの場合、多くの例ではフォーム送信が使用されます。

<form action="<nowiki>http://bank.com/transfer.do</nowiki>" method="POST">
  <input type="hidden" name="acct" value="マリア" />
  <input type="hidden" name="金額" value="100000" />
  <input type="submit" value="私の写真を見る" />
</フォーム>

最終的に、これらの 2 つの方法では、リクエストが HTML によって制御され、JS を使用して結果を直接操作できないため、クロスドメインが報告されません。

SOP と ajax

ajax リクエストの場合、データを取得した後、必要に応じて js 操作を実行できます。この時点では、同一生成元ポリシーにより応答は阻止されますが、リクエストは引き続き行われます。応答のインターセプションを実行するのはバックエンド プログラムではなくブラウザだからです。実際、リクエストはサーバーに送信され、結果が返されていますが、セキュリティ ポリシーにより、ブラウザーは js 操作の続行を許可しないため、「CORS ポリシーによってブロックされました: 要求されたリソースに 'Access-Control-Allow-Origin' ヘッダーが存在しません」というよく知られたメッセージが報告されます。

したがって、同一オリジンポリシーは CSRF を防止する方法として使用することはできないことを再度強調しておきます。

ただし、CSRF を防止できる例外があります。ブラウザはすべてのリクエストが正常に送信されることを許可しません。上記の状況は単純なリクエストに限定されます。関連する知識については、以下の CORS セクションで詳しく説明します。

CSRF対策

SOP は CSRF によって悪用されるので、本当に役に立たないのでしょうか?

いいえ! SOP が Cookie の名前の範囲を制限していることを覚えていますか? リクエストによって Cookie が自動的に取得されますが、攻撃者は Cookie の内容自体を取得することはできません。

したがって、CSRF に対処するための考え方は、トークンを Cookie に書き込み、リクエストを行うときにそのトークンをクエリ、本文、またはヘッダーに含めることです。リクエストがサーバーに到着し、トークンをチェックします。トークンが正しければ、そのリクエストは Cookie を表示できるドメインから送信されたものであるはずです。CSRF はこれを実行できません。 (この方法はフロントエンドとバックエンドを分離するために使用され、バックエンドのレンダリングはDOMに直接書き込むことができます)

サンプルコードは次のとおりです。

var csrftoken = Cookies.get('csrfToken')

関数csrfSafeMethod(メソッド) {
  // これらの HTTP メソッドは CSRF 保護を必要としません
  /^(GET|HEAD|OPTIONS|TRACE)$/.test(メソッド) を返します
}
$.ajaxSetup({
  送信前: 関数(xhr, 設定) {
    if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
      xhr.setRequestHeader('x-csrf-token', csrftoken)
    }
  },
})

クロスオリジンリソース共有 (CORS)

クロスドメインはブラウザの制限ですが、サーバーが CORS 関連の構成を設定すると、サーバーに返される情報ヘッダーに Access-Control-Allow-Origin が追加されます。ブラウザは、このフィールドの値が現在のオリジンと一致することを確認すると、クロスドメイン制限を解除します。

HTTP/1.1 200 OK

日付: 2016 年 4 月 24 日 (日) 12:43:39 GMT

サーバー: Apache

アクセス制御許可元: http://www.acceptmeplease.com

キープアライブ: タイムアウト=2、最大=100

接続: キープアライブ

コンテンツタイプ: application/xml

コンテンツの長さ: 423

CORS には 2 種類のリクエストがあります。

簡単なリクエスト

  • リクエストメソッドは GET、POST、または HEAD です。
  • Content-Type は application/x-www-form-urlencoded、multipart/form-data、または text/plain に設定されます

上記の 2 つの条件を満たすすべてのリクエストは CORS シンプル リクエストです。単純なリクエストはサーバーに直接送信されるため、CSRF が発生する可能性があります。

事前飛行リクエスト

単純なリクエストの要件を満たさないリクエストでは、まずプリフライト リクエストを送信する必要があります。ブラウザは、実際のリクエストを行う前に、現在のソースが CORS ターゲットを満たしているかどうかをサーバーに問い合わせる OPTION メソッドを使用してリクエストを送信します。正式なリクエストは、検証に合格した後にのみ送信されます。

たとえば、application/json を使用してパラメータを渡す POST リクエストは単純ではないリクエストであり、事前チェック中にインターセプトされます。

たとえば、PUT メソッド リクエストが使用される場合、事前チェック リクエストも送信されます。

CSRF を防ぐことができる上記の例外は、事前チェック リクエストを指します。クロスドメイン リクエストの事前チェックが成功した場合でも、実際のリクエストは送信できないため、CSRF が成功しないことが保証されます。

CORS と Cookie

同じドメインとは異なり、クロスドメイン CORS リクエストは、デフォルトでは Cookie と HTTP 認証情報を送信しません。フロントエンドとバックエンドの両方で、構成に Cookie を含めるようにリクエストを設定する必要があります。

このため、axios では CORS リクエストを行うときに withCredentials: true を設定する必要があります。

以下は、node.js バックエンド koa フレームワークの CORS 設定です。

/**
 * CORSミドルウェア
 *
 * @param {Object} [オプション]
 * - {String|Function(ctx)} origin `Access-Control-Allow-Origin`、デフォルトはリクエスト Origin ヘッダー
 * - {文字列|配列} allowMethods `Access-Control-Allow-Methods`、デフォルトは 'GET、HEAD、PUT、POST、DELETE、PATCH'
 * - {文字列|配列} exposeHeaders `Access-Control-Expose-Headers`
 * - {文字列|配列} allowHeaders `アクセス制御許可ヘッダー`
 * - {文字列|数値} maxAge `Access-Control-Max-Age`(秒単位)
 * - {ブール値} 資格情報 `Access-Control-Allow-Credentials`
 * - {Boolean} keepHeadersOnError エラーが発生した場合に `err.header` に設定されたヘッダーを追加します
 * @return {Function} corsミドルウェア
 * @api パブリック
 */

以上がJS Same-Origin PolicyとCSRFの詳しい説明です。JS Same-Origin PolicyとCSRFの詳細については、123WORDPRESS.COMの他の関連記事もご覧ください。

以下もご興味があるかもしれません:
  • JavaScript ホモロジー ポリシーとクロスドメイン アクセスの例の詳細な説明
  • JS で実装された Ajax とホモロジー戦略 (例の説明)
  • jsホモロジー戦略の詳細な説明
  • js を使用して 2 つの HTML ウィンドウ間で通信する方法
  • JavaScriptのEventBusはオブジェクト間の通信を実装します
  • vue websocket nodeJS を使用したリアルタイム通信の落とし穴についての簡単な説明
  • Vue.js コンポーネント通信のカスタムイベントの詳細な説明
  • SpringBoot は jsonp クロスドメイン通信メソッドの例を実装します
  • Vue.js の子コンポーネントが親コンポーネントと通信する方法の詳細なコード例
  • SockJS を使用して vue で webSocket 通信を実装するプロセス
  • JavaScript で同一オリジン通信を実装する方法

<<:  Dockerのクイックガイド

>>:  MySQL5.7.17 winx64 インストール バージョン構成方法 Windows Server 2008 R2 でのグラフィック チュートリアル

推薦する

axiosのシンプルなカプセル化と使用例コード

序文最近、プロジェクトを構築しているときに、リクエストのカプセル化について考え、どのようにカプセル化...

SQL IDENTITY_INSERT ケーススタディ

一般的に、データ テーブル内の列を ID 列として設定すると、ID 列の表示値を手動で ID 列に挿...

jQueryはネストされたタブ機能を実装します

この記事では、ネストされたタブ機能を実装するためのjQueryの具体的なコードを参考までに紹介します...

要素を中央に配置するための配置方法 (Web ページ レイアウトのヒント)

ブラウザウィンドウの中央に要素を配置する方法まず、コード ブロックを示します。すでにコードを理解して...

フィールドを結合するSQL関数

最近、関連テーブル内のすべてのフィールドをクエリし、それらを 1 つのフィールドに再グループ化する必...

jsを使用してサーバーに写真をアップロードする

この記事の例では、参考のために画像をサーバーにアップロードするためのjsの具体的なコードを共有してい...

MySQL 5.7.33 インストール プロセスの詳細な図解

目次インストールパッケージのダウンロードインストール環境変数の設定インストールが成功したか確認する記...

InnoDB タイプの MySql によるテーブル構造とデータの復元

前提条件: データベースを復元するために必要な .frm ファイルと .ibd ファイルを保存します...

表の最初の行と最初の列を固定し、適応型ウィンドウを実現するための CSS の例コード

今日のキャンパス採用筆記試験では、固定された最初の行と最初の列を実装し、幅をウィンドウの変更に適応さ...

Nginx 外部ネットワーク アクセス イントラネット サイト構成操作

背景:サイトはフロントエンドとバックエンドから分離されています: vue+springbootフロン...

CentOS の MySQL に MariaDB をインストールするときに発生する方法と問題

以前にインストールしたmariadbを削除する1. rpm -qa | grep mariadb を...

HTML+CSS3+JSで実装されたドロップダウンメニュー

成果を達成する html <div class="コンテナ"> &l...

Nginx操作応答ヘッダー情報の実装

前提条件: ヘッダー情報操作をサポートするには、ngx_http_headers_module モジ...