Closed5

Cookie

kondokondo

Same Origin Policy(同一オリジンポリシー)

◯同一オリジンの定義

プロトコル、ポート番号、ホストが等しい場合のみ同じオリジンとみなされる。

◯同一オリジンポリシーの制限の対象になるもの/ならないもの

  • 制限の対象になる
    • JavaScriptでの非同期通信、など
  • <script>で読み込まれたJavascript
  • <link>で読み込まれたCSS、など

◯制限の挙動

シンプルリクエストに該当する場合

  • ブラウザ側でサーバーから取得したリソースへのアクセスが制限される
  • どのような場合にシンプルリクエストに該当するかは別途参照
Access to XMLHttpRequest at 'http://localhost:8080/ping' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

シンプルリクエストに該当しない場合

  • プリフライリクエストが本来のリクエストの前に実行され、当該リクエストは実行されない

◯同一オリジンポリシーの目的

例えば、ユーザーが悪意のあるwebサイトを訪問する。悪意のあるwebサイトは訪問時に、ユーザーが使用している正規のサイト(もしかしたら認証済)へリクエストを実行する。こうして、そのリクエストから得たリソースを悪意のあるwebサイトは入手することができる。

◯同一オリジンポリシーで防ぐことができない問題

例えば、シンプルリクエストの場合は、正規のwebサーバーのリソースの操作を防ぐことはできない。リソースを入手することはできないが、データベースなどは操作できてしまう。これらの対策として、CSRFの仕組みが必要になる。※後述
プリフライリクエストが伴う場合においても、当該リクエストはキャッシュされるのでCSRFの仕組みは必要と考えられる(Access-Control-Max-Age)。

◯クロスオリジンで通信したい

フロントとバックエンドでそれぞれサーバーを立てており、オリジン(≒ドメイン)が異なる構成は多い。こうした場合は、オリジン間リソース共有 (CORS)というブラウザの仕組みを用いる。後述

https://developer.mozilla.org/ja/docs/Web/Security/Same-origin_policy

kondokondo

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

クロスオリジンにおいて、同一オリジンポリシーの制限を回避するための方法。

シンプルリクエストの場合

リクエスト

Originヘッダーを付与する。これはブラウザが自動で行ってくれる。

Origin: https://foo.example

レスポンス

サーバー側で、Access-Control-Allow-Originヘッダーを付与する。

Access-Control-Allow-Origin: https://foo.example

シンプルリクエストではない場合(プリフライトリクエスト)

本来のリクエストの前にOPTIONSメソッドによるプリフライトリクエストが実行される。

リクエスト

ブラウザが自動で付与する。

Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-PINGOTHER, Content-Type

レスポンス

特筆すべきは、Access-Control-Max-Ageでプリフライトのレスポンスをキャッシュできること。よって、全てのリクエストの度にプリフライトリクエストを実行する必要はない。

Access-Control-Allow-Origin: https://foo.example
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
Access-Control-Max-Age: 86400

https://developer.mozilla.org/ja/docs/Web/HTTP/CORS

kondokondo

Cookie(資格情報を伴うリクエスト)

Cookieを用いてセッションを管理している場合はさらに知るべきことがある。

シンプルリクエストの場合

リクエスト

クロスオリジンでは、Cookieを送信するために以下の指定が必要。

const invocation = new XMLHttpRequest();
invocation.withCredentials = true;

レスポンス

以下の指定がないと、ブラウザはレスポンスを拒否する。

Access-Control-Allow-Credentials: true

シンプルリクエストではない場合(プリフライトリクエスト)

プリフライトリクエストには資格情報を含めてはならない。

レスポンス

プリフライトリスクエストへのレスポンスに以下を指定する。

Access-Control-Allow-Credentials: true 
kondokondo

CSRF攻撃

攻撃手法

罠サイトにフォームを用意しておき、ユーザーがフォームを送信することで、攻撃者の任意のリクエストをユーザーが実行してしまう。

対策

  • SameSite Cookie
    • クロスオリジンの通信が必要なアプリケーションではNone設定するので利用できない
  • CORS
    • 前述したようにシンプルリクエストの場合はサーバー側のリソースを操作されてしまうため、完全な対策にはならない
  • トークン
    • HTMLレンダリング時にhiddenでトークンを埋め込み、リクエスト時に"添付"する
    • サーバーがトークンの検証をすることで、同一セッションでのリクエストだと判定できる
    • 大概、この手法を取ることが多いという認識

SPA

先のトークンによる対策は、サーバーサイド側で HTMLを生成しないSPAでは使用できない。SPAでは以下の手法が考えられる。

  • セッションを確認するような API から Cookie 経由で渡す
  • CSRF トークン取得用の API から json として返す

これらが何故CSRFの対策になるのか。罠サイトがAPIを実行してトークンを手に入れた上で、ユーザーにフォームのリクエストを実行させれば同じでことではないのか。しかしこれは以下の条件を満たせば不可能である。

  • 正規サイトでのみ、Access-Control-Allow-Credentials: trueをヘッダーに設定する

これにより、罠サイトはAPIを実行してもトークンを取得することはできない。

https://zenn.dev/kazu1/articles/ba8c7a2a2292fd
https://zenn.dev/leaner_dev/articles/20210930-rails-api-spa-csrf

kondokondo

Cookieの取り扱い

ここまでの議題とは少しずれるが、Cookieの取り扱いについて整理しておく。

  • Secure属性
    • HTTPSのリクエストでのみサーバーに送信される
  • HttpOnly属性
    • JavascriptのDockument.cookieAPIによってアクセスされなくなる
    • セッションのCookieには付与するのが推奨
    • XSS攻撃を緩和する
  • Domain属性
    • Cookieを受信することができるホストを指定する
    • サーバーがDomainを付与しなかった場合は、サブドメインが除外される
    • 裏を返せば、サーバーが付与すればサブドメインにも送信が可能
  • Path 属性
    • 興味ないので省略
  • SameSite 属性
    • Strict, Lax, Noneのいずれかの値を設定する
    • Noneを設定する場合は、Secure属性の指定も必要である(つまり、HTTPSの必要がある)

マイクロサービスにおけるCookieの扱い

現在、サブドメインで複数のマイクロサービスを扱うアプリケーションを構築している。
(example.com、serviceA.example.com、serviceB.example.com、、、)

以下の要件を満たしたい

  • Domain属性がexample.comのCookieをserviceA(or B).example.comに送信したい
  • serviceA(or B).example.comのサーバーで、 Domain属性をexample.comに設定してSet-Cookieしたい

結論としては、いずれも可能である。
以下を準拠する。

  • 各サーバーは、必ずDomain属性を明示的に付与すること (後方一致)
  • SameSiteはNoneに設定する (必然的にHTTPSに限定)

https://qiita.com/HAYASHI-Masayuki/items/209039717c15834603d8
https://qiita.com/il-m-yamagishi/items/9aad5737c80d5bfd5eb8

このスクラップは2024/01/06にクローズされました