CSRF対策 December 2023
Refferences
- Cross-Site Request Forgery Prevention - OWASP Cheat Sheet Series
- 安全なウェブサイトの作り方 - 1.6 CSRF(クロスサイト・リクエスト・フォージェリ) | 情報セキュリティ | IPA 独立行政法人 情報処理推進機構
- 今時の CSRF 対策ってなにをすればいいの? | Basicinc Enjoy Hacking!
- SPA + WebAPI でアプリケーションを構築するときの CSRF 対策についてのメモ
- 2022年1月においてCSRF未対策のサイトはどの条件で被害を受けるか | 徳丸浩の日記
- 大量の「はまちちゃん」を生み出したCSRFの脆弱性とは? - ITmedia エンタープライズ
- Sec-Fetch-Site - HTTP | MDN
- "Sec-Fetch-Site" | Can I use... Support tables for HTML5, CSS3, etc
- Forbidden header name - MDN Web Docs Glossary: Definitions of Web-related terms | MDN
- Using HTTP cookies - HTTP | MDN
- "samesite" | Can I use... Support tables for HTML5, CSS3, etc
- 3PCA 21 日目: SameSite Cookie | blog.jxck.io
- Cross-Origin Resource Sharing | Can I use... Support tables for HTML5, CSS3, etc
- Mobile & Tablet iOS Version Market Share Japan
結論
-
Sec-Fetch-Site: same-origin
orSec-Fetch-Site: same-site
の確認 - Cookieの
samesite=lax
orsamesite=strict
(Safari on iOS v16.4 or later を許容できれば) この2点で十分そう。
Sec-Fetch-Siteに絞ってはダメなら↓が最適解ぽい。
- CORS + 全POSTリクエストを単純リクエストで無いことを強制する
- Cookieの
samesite=lax
orsamesite=strict
CSRF
Cross-Site Request Forgery
典型例
- 罠サイトを踏んだら、SNSに自分で投稿してしまう
- 罠サイトを踏んだら、匿名掲示板に投稿してしまう
- 自サイトのXSSから、意図しないリソースを作成してしまう
対象はブラウザユーザー
CORS
Cross-Origin Resource Sharing
セッションベース認証とトークンベース認証
認証なし: CSRF起きる
セッションベース認証: CSRF起きる
トークンベース認証: CSRF起きない
CookieのSameSite Attribute
主眼は 3rd Party Cookieを消していくところ(に見える)
CSRFの緩和にも役立つ
cons
- 認証なしの場合は意味がない
CSRF token (古典的なやつ)
POSTの前の画面のHTMLにCSRF tokenがあって、それを一緒にPOSTする。
サーバー側で受け取ったCSRF tokenを検証する。
CSRF token (今使うなら)
はじめのレスポンスにCSRF tokenを含むか、CSRF token用エンドポイントを用意して、クライアント側はそれを叩く。以降のリクエストに取得したCSRF tokenを合わせて送る。
サーバー側で受け取ったCSRF tokenを検証する。
Referer
リファラが自分のサイトかサーバー側で検証する。
cons
セキュリティソフトや環境によっては、Referer を残さない環境がある
CORS + 全リクエストを単純リクエストで無いことを強制する
request headerに APP-FROM-WEB: 1
をつけるなどで単純リクエストではなくする。
サーバー側でAPP-FROM-WEB: 1
を検証して、単純リクエストではないことを確定させる。
pros
クライアント側サーバー側で一番実装が単純
cons
全リクエストでpriflightが走り、2度リクエストしてまあまあ無駄
Sec-Fetch-Site: same-origin or Sec-Fetch-Site: same-site
サーバー側で受け取ったSec-Fetch-Siteを検証する。
pros
- サーバー側だけで良い
- CSRF用の機能といえる
cons
- Safari on iOS v16.4 or later
- Sec-Fetch-Site を使わない or 実装していないブラウザでも、CSRFに脆弱になってもいいから使えてほしい、けどそうできない
CORS + 全POSTリクエストを単純リクエストで無いことを強制する
前提として、GET, HEADで副作用があってはいけない。
POSTのrequest headerに APP-FROM-WEB: 1 をつけるなどで単純リクエストではなくする。
サーバー側でPOSTのときはAPP-FROM-WEB: 1を検証して、POSTが単純リクエストではないことを確定させる。
不特定多数ユーザー向けにはこれが最適解にみえる。
pros
- CORSはほぼすべてのブラウザで使える
- CORSに対応して無くてもheaderが送れれば使える
cons
- CORSはCSRF対策に使えるけど、厳密にはそれ用途ではない?
CORSハマったところ
preflightなしにリクエストきた場合、ブラウザにはCORSエラーが返るが、処理自体は一通り通ってしまう。(これはサーバー側実装によるかもしれない)
全リクエストがpreflight通る場合は、そこで止まる