Closed18

CSRF周りメモ(with NextAuth)

shuntakashuntaka

/api/auth/sessionで返却される電文は、JWSの中にあるものから選ぶ事ができる

shuntakashuntaka

https://blog.hozi.dev/hozi576/articles/01fvpj77522jpcagxsget1ejqr#トークンの扱い検討

Authraizationヘッダー + localStorage
=> XSS怖い
Authraizationヘッダー + Cookie(not HTTP Only属性)
=> CSRF怖いのでAuthraizationヘッダーを使うと、CookieにHTTP only属性は使えない。。(XSS怖い)
Cookie認証 + Cookie(HTTP Only属性+Same site(Lax,Strict))
=> XSS,CSRF対策出来てそう

3つ目ってやっぱり、CSRF対策としては何もできてないよね。

shuntakashuntaka

NextAuthはここら辺/api/auth/sessionエンドポイントでJWSの平文を返却してくれる。
フロント側は、これをベアラートークンに設定して別APIを叩くからCSRF対策になる。

shuntakashuntaka

試しに、localhost:3002->example.comに対してGETリクエストをしているんだけどどういうわけかcookieが射出されない。SameSite=Lax;Secure;HttpOnly;で、fetchはこんな感じなんだけど、、

      const response = await fetch(
        'https://example.com/api/auth/session',
        {
          mode: 'cors',
          credentials: 'include',
        },
      );
      const data = await response.json();

リクエスト自体は単純リクエストなんだけどなぁ(一部改変)

curl 'https://example.com/api/auth/session' \
  -H 'accept: */*' \
  -H 'accept-language: ja,en-US;q=0.9,en;q=0.8' \
  -H 'origin: http://localhost:3002' \
  -H 'referer: http://localhost:3002/' \
  -H 'sec-ch-ua: "Chromium";v="112", "Google Chrome";v="112", "Not:A-Brand";v="99"' \
  -H 'sec-ch-ua-mobile: ?1' \
  -H 'sec-ch-ua-platform: "Android"' \
  -H 'sec-fetch-dest: empty' \
  -H 'sec-fetch-mode: cors' \
  -H 'sec-fetch-site: cross-site' \
  -H 'user-agent: Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Mobile Safari/537.36' \
  --compressed

shuntakashuntaka

およ?DevtoolでSameSite=LaxからNoneに変えたら飛んだわ。

shuntakashuntaka
GPT-4君の回答
SameSite=Lax の場合、クロスサイトのリクエストで Cookie が送信される状況は限定的です。主に次のような場合に Cookie が含まれます。

* リンクをクリックしてナビゲートする場合
* GET メソッドのフォーム送信の場合
* プリロード要求の場合

しかし、fetch や XMLHttpRequest でクロスサイトリクエストを行う場合、SameSite=Lax では Cookie は含まれません。これは、fetch や XMLHttpRequest によるリクエストが上記の条件に該当しないためです。

一方、SameSite=None に設定された場合、ブラウザは、リクエストの種類に関係なく、クロスサイトリクエストで Cookie を送信します。ただし、これにより CSRF のリスクが高まるため、他のセキュリティ対策を適切に実装することが重要です。

例として、fetch を使って SameSite=Lax の Cookie を送信しようとしても、ブラウザは Cookie を含めずにリクエストを送信します。これが、SameSite=None では Cookie が送信されるが、SameSite=Lax では送信されない理由です。

shuntakashuntaka

このように strict だとクロスオリジンなリクエストではCookieが送信されないため、CSRF攻撃の緩和につながる。
一方でリンクを辿るだけでもCookieが送信されないため、それはそれで不便。

shuntakashuntaka

一方でリンクを辿るだけでもCookieが送信されないため、それはそれで不便。

これってどんなケースなんだろう?イメージできない。

shuntakashuntaka

例えば、Aサイトでログイン中だった場合に、Bサイト上に用意されたAサイトへのリンクをクリックした場合、ログイン状態でページの遷移が行われます

ページ遷移するときに認証情報が抜けてるってこと?そんなことあるのか。

Aサイトでログイン中だった場合に、Bサイト上に用意されたAサイトへのリンクをクリックした場合、Aサイトにクッキーが送られませんので、Aサイトに対して未ログイン状態の扱いでページの遷移が行われます。当然、この動作は不便な面もあります。

実体験としてあったかなぁ、、
NextAuthの場合遷移したら、/api/auth/sessionをクライアントから叩くから再現しないのかな。
cookie情報をもとに認証情報のレンダリングして返している場合は、ワークしないかもね。

shuntakashuntaka

結局Aタグってクロスドメインのリクエストなんだよね

aサイトbサイトがあって、bにログイン済みの場合、Aタグでbサイトに遷移するときaからbにリクエストしてるわけだし。
そりゃstrictならcookie飛ばないや。

nextauthそこらへんクライアントサイドでAPI叩くことで解消してるようにみえるけど、、詳しいところは謎

shuntakashuntaka
  • GETはクロスドメインでも実行されてしまう(SameSite=strictにすれば防げるが、Google検索からの初回リクエストでcookieが飛ばずログアウト状態になるので実質)
    • GETで重要な処理をしない
    • Origin検証、CSRFトークンで対策をする
このスクラップは4ヶ月前にクローズされました