CSRF対策のやり方、そろそろアップデートしませんか / Update your knowledge of CSRF protection
by
YAMAOKA Hiroyuki
×
Copy
Open
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Slide 1
Slide 1 text
2024年3月8日 / PHPerKaigi 2024 • Day 1 合同会社テンマド 山岡広幸 CSRF対策のやり方、 そろそろアップデートしませんか
Slide 2
Slide 2 text
自己紹介 - 山岡広幸(やまおかひろゆき) - Bluesky: @hiroy.kotori.style - X: @hiro_y - PHPは大学のころ、バージョンは3のころから - 最近はSvelteKitとかも
Slide 3
Slide 3 text
会社をやっています - 合同会社テンマド - 代表社員/2024年6月で10周年! - 現在のメンバーは総勢で5名 - PHPエンジニア採用募集中!!
Slide 4
Slide 4 text
お仕事先 - 株式会社イノベーター・ジャパン - 社外CTO/神宮前・柏・茅ヶ崎 - 株式会社GoQSystem - 技術顧問/京橋・岩国・広島 - 広島で勉強会やるぞ…!
Slide 5
Slide 5 text
さて、CSRF (発音: CSRF or “sea-surf")
Slide 6
Slide 6 text
Cross Site Request Forgery
Slide 7
Slide 7 text
Cross またいだ Site サイトを Request リクエストの Forgery 偽造行為
Slide 8
Slide 8 text
IPAによる情報提供 - 安全なウェブサイトの作り方 - 1.6 CSRF(クロスサイト・リクエスト・フォージェリ) - 共通脆弱性情報データベース - https://jvndb.jvn.jp/ja/cwe/CWE-352.html - 「脆弱なコード例」としてPHPのコードが載っている
Slide 9
Slide 9 text
CSRFの基本構造 出典: https://www.ipa.go.jp/security/vuln/websecurity/csrf.html
Slide 10
Slide 10 text
雑な解説 - 本来のサイトの正規ページを模倣した 悪意あるサイトの罠ページを用意 - 悪意あるサイトから本来のサイトに向けてリクエスト送信 - 意図しないパラメーターを含む等 攻撃的リクエスト(状態変更)を送ってしまう…
Slide 11
Slide 11 text
防御方法 1⃣ トークン
Slide 12
Slide 12 text
古来より伝わる防御方法 - サーバー側で予測不能な文字列(トークン)を生成、 セッションに保存し、トークンをフォームに埋め込み表示 - リクエストの際にトークンを含めるようにする - サーバー側でセッションで保持していたトークンと照合
Slide 13
Slide 13 text
つまりこう
Slide 14
Slide 14 text
Laravelの場合 - CSRF Protection - Laravel 10.x - Bladeテンプレートでは @csrf と書けばOK -
Slide 15
Slide 15 text
トークン方式のメリット - 確実に防御することができる - 数多くのフレームワークで採用されている - Symfony、Ruby on Rails、Play Framework等 - (フレームワークを使っていれば)お手軽に導入可能
Slide 16
Slide 16 text
トークン方式のデメリット - (よく考えると)シンプルな実装とは言いがたい - トークンを保管するストレージが必要 - セッション用Cookieを改竄されてしまうと… - (XSS等がある時点でCSRFどころではないのでは…
Slide 17
Slide 17 text
さて、最近の話
Slide 18
Slide 18 text
アップデート していきましょう!
Slide 19
Slide 19 text
このトークのきっかけ - SvelteKitを触っていた - あれ、CSRF対策とかどうするんだろう… hidden項目とか必要じゃないんだっけ?? - CookieのSameSite属性とかあったような… - よい機会なので調べてみよう!!
Slide 20
Slide 20 text
防御方法 2⃣ SameSite属性を 指定したCookie
Slide 21
Slide 21 text
CookieのSameSite属性 - 【参考】 Site: 公開接尾辞リスト + 直前のドメイン名 - 指定できる値 - Strict: 同一siteの場合のみ送信 - Lax: 異なるsite間の場合、GETの場合だけ送信 - None: どんな場合でも送信
Slide 22
Slide 22 text
つまりこう
Slide 23
Slide 23 text
ブラウザごとに挙動に差異が… - デフォルト(=指定しない場合)の挙動が異なるので、 明示的にきちんと指定しよう - Chrome: Laxと同様だが、Cookieセット後2分間は POSTの場合でもCookieが送られる(Lax+POST) - Safari: None。「サイト越えトラッキングを防ぐ」 設定によりそもそも送られないことも
Slide 24
Slide 24 text
SameSite属性利用のメリット - セッション用CookieにSameSite=Laxを指定する だけで防御を行うことができる(Strictでも可) - 異なるsiteからは送信されなくなるから お手軽でよさそう、なんだけど
Slide 25
Slide 25 text
SameSite属性利用のデメリット - 古いブラウザはSameSite属性に対応していない - GETの場合はCookieが送られてしまう(Laxの場合) - そもそもGETで状態変更できるリクエストは… - Cookieを利用しないアプリケーションでは使えない - 認証不要な場合とか
Slide 26
Slide 26 text
さらに中間者攻撃のリスクも - “http://example.com" と “https://example.com" は同一siteなのか問題 - ブラウザによって考え方が違う… - HTTPな経路でリクエストが改竄されてしまった場合、 攻撃を受けてしまう可能性がある
Slide 27
Slide 27 text
SameSite属性利用まとめ - Lax、Strictのいずれかを明示的に指定 - 中間者攻撃への対策としてはHSTSを有効化 (includeSubdomainsの指定を忘れずに) - 防御として、緩和はできるが穴があることがわかった - さて… 🤔
Slide 28
Slide 28 text
防御方法 3⃣ Originヘッダーを利用
Slide 29
Slide 29 text
Originヘッダーとは - ブラウザがリクエスト時にOriginヘッダーを付与する - https://developer.mozilla.org/ja/docs/ Web/HTTP/Headers/Origin - 同一Origin間のリクエストでは、 GET・HEADの場合は付与されないので注意
Slide 30
Slide 30 text
Originヘッダーを利用した防御 - リクエストのOriginヘッダーの値と サーバー側のホスト情報を照合 - 一致すれば正規なリクエスト、 一致しなければ不正なリクエストとして拒否 - そもそも送られてこなかったら拒否するようにする
Slide 31
Slide 31 text
つまりこう
Slide 32
Slide 32 text
Originヘッダー利用のメリット - 簡単、シンプルな手順で防御が可能 - 古いブラウザにも対応できる - Originヘッダーなしの場合、不正とみなす 最近採用されることが増えている
Slide 33
Slide 33 text
SvelteKitの例 - https://kit.svelte.dev/docs/con fi guration#csrf - https://github.com/sveltejs/kit/issues/72 - 最初はトークン方式(いろいろ)が提案されるが、 Originヘッダーの利用で十分では?と結論
Slide 34
Slide 34 text
Next.jsの例 - How to Think About Security in Next.js | Next.js (Server Actionsに関する記事) - Same-Site Cookieがブラウザで デフォルトで付くから防げるとか 🤔 (指定しようね) - HostとOriginのチェックも追加でやるよ、とのこと
Slide 35
Slide 35 text
Honoの例 - https://hono.dev/middleware/builtin/csrf - https://github.com/honojs/hono/pull/1823 - SvelteKitでの議論を参考に実装した、とのこと - v4も出たし注目のフレームワーク
Slide 36
Slide 36 text
防御方法 4⃣ Sec-Fetch-* ヘッダーを利用
Slide 37
Slide 37 text
Sec-Fetch-* ヘッダーとは - Sec-Fetch-Dest: fetchするリソースを使う形態 (documentとかimageとかfontとか) - Sec-Fetch-Mode: リクエストの形態 (navigateとかcorsとか) - Sec-Fetch-Site: リクエスト元Originとの関係 (same-originとかcross-siteとか)
Slide 38
Slide 38 text
Sec-Fetch-* ヘッダーを利用 - Sec-Fetch-Siteがsame-originであること - Sec-Fetch-Modeがnavigateであること - Sec-Fetch-Destがdocumentであること - 以上をそれぞれ検証すればよさそう
Slide 39
Slide 39 text
Sec-Fetch-* ヘッダー利用の特徴 - Originヘッダーの利用と同様にシンプルに防御可能 - ただし、ブラウザのサポートが割と最近 - https://caniuse.com/?search=Sec-Fetch- Site - 使えるけど、Originヘッダー利用で必要十分ではある
Slide 40
Slide 40 text
結局どうすれば いいの?
Slide 41
Slide 41 text
オススメパターン - 2⃣ セッション用CookieにはSameSite属性を指定 - __HOST- pre fi xを付けられるとなおよい - 3⃣ サーバー側ではOriginヘッダーをチェック - 4⃣ 追加として、Sec-Fetch-* ヘッダーもチェック - 送られてきていたらチェックするぐらい
Slide 42
Slide 42 text
でも結局のところ - フレームワークで用意されている方法を使うのが一番 - Web開発ではほとんどの場合フレームワークを使う - 1⃣ トークン方式も全然よいものだよ!!
Slide 43
Slide 43 text
今回話したかったこと (おまけ)
Slide 44
Slide 44 text
エンジニアとしての心がけ - 使っているフレームワークのことをよく知ろう - 使い方も大事だけど、仕組みに興味を持ってほしい - その上で、それ以外のやり方がないか調べよう - 異なる言語・フレームワークを触るときにきっと役立つ
Slide 45
Slide 45 text
ありがとう ございました!