はじめに
CSRF(Cross-Site Request Forgery)は古典的な脆弱性ですが、
「Hidden link / hidden image」 を用いた CSRF は今でも非常に実践的です。
この手法の恐ろしい点は、
- ユーザーが 操作した自覚すらない
- 攻撃が ワンクリック、場合によってはノークリック
- ログも正規操作と区別がつきにくい
という点にあります。
本記事では、Hidden link / image CSRF の仕組みを
実際の攻撃シナリオ → 脆弱性の本質 → 防御策 の順で解説します。
Hidden Link / Image CSRF とは?
Hidden link / image CSRF とは、攻撃者が 不可視または無害に見える要素 を使って、
被害者のブラウザに 認証済みリクエストを自動送信させる 攻撃手法です。
代表例:
- 0×0 ピクセルの画像
- 透明な画像
- 「賞品を受け取る」「確認はこちら」などのリンク
- iframe や自動 submit フォーム
共通点はこれです:
ブラウザは、ユーザーがログイン中のサイトに対して Cookie を自動送信する
この「親切仕様」が、CSRF の根源です。
攻撃シナリオ(VM 内の想定)
登場人物
-
Josh(被害者)
- メール:
http://mailbox.thm:8081 - 銀行:
http://mybank.thm:8080 - Chrome で常にログイン状態
- メール:
-
攻撃者
- Josh のメールアドレスを知っている
- 同じ銀行に口座を持っている
GB82MYBANK5698
脆弱な実装(銀行側)
送金処理のフォームは以下のようになっています:
<form action="transfer.php" method="post">
<label for="to_account">To Account:</label>
<input type="text" id="to_account" name="to_account" required>
<label for="amount">Amount:</label>
<input type="number" id="amount" name="amount" required>
<button type="submit">Transfer</button>
</form>
一見、問題なさそうに見えますが、致命的な欠陥があります。
何が問題なのか?
サーバーが「このリクエストは正規画面から来たのか」を検証していない。
- 認証は Cookie 任せ
- CSRF Token なし
- Origin / Referer チェックなし
つまり:
Cookie さえ付いていれば、誰が送っても正規操作として処理される
攻撃方法①:Hidden Link(クリック誘導)
攻撃者は Josh に次のようなメールを送ります。
<a href="http://mybank.thm:8080/dashboard.php?to_account=GB82MYBANK5698&amount=1000"
target="_blank">
Click Here to Redeem
</a>
Josh 視点で起きていること
- メールのリンクをクリック
- ブラウザが
mybank.thm:8080にアクセス - ログイン中の Cookie が自動送信
- 銀行は「Josh が送金した」と誤認
- 送金完了
Josh は「リンクを踏んだだけ」のつもりです。
攻撃方法②:Hidden Image(ノークリック)
さらに厄介なのが 画像による自動発火 です。
<img src="http://mybank.thm:8080/dashboard.php?to_account=GB82MYBANK5698&amount=1000"
width="0" height="0" style="opacity:0">
- ユーザーは何も操作しない
- ページ(または HTML メール)を 開いた瞬間に送金
これが Hidden Image CSRF です。
攻撃フロー全体(Mermaid)
Missing Link(欠けていたもの)
入力チェックや認証は正しくても、以下が欠けていました:
- リクエストが
「正規ページから送信されたか」 の検証
CSRF は 認証の問題ではなく、リクエストの正当性の問題 です。
修正後の実装(CSRF Token)
銀行側は CSRF Token を導入しました。
<input type="hidden" id="csrf_token" name="csrf_token"
value="<?php echo $_COOKIE['csrf-token']; ?>">
サーバー側のチェック
- token が存在するか
- セッションと一致するか
- 不一致 → リクエスト拒否
修正後に何が起きるか?
Josh が再び攻撃メールを開いても:
- リンクには CSRF Token が含まれない
- サーバーが不正リクエストとして拒否
- 送金は実行されない
攻撃チェーンは完全に断ち切られます。
防御策まとめ
CSRF 対策は 多層防御 が基本です。
必須
- CSRF Token(同期トークン / Double Submit Cookie)
推奨
-
SameSite=LaxorStrict - POST + 正しい Content-Type 限定
- Origin / Referer チェック
- 重要操作は再認証・OTP
まとめ
Hidden link / image CSRF は、
- 古い
- シンプル
- しかし 今でも通用する
攻撃です。
「ログインしているだけ」で被害者になる
この前提を忘れないことが、
設計・実装・テストすべての出発点になります。