Pre-hijacking Attacksについてのメモ書きです。 元の論文と記事は次のページを読んでください。
- [2205.10174] Pre-hijacked accounts: An Empirical Study of Security Failures in User Account Creation on the Web
- New Research Paper: Pre-hijacking Attacks on Web User Accounts – Microsoft Security Response Center
Pre-hijacking Attacks はメールアドレスの確認をしないでアカウントを作れるサービスという前提があります。 アカウント作成からそのまま特定の機能をすぐ利用できるようにすることで、体験をよくするための施策としてメールアドレスの確認のステップを後回し(またはしない)サービスがあります。 モバイルアプリでアカウント作成時に、メールアプリをわざわざ別で開かせるようなフローを避けたりするためにメールを確認しないでアカウント作成ができるサービスもあります。
例) Dropboxはメールアドレスとパスワードを入力して新規アカウントを作成できる。 このときに、自分が持っていないメールアドレスでもとりあえずアカウントを作成できて、そのままログインできる。
📝 メールアドレスと書いてるけど、電話番号 + SMSも基本同じ。ログインするIDという意味合い
- 攻撃者は、被害者のメールアドレスを使ってアカウントを作っておく
- 被害者は、GoogleログインなどのSSOでログインする
- メールアドレスとIdPのメールアドレスが一致するのでアカウントがマージされる
- 攻撃者は、メールアドレスと攻撃者が設定したパスワードでログインできるので、マージ後の被害者のアカウントを乗っ取れる
- 対策:
- アカウントをマージするときには、サービスのメールアドレスとIdPのメールアドレスをどちらも検証済みであるかを確認する
- Unexpired Session Identifier Attack:
- 攻撃者は、被害者のメールアドレスを使ってアカウントを作っておく
- 攻撃者は、そのままログイン状態を維持するように定期的にアクセスし続ける
- 被害者が、そのサービスを新規で使おうとして「メールアドレスは既に登録されています」となって「このサービスの使ってたけ?」と思ってパスワードリセットする
- 被害者が、パスワードリセットしてサービスにログインして利用する
- パスワードリセット時に、攻撃者がログインしていたセッションが切れないため、被害者が設定した内容を盗み取れる(アカウントも乗っ取れる)
- 対策:
- パスワードリセットするときに、セッションもリセットする
- Trojan Identifier Attack:
- 攻撃者は、被害者のメールアドレスを使ってアカウントを作っておく
- 攻撃者は、そのアカウントと攻撃者のIdPアカウントを紐づけておく
- 被害者が、そのサービスを新規で使おうとして「メールアドレスは既に登録されています」となって「このサービスの使ってたけ?」と思ってパスワードリセットする
- 被害者が、パスワードリセットしてサービスにログインして利用する
- 攻撃者は、攻撃者のIdPアカウントでサービスにログインできるので、被害者が設定した内容を盗み取れる(アカウントも乗っ取れる)
- 対策:
- アカウントをマージするときには、サービスのメールアドレスとIdPのメールアドレスをどちらも検証済みであるかを確認する
- 📝 Classic-Federated Merge Attack は被害者がSSOでログイン、Trojan Identifier Attackは攻撃者がSSOでログイン の違い
- どちらもマージの挙動を利用した攻撃
- 📝 もと論文だと、もう一つの攻撃が含まれていて、サブメールアドレスや電話番号を最初に紐づけておいて、それでリセットする攻撃も同じくTrojan Identifier Attackと言ってる
- Classic-Federated Merge Attackの対義語として扱った方がいいので、SubProcess Attackみたいな別の名前に分離したい
- Unexpired Email Change Attack:
- 攻撃者は、被害者のメールアドレスを使ってアカウントを作っておく
- 攻撃者は、そのアカウントで攻撃者のメールアドレスに変更の申請をしておく(まだ確定はしない)
- サービスは、メールアドレスの変更の確認メールを攻撃者のメールアドレスの送信する(まだ確定はしない)
- 被害者が、そのサービスを新規で使おうとして「メールアドレスは既に登録されています」となって「このサービスの使ってたけ?」と思ってパスワードリセットする
- 被害者が、パスワードリセットしてサービスにログインして利用する
- 攻撃者、メールアドレスの変更の確認メールからメールアドレスの変更を確定する
- 攻撃者は、攻撃者のメールアドレスでログインできるので、被害者が設定した内容を盗み取れる(アカウントも乗っ取れる)
- 対策:
- パスワードリセットするときに、メールアドレスの変更を保留している状態もリセットする
- メールアドレスの変更の有効期限を設定する
- Non-Verifying IdP Attack:
- 攻撃者は、メールアドレスの確認をしないIdPで被害者のメールアドレスを使ってアカウントを作成する
- 被害者は、自分自身のメールアドレスでアカウントを作成して利用する
- 攻撃者は、被害者のメールアドレスを使ったIdPでサービスにログインしてアカウントをマージさせる
- 攻撃者は、被害者のアカウントを乗っ取れる
- 📝 メールアドレスの存在確認などをしてないIdP連携の問題
- またサービスが、OpenIDのclaimに含まれる
email_verified
をチェックせずにマージしているとこの問題が起きる - マージするときは、そのサービスでメールアドレスが確認ずみ + IdPアカウントのメールアドレスが確認ずみで初めてマージする
- さらにより良くするには、マージするタイミングで、サービスのメールアドレスに紐づくパスワードをリセット または 再入力して、マージするタイミングでの持ち主をもう一度検証する
- またサービスが、OpenIDのclaimに含まれる
- 対策:
- そういうメールを検証しないIdPでSSOは実装しない
- アカウントをマージするときには、サービスのメールアドレスとIdPのメールアドレスをどちらも検証済みであるかを確認する
- アカウントを作成時には、メールアドレスの検証をしてからアカウントをする
- これができるとPre-hijacking AttacksのNon-Verifying IdP Attack以外は防げる
メールアドレスの検証前にアカウントを作るサービスの場合
- メールアドレス未確認のアカウントを定期的に削除する
- アカウント作成時にreCAPTCHAなどを導入し、機械的にアカウントを作成しにくくする
どちらのケースでも共有でやるべきもの
- パスワードをリセットすると、そのアカウントのセッションを全て無効にする
- パスワードをリセットすると、メールアドレスの変更を保留している状態もリセットする
- パスワードをリセットしたときの通知メールに、紐づくIdPやメールアドレスの情報を掲載する
- アカウントをマージする際には、サービスのアカウントとIdPのアカウントが両方検証ずみアカウントであることを確認する
- OpenID Connectならclaimの
email_verified
をチェックする- ライブラリがやってくレルこともあるが、手動でやらないといけないこともあるので必ず確認する
- Passport + Googleなら、
email
配列の要素のverified
プロパティ - Next Auth + Googleなら
profile.email_verified
をチェックする
- verifiedされていないアカウントはマージしてはいけない
- OpenID Connectならclaimの
- メールアドレスの変更の確認メールは、一定の有効期限をつける
- 1日以内に確定されないならメールアドレスの変更自体を無効にするなど
- IdPでアカウントを作成した場合、そのアカウントでパスワードリセットはできないようにする
- IdPでアカウントを作成した場合、そのアカウントにはパスワードそのものがないはず
- パスワードリセットによって、パスワードが設定できてしまうと、パスワードレスじゃなくなるため、セキュリティの強度が下がる
- IdPのみのアカウント(マージされていないアカウント)の場合は、パスワードリセットは、SSOでログインできる有無のメールをリセットメールの代わりに送信するなど
- パスワードリセットによって、そのアカウントの存在が判定できないようにする
- パスワードリセットの結果(レスポンス)が、アカウントの存在の有無で変わらないようにする
- メールの内容を変更すればいいので、レスポンスはアカウントの有無で変更しない
- 攻撃者が機械的にパスワードリセットしていくことで、アカウントのスクリーニングを防ぐ目的
- セシールオンラインショップへの不正アクセス、二重登録防止機能を悪用しリストをスクリーニング(ディノス・セシール) | ScanNetSecurity
- 多要素認証を推奨する
- 多要素認証を有効化した際に、そのアカウントのセッションを全て無効化する