CSRF対策のやり方、そろそろアップデートしませんか / Update your knowledge of CSRF protection
by
YAMAOKA Hiroyuki
Link
Embed
Share
Beginning
This slide
Copy link URL
Copy link URL
Copy iframe embed code
Copy iframe embed code
Copy javascript embed code
Copy javascript embed code
Share
Tweet
Share
Tweet
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
ありがとう ございました!