この記事の目的
課題: Webサービスの各機能の仕様に関するセキュリティ情報があまりない
Webサービスを設計するにあたり、よくある機能というのが存在するかと思います。
- ユーザ登録
- ログイン・ログアウト
- パスワード復旧
- URLで共有
- SNSログイン
- お気に入り登録
- いいねボタン
- マイページ
- 通知
- 等・・・
これらに関して、自分の認識をまとめておきたい・意見をもらってブラッシュアップしたいと思い、記事を書きます。
大きい記事たくさん書くの大変なので、機能ごとに書こうかな・・・と思ってますが一つを育てていくかもしれないです。
前書いた記事が個人的には好評だったことも受けて、書いています。
ユーザ登録機能の仕様とセキュリティ
toC向けサービスならかなりの割合で存在する機能です。よくある仕様パターンについて考えてみます。
この機能でユーザから取得するもの
- 認証情報(ID/パスワード)
- 連絡手段
- 連絡手段を認証で用いるIDとして扱うことも多いですね
- メールアドレス・電話番号等
- 個人情報
- 年齢、住所、氏名、ニックネームなど
この機能で達成されるべきこと
ユーザが次から上記の認証情報を用いてログインしサービスが受けられる状態、だとは思いますが
- 上記情報をユーザから取得し、サーバに適切な形で保存されていること
- 認証情報を用いてユーザがログインできる状態になってること
- 連絡手段の疎通確認ができていること(SMS/メールなどで)(オプショナル)
- 一人のユーザが無制限な数アカウントを作成できないこと(オプショナル)
とかでしょうか
ユーザ登録機能の仕様パターンとセキュリティ観点
パターンA: 連絡手段+個人情報入力 -> 疎通確認URL送信 -> 踏んだらログイン状態になる
非常によくあるパターンです。
最初こういう画面に情報を入れて
で、
件名: 会員登録の確認
〇〇様
登録ありがとうございます。
下記URLにアクセスしますと登録が完了します。
よろしくお願いします。
みたいなメールが届くパターン
踏んだら、
登録完了です。
マイページへ
みたいな画面が出るパターン。
観点1: 第三者のメールアドレス・電話番号の登録状況が確認できてしまう
この仕様は、多くのサイトで実装されています。
が、二つの観点で注意が必要です。
- 「サービスに登録している」という事実が漏洩してしまう
- サービスの性質や法務的観点・ポリシーなど考慮しつつ判断が必要です
- リスト型攻撃の攻撃準備に悪用されてしまう
- 流出済みID/パスワードの組を利用する際、登録済みIDだけを抽出する作業に悪用されてしまいます
- セシールオンラインショップへの不正アクセス、二重登録防止機能を悪用しリストをスクリーニング(ディノス・セシール)
- 事例とともにすでに解説記事があったので引用します
- 「大手サイトもやっているじゃないか!」という意見もあるかと思いますが、認証機能への監視・リスト型対策・自動化対策が成熟していると思われるサービスの仕様を新規に作るサービスで真似するのは、難しい場合もあります。
- この対策を怠るとリスト型攻撃の特徴のサービスに登録されていないIDによるログイン失敗が多発するといった性質が観測できなくなってしまいます。
- 流出済みID/パスワードの組を利用する際、登録済みIDだけを抽出する作業に悪用されてしまいます
対策1-1: 疎通確認時に登録済みであることをユーザに伝える
大事なことは第三者に登録状況が知られてしまうことがリスクということです。
本人には伝えるべきです。
なので、入力されたIDに対応する連絡手段(メールやSMS)で疎通確認URLを送信する代わりに
このメールアドレスはユーザ登録が完了しております。
パスワードを忘れた場合は、こちらからパスワードの再登録をお願いします。
といった内容を送るとよいでしょう。
観点2: ユーザが間違って第三者の連絡手段を入力してしまった場合、第三者に個人情報が流出してしまう
ユーザ登録時に誤って、第三者のメールアドレスを書いてしまうとどうなってしまうでしょうか。
受け取った第三者がメールに従って登録をし続けるとマイページから住所等が閲覧できてしまうのではないでしょうか。
マイページを見るためにパスワード再入力が必要な場合も、そもそも第三者のメールアドレスで登録が進んでしまっていますから、パスワード復旧機能等からパスワードを変更してしまえばすべて見れてしまいます。
第三者に住所や年齢まで漏洩してしまうことは、打ち間違えたユーザにも原因があるとはいえ、サービス運営側として防ぎたいリスクです。
そもそも打ち間違えるの?ということがあるかもしれませんが、例えば、(ニックネーム).(数字4ケタ)@gmail.com
のようなメールアドレスはありがちかと思いますが、数字4桁を打ち間違えたり、そもそもニックネームだけで登録してしまったり・・・といったことがあり得るかなと思います。
**「メールアドレスを書き間違えただけなのに」**といった事故による不幸は減らしたいです。
対策2-1: セッションIDなどでメールを受け取ったユーザが登録を行ったユーザと同一人物であることを確認する
この事故は、個人情報を入力したユーザと疎通確認メールを受け取ったユーザが同じユーザであることを確認していないことが原因で起きます。
そのため、確認URLを踏んだ際に同一人物であるかどうかを確認しましょう。
SessionIDによる確認方法
同じブラウザでリンクを踏まないと登録が成功しないパターンです。
メールアドレスはスマホ・操作はPCといった場合や、ユーザがブラウザを複数使い分けている場合うまくいかず、下記に紹介する手段を組み合わせる必要があります。
パスワードによる確認方法
違うブラウザで開いてもパスワード入力が求められるので登録が成功しないパターンです。
パスワード打つのがめんどくさいといったデメリットや、疎通が取れるまではパスワードリセットを無効にしなければならないなどの懸念があります。
対策2-2: 確認URLをやめてPINコードを入力させる
確認URLの代わりに、4桁の数字などのPINコードを送ります。
登録操作をしたブラウザ上でメールに送信したPINを入力してもらいます。
これにより、第三者にメールアドレスを誤入力しても4桁の数字が送られるだけですので、リスクが小さいです。
あくまで同一人物であることの確認はSessionIDで行っており、本人の誤入力防止観点の機能であるため、4桁等弱い確認で済ませることができています。
無理やり登録しても、第三者のメールアドレスで登録されてしまうだけですので、本人が損するだけです。
電話番号につき1IDに制限することによりアカウント発行数を抑えたい(攻撃者がアカウントを大量にとることによってメリットが大きい場合)などは、4桁数字部分を強くする必要があります。
また、そもそも電話番号に紐づいた個人情報を持っているサービス(宅配サービスなど)である場合も同様に強固にしてください(6桁数字以上で試行回数制限を厳しくするなどが考えられます)。
対策2-3: 疎通確認前に個人情報をユーザから取得しない
そもそも疎通確認前にユーザの個人情報を取得するのをやめる、登録フローを変更するという対策です。
パターンB, パターンCとします。
パターンB: 連絡手段入力 -> 疎通確認URL送信 -> URLから個人情報入力
まず、こういう画面で連絡手段を入力させます
その後、下記のようなメールを送ります。
件名: 会員登録URLのご案内
登録ありがとうございます。
下記URLにアクセスし、登録を続けてください。
URLに遷移すると、ユーザ登録フォームが表示される、といった流れです。
パターンAと同様に、下記に対するケアは必要となります。
- 観点1: 第三者のメールアドレス・電話番号の登録状況が確認できてしまう
- 対策1: 疎通確認時に登録済みであることをユーザに伝える
が、
- 観点2: ユーザが間違って第三者の連絡手段を入力してしまった場合、第三者に個人情報が流出してしまう
に関するリスクは対策が不要になっています。
疎通確認メールが届く時点ではまだ個人情報が載っていませんので、そのケアが不要となります。
UXとしてはPCで登録し始めたのに、スマホのメールに届いて不便、という方もいるかもしれませんね。
セキュリティ観点としては問題なさそうです。
パターンC: 連絡手段入力 -> PINコード送信 -> PINコード入力 -> 個人情報入力
こちらも、パターンBとほぼ同様で観点1に関するケアが必要になります。
ユーザ登録操作を行う端末と、メール・SMSを受け取る端末が異なってもスムーズに登録を続けることができます。
パターンD: 連絡手段と個人情報入力のみで登録を完了し疎通確認をしない
連絡手段+個人情報を入力した時点で登録が確認し、ログイン状態になるサービスです。
このパターンはケアしなければならないことが多いです。
観点1: 第三者のメールアドレス・電話番号の登録状況が確認できてしまう
パターンAと同様のリスクがあります。
対策は下記で検討しましたが、ここまで複雑になるのであれば、登録状況が確認できてしまうリスクをとるほうが無難であるとも考えられますし、そのリスクが取れないのであれば、このフローを採用しないほうが良いかもしれません。
対策1-2: ログインIDに連絡手段(メールアドレス/電話番号)を使わない
懸念は同様ですが、対策が異なります。
対策1-1で行ったような疎通確認のタイミングがないので、その際にユーザに知らせることができません。
連絡手段以外のものをログインIDにする方法はあります。
システムが発行してしまうのが一番無難かと思います。
ログインIDを忘れたという問い合わせが多くなるかと思いますが、
それについては疎通確認を行っていないメールアドレスを利用して復旧(通知)することができます。
(同じメールアドレスに複数のログインIDが紐づいてしまってる可能性はありますので複数通知する必要は出てきます)
ユーザに決めさせる場合、該当サービスにそのログインIDが存在することは、どうしても確認できてしまいます(一意性は必要で、重複の有無はユーザに返す必要があるため)。
この対策をしつつ単一メールアドレスに複数のIDが紐づくのを避けるためには、そもそも登録時に連絡手段を登録させない・その後連絡手段を登録させるときは疎通確認を行う、という方法も考えられますが、ログインIDを忘れたユーザを救済できません。
観点3: ユーザが間違って第三者の連絡手段を入力してしまった場合、登録完了後第三者にパスワード復旧されることにより乗っ取られる可能性がある
観点2とほぼ同様です。
疎通確認が取れていないため、入力された連絡手段によるパスワード復旧は、観点2のような打ち間違えリスクがあります。第三者に突然パスワード復旧されてしまう可能性があります。
対策3: 疎通確認ができるまでパスワード復旧機能が使えない仕様とする
疎通確認が終わるまで第三者の連絡手段と紐づいている可能性があるため連絡先情報によるパスワード復旧は避けるほうが良いです。
この場合、パスワードを忘れたユーザの救済ができません。
絶対に救済したいユーザを定義し(コンテンツ購入済みのユーザは救いたいなど)、救済したいユーザに遷移するタイミング(この場合はコンテンツ購入)で疎通確認を強制する仕様とするのが良いと思います。
最後に
パターンC: 連絡手段入力 -> PINコード送信 -> PINコード入力 -> 個人情報入力
がUX的にもセキュリティ的にもバランスが良いのかなと考えています。
が、パターンD: 連絡手段と個人情報入力のみで登録を完了し疎通確認をしないのようなサービスが最近のサービス多い気がします。
(メールアドレス疎通確認を遅延させる)
また、SMSだけは疎通確認して、機能の限定解除にはアドレスの確認が必要といったかなり複雑なフローを踏むものもあります。
コストをかけてハードルを下げなければならないくらい、メールの疎通確認をめんどくさいと感じるユーザが多いのだなと強く感じます。
使用しているイラスト
下記からお借りしました
http://www.illusts.xyz/p/top.html