【新規登録フォームの裏側】サインアップから漏れる情報と防御策|CTF思考フレームワーク #02
こんにちは、アンペンです!「はじめてのWebセキュリティ」シリーズの第2回は新規登録フォーム編。前回のログイン画面に続いて、今回は会員登録(サインアップ)の画面を見ます。「このメールアドレスは登録済みです」という親切な一言が、なぜ攻撃者の手がかりになるのか。CTF(シーティーエフ)という安全な演習環境を題材に、守る側の対策とセットで学びましょう。

登録フォームで「そのメールはもう使われています」って出るの、便利だよね。間違って二重登録しなくて済むし。

使う人にはありがたい表示だよね。でも裏を返すと、「そのメールアドレスの人は会員だ」と誰にでも教えていることになるんだ。前回学んだユーザー名列挙が、登録フォームでも同じように起きる。今日はその仕組みと、便利さを保ったまま守る方法を見ていこう。
新規登録フォームの「このメールアドレスは登録済みです」という表示は、入力した人だけでなく第三者にもアカウントの有無を教えてしまいます。これは前回のユーザー名列挙と同じ問題で、登録フォームは特に誰でもログイン前に試せる入口なので狙われやすい場所です。守る側の答えは『存在しても・しなくても画面表示は同じにし、結果はメールで知らせる』。あわせてリアルタイム重複チェック・応答時間・レート制限まで気を配ります。
この記事で分かること
- 新規登録フォームで、攻撃者が見ているポイント
- 「登録済みです」表示が、なぜ情報漏れになるのか
- 入力中のリアルタイム判定や応答時間にも差が出ること
- 演習環境での確認手順(登録時の応答の差を観察する)
- 便利さを保ったまま存在を隠す「メール確認フロー」
📖 はじめてのWebセキュリティ #02|新規登録フォーム編
前回の「失敗メッセージ」に続き、今回は「登録時の応答」から何が漏れるかを学びます。攻撃手順を覚えるのではなく、「どこを見るか・なぜ危ないか・どう守るか」を1つずつ。 シリーズ一覧を見る →
⚠️ 大事なお約束
この記事の確認は、CTF・公式ラボ・自分で作った検証環境だけで行ってください。実在するサイトの登録フォームに他人のメールアドレスを入力して試すことは、不正アクセス禁止法や個人情報・プライバシーの問題に触れるおそれがあります。本記事の目的は守る側の理解です。「できる」と「やってよい」は全く別です。
新規登録フォームは「申し込むだけ」の場所ではない
新規登録フォームは、メールアドレスやIDを入力して会員になるための画面です。だから普通は「登録できたか、できなかったか」だけを気にします。でもセキュリティを学ぶときは、もう一つ見ます。それが登録できなかったときに画面が何を教えているかです。しかも登録フォームはログイン前の誰でも触れる入口なので、ログイン画面以上に手がかりが漏れやすい場所でもあります。攻撃者が観察するのは、次のような『反応の差』です。
- エラーメッセージの文言:「このメールアドレスは登録済みです」と「確認メールを送りました」を出し分けていないか
- リアルタイム重複チェック:入力中に「✓使えます/×使われています」をその場で返していないか
- 応答時間・移動先:登録済みアドレスだけ処理が違って、時間差や画面遷移で判別できないか
- 他の入口との一貫性:ログイン・パスワードリセットでも同じ存在情報が漏れていないか

ここで覚える用語:アカウント存在の漏洩(登録時のユーザー名列挙)
意味:新規登録フォームの反応の違いから、「そのメールアドレス/IDが既に登録されているか」を第三者が知ってしまうこと。前回のユーザー名列挙が、登録という入口で起きるバージョンです。
例:alice@example.comで登録しようとすると『登録済みです』、nobody@example.comだと『確認メールを送りました』→alice@example.comは会員だと分かる。
使いどころ:守る側は登録時の画面表示をそろえ、会員かどうかが外から区別できないようにします。OWASPのテストガイドでも確認項目として扱われています。
ここでひとつ、想像してみてください。あなたのメールアドレスを使って、知らない誰かがあちこちのサービスで“登録ボタン”を押して回っているところを。本人はログインできなくても、「このメールアドレスは登録済みです」の一言が返るたびに、『この人はこのサービスを使っている』という事実が相手の手元に積み上がっていきます。これが地味に怖いところなんです。
なぜ「登録済みです」の一言が危ないのか
会員制クラブに入会を申し込んだ人へ、受付が「その方はすでに会員です」と「入会のご案内をお送りします」を使い分けたらどうでしょう。申込者は中に入れなくても、「あの人はこのクラブの会員だ」とハッキリ分かってしまいます。攻撃者にとって、あるメールアドレスが特定サービスの会員だと分かるのは大きな一歩です。「この人は通販サイトAと投資サービスBの会員」といった事実は、フィッシングメール(「Aから重要なお知らせ」を装う)や、他サイトから漏れたパスワードの使い回し試行の材料になります。だから受付の正解は、申込者が会員でもそうでなくても『同じ対応をして、結果はご本人にお手紙で知らせる』こと。手紙は本人しか読めないので、第三者には会員かどうか分かりません。登録フォームもまったく同じで、結果はメールで知らせるのが守りの基本です。

とくに見落としがちなのが、入力している最中にその場で出る「✓使えます/×すでに使われています」の判定です。親切のつもりの機能なのですが、登録ボタンを押すよりずっと前に、しかも何度でも“当たり判定”を返してしまう。攻撃者からすれば、これほど都合のいい確認窓口はありません。便利な機能ほど、情報の漏れ方も静かなんですね。
差は「登録済み表示」だけに出るとは限らない
登録時のメッセージを工夫しても、別のところで差が出ることがあります。よくあるのが入力中のリアルタイム重複チェックです。メール欄に入力しただけで「×すでに使われています」と即座に返すと、登録ボタンを押す前に存在が分かってしまいます。ほかにも、登録済みアドレスだけ内部処理が違って応答が少し遅い、エラー時の画面遷移が微妙に違う、といったケースもあります。攻撃者はこうした小さな差も手がかりにします。だから守る側は『見える文言』だけでなく、入力中の挙動・裏側の応答時間までそろえる意識が必要です。
ここで覚える用語:メール確認フロー(存在を隠す登録)
意味:登録の可否を画面に出さず、入力されたアドレス宛のメールで知らせる仕組み。未登録なら「登録用リンク」、登録済みなら「すでに登録があります/ログインはこちら」と、内容を変えたメールを送ります。画面表示は常に「確認メールを送りました」で一定です。
例:第三者が他人のアドレスを入れても、画面は「メールを送りました」だけ。会員かどうかはメールを受け取れる本人にしか分からない。
使いどころ:便利さ(二重登録の防止案内)を保ったまま、第三者への存在漏れを断つ定番の設計です。
「結果はメールで知らせればいい」と言われても、最初はピンと来ないかもしれません。次の会話で感覚をつかみましょう。

画面に出さないで、わざわざメールにするの?それって二度手間じゃない?

それがミソなんだ。メールは“本人だけ”が受け取れるよね。だから「登録済みかどうか」をメールの中で伝えれば、画面の前にいる第三者には何も分からない。手間が一つ増える代わりに、存在のヒントを完全に隠せる——このトレードオフが効いてくるんだよ。
CTFでやってみよう:登録時の「差」を見つける
登録済みアドレスと未登録アドレスで、応答の「差」を比べてみよう
この演習の目的は、誰かのアカウントを暴くことではありません。登録フォームが返す『情報の差』に気づくことです。対象は必ず自分の検証環境かCTFにし、使うアドレスも自分が用意したテスト用だけにしてください。各ステップに「なぜやるか」を添えました。
- 演習環境で登録済みのテスト用アドレスを1つ確認 → なぜ:比較の基準を作るため
- まだ使っていないテスト用アドレスを1つ用意 → なぜ:対照を作るため
- 両方で登録を試し、画面メッセージを記録 → なぜ:文言の差を確認するため
- メール欄入力中のリアルタイム判定の有無を見る → なぜ:押す前に漏れていないか確認するため
- 開発者ツールでHTTPステータス・移動先を確認 → なぜ:文言以外の差を見るため
- 応答時間(処理の速さ)の違いを観察 → なぜ:時間差の手がかりを見るため
- 「第三者には何が分かるか」を書き出す → なぜ:リスクを言葉にするため
- 画面表示を一定にし結果をメールで返す形に直して再確認 → なぜ:守りを手で検証するため
実際にCTFで触ってみると、『便利な登録フォームほど、こんなにしゃべってしまうのか』と実感できるはずです。その気づきを持ったまま、次は守る側の具体策を見ていきましょう。ポイントは“便利さを捨てずに、存在だけ隠す”ことです。
守る側:存在を隠したまま親切な登録にする
- 画面表示を一本化:登録済みでも未登録でも「確認メールを送りました」に統一する
- 結果はメールで知らせる:登録済みなら「すでに登録があります」、未登録なら「登録用リンク」を本人宛に送る
- リアルタイム判定をやめる:入力中に「使われています」を即返さない(本人のメールで案内)
- ステータス・移動先も同一に:HTTP応答コードやリダイレクト先を存在/非存在で揃える
- 応答時間を均一化:登録済みでもダミー処理を行い処理時間をそろえる
- レート制限・CAPTCHA:同一IPからの大量試行を抑え、機械的な列挙を困難にする
- 他の入口も統一:ログイン・パスワードリセットでも存在を漏らさない応答にする
- ログ監視:登録試行の集中や列挙の兆候を検知してアラートする


なるほど!「結果はメールで知らせる」なら、二重登録の案内もできて、しかも第三者には会員かどうか分からないんだね。便利さと安全が両立してる。

その通り!「本人にしか読めないメール」を使うのがコツなんだ。次回#03はパスワードリセット編。「登録メールに送りました」と「そのアドレスは未登録です」、リセット画面でも同じ落とし穴があるよ。一緒に見ていこう。
まとめ:登録の「結果」は画面でなくメールで返す
- 新規登録フォームはログイン前の誰でも触れるので、存在情報が漏れやすい入口
- 「登録済みです」表示は第三者にもアカウントの有無を教えてしまう
- 差は文言だけでなくリアルタイム判定・応答時間・移動先にも出る
- 守る側は画面表示を一定にし、結果は本人宛メールで知らせる
- レート制限・CAPTCHA・監視を組み合わせ、便利さと安全を両立する
今日のいちばんの持ち帰りは、『登録の結果は、画面ではなくメールで返す』のひと言です。画面はいつも同じ顔、本当の答えは本人のメールボックスの中——この形を覚えておくと、ログインもパスワードリセットも、ぜんぶ同じ考え方で守れるようになります。
新規登録フォームは、ただ申し込むだけの場所ではありません。表示やメールの設計ひとつで、外から見える情報は大きく変わります。次回は、同じく存在情報が漏れやすいパスワードリセットの画面を見ていきましょう。
