WordPressで考えるSameSite回避|クライアント側リダイレクトでCSRFが成立する理由

※本記事にはプロモーションが含まれています。

CSRF対策として「SameSite属性を設定しているから安全」と考えていませんか。

確かに SameSite=Strict は強力な防御ですが、実装によっては回避されるケースがあります。

この記事では、Web Security Academyのラボ「SameSite Strict bypass via client-side redirect」をもとに、

  • なぜSameSiteがあってもCSRFが成立するのか
  • WordPressではどのような実装ミスが起こり得るのか

を解説します。

CSRFの基本については以下の記事で解説しています。

CSRFの仕組みまとめ|成立条件と対策の基本

SameSite Strict bypass via client-side redirectラボ概要

このラボでは、メールアドレス変更機能にCSRF脆弱性があります。

特徴は以下の通りです。

  • セッションCookieに SameSite=Strict が設定されている
  • 一見するとCSRFは不可能に見える
  • しかし、クライアント側リダイレクトを利用することで攻撃が成立する

クライアント側リダイレクトを利用した攻撃の流れ

今回の攻撃は、単純なCSRFではありません。

以下のような流れで成立します。

  1. 被害者が攻撃ページにアクセス
  2. 正規サイトの確認ページに遷移させる
  3. ページ内のJavaScriptがリダイレクトを実行
  4. 同一サイト内リクエストとして扱われる
  5. Cookie付きでメール変更リクエストが送信される

※CSRFはトークンの実装不備によっても成立します。

WordPressで考えるCSRF対策の落とし穴|トークン未送信で突破されるケース


SameSiteが効かない理由

SameSite=Strictは、クロスサイトリクエストにCookieを付与しません。

しかし今回のケースでは、

  • 最初のアクセス → クロスサイト
  • その後のリダイレクト → 同一サイト

と扱われます。

つまりブラウザは、「これはサイト内の通常遷移だ」と判断し、Cookieを付与してしまいます。


攻撃者はどこに注目するのか

攻撃者が見ているのはここです。

  • URLパラメータがそのままJavaScriptで使われている
  • その値がリダイレクト先として使われている

今回のコードは以下のような構造でした。

const postId = url.searchParams.get("postId");
window.location = blogPath + '/' + postId;

この実装には問題があります。

  • 入力値の検証がない
  • URLとして扱っている

つまり攻撃者は、

postId = 1/../../my-account/change-email?email=attacker@evil.com&submit=1

のような値を渡すことで、意図しないページにリダイレクトさせることができます。


WordPressで起こり得る実装ミス

WordPressでも似たような問題は普通に起きます。

例1:リダイレクト処理の実装ミス

$redirect = $_GET['redirect'];
wp_redirect('/post/' . $redirect);

このようなコードがあると、

  • ../ を使ったパス操作
  • 任意ページへの遷移

が可能になります。

例2:JavaScriptでの遷移制御

const next = new URL(location).searchParams.get("next");
location = "/mypage/" + next;

このような実装も同様に危険です。

例3:コメント後の遷移処理

今回のラボと同じく、

  • コメント投稿後
  • フォーム送信後
  • 完了ページ表示後

などにJSで遷移させているケースは特に注意が必要です。

なぜ気づきにくいのか

この問題はかなり見落とされやすいです。

理由は以下の通りです。

  • SameSiteを設定していることで安心してしまう
  • CSRF対策はサーバー側だけ見がち
  • クライアント側の挙動を考慮していない

こうしたリダイレクトやURL処理の問題は、サーバー側の設定だけでは防げないケースもあります。

最低限のWAFやセキュリティ対策を備えた環境での運用が重要です。

エックスサーバー ▶ エックスサーバー公式サイトはこちら


SameSiteだけに依存しないCSRF対策

対策はシンプルですが重要です。

入力値をそのままURLに使わない

  • 数値なら数値として扱う
  • パスならホワイトリストで制御する

リダイレクト先を固定する

wp_redirect('/post/');

のように、ユーザー入力を使わない設計にする。

CSRFトークンを正しく実装する

SameSiteだけに依存せず、

  • トークン検証
  • セッションとの紐付け

を行う。

クライアント側の処理も監査対象にする

  • JavaScriptでのURL操作
  • location変更
  • パラメータ利用

これらも含めて確認する。


セキュリティ診断でのチェックポイント

実務で見るならここをチェックします。

  • URLパラメータがそのままリダイレクトに使われていないか
  • JavaScriptでURLを組み立てていないか
  • ../ を使ったパス操作が可能でないか
  • SameSiteに依存した設計になっていないか

まとめ│SameSiteでも防げないCSRFから学ぶべきこと

SameSite=Strictは強力な対策ですが、万能ではありません。

特に、

  • クライアント側リダイレクト
  • ユーザー入力のURL利用

が組み合わさると、簡単に回避されることがあります。

CSRF対策は単体ではなく、設計全体で考える必要があります。