Hello there, ('ω')ノ
🧠 パスワードリセットの基本的な仕組み
多くのウェブサイトでは、ユーザーがパスワードを忘れたときのために「パスワードリセット」機能を提供しています。その仕組みは以下のような流れです:
- ユーザーが自分のメールアドレスやユーザー名を入力してリセットをリクエスト。
- サーバーは、対応するアカウントを確認して、一意な「リセットトークン」を生成。
- そのトークンを含んだリセットリンクをメールで送信:
https://normal-website.com/reset?token=abcdef123456
- ユーザーがリンクをクリックすると、トークンを検証し、新しいパスワードの入力画面へ。
- リセット完了後、トークンは無効化。
この仕組み自体はシンプルかつ比較的安全です。ただし、リンクの生成に「Hostヘッダー」が使われていると話は別です。
🧨 パスワードリセットポイズニング攻撃とは?
「Hostヘッダー」によってリセットリンクのURLが生成されている場合、攻撃者は以下のような手順で攻撃できます:
🕵️♂️ 攻撃手順
- 攻撃者が被害者のメールアドレスを使って、パスワードリセットをリクエスト。
- リクエストをBurpなどでキャプチャしてHostヘッダーを書き換え、自分の管理するドメイン(例:
evil-user.net
)に変更。 - サーバーはリセットリンクを被害者に送信するが、リンクのドメインは以下のようになっている:
https://evil-user.net/reset?token=abcdef123456
- 被害者がリンクをクリックすると、トークンが攻撃者のサーバーに送られてしまう。
- 攻撃者はトークンを使って本物のサイトでパスワードを変更し、アカウントを乗っ取る。
🛡️ 防御策
防御策 | 内容 |
---|---|
Hostヘッダーを使わない | 絶対URLが必要な場合でも、設定ファイルでドメインを指定するべき。 |
Hostヘッダーを検証 | ホワイトリスト方式でドメインをチェック。例:DjangoならALLOWED_HOSTS 。 |
HTMLエスケープを忘れない | メール本文にURLを含む場合は、Hostヘッダー由来の値をHTMLエスケープする。 |
✅ まとめ
ポイント | 解説 |
---|---|
パスワードリセットはトークンに依存 | トークンが盗まれると誰でもパスワードを変えられる |
Hostヘッダーが脆弱だとリンクを乗っ取れる | 攻撃者が悪意のあるドメインでリンクを送れる |
防御には構成ファイルの見直しが有効 | フレームワークの設定で許可ドメインを制限するのが重要 |
Best regards, (^^ゞ