「ログイン機能を付けたから、もう守れている」——これは危ない思い込みです。実際には、ログイン(認証)と権限(認可)は別物で、ここを取り違えるとログインした人が全員、他人の分まで含めて全データを見られる事故が起きます。攻撃手順は伏せ、仕組みと守り方を解説します。
認証と認可は別物
混同されがちですが、役割はまったく違います。
認証だけ(ありがちな誤解)
- 「ログインできる=安全」と考える
- ログイン後のデータ取得を全員同じに扱う
- 結果:ログインした人は全員、全データに到達
認証+認可(あるべき姿)
- 認証で「誰か」を確かめる
- 認可で「その人が触れてよいデータだけ」に限定する
- データ取得は常に本人の所有分でスコープ
認証は「入口での本人確認」、認可は「入ってよい部屋の制御」。ログイン機能は前者しか保証しません。「誰がどのデータに触れてよいか」は、あなたが別に書く必要があります。
自作アプリで“全データ閲覧”が起きる仕組み
現場では、独立した複数の自作システムで同じ穴が繰り返し見つかります。たとえば——個人用のタスク/メモ管理アプリでも、小規模な商品・受注管理システム(外部API連携あり)でも、原因は同じ2つの欠陥の重なりでした。
① 登録が開いている(しかも二重経路)
認証スキャフォールド(Laravel の Breeze/Jetstream に類する仕組みなど)は、初期状態で新規登録ページが公開されていることが多い。さらに UIライブラリ側と認証パッケージ側で登録ルートが二重化していると、片方を塞いでも /register が残る。URLを知る第三者が登録できてしまう。
② 認証はあるが認可が無い(所有者スコープの欠落)
データのテーブルに所有者カラム(user_id)が無い、または一覧・取得・更新・削除のクエリを本人で絞り込んでいない。すると「ログイン=全データへのアクセス」になる。登録直後に自動ログインする実装なら、第三者は登録した瞬間に他人のデータ一覧へ着地する。
結果:認証 ≠ 認可 の事故
入口(ログイン)は付いているのに、部屋の鍵(認可)が無い状態。第三者は「正規にログインした利用者」として振る舞えるため、不正アクセスの痕跡すら残りにくい。
商品・受注管理のような業務データを扱う側ほど爆発半径が大きい(顧客情報・注文・連携先のAPIキーなどに波及しうる)点も見逃せません。同じ作り方をした別のシステムには、同じ穴がある可能性が高いのです。
守り方
データは必ず所有者でスコープする
すべての読み書きを「ログイン中の本人の所有分」に限定する。ORMのグローバルスコープや認可ポリシー(ポリシー/ゲート)で、取得・更新・削除のすべてに所有者条件を強制する。テーブルに所有者カラムが無いなら、まずそこから設計し直す。
不要な登録は即閉じる・経路の二重化を疑う
個人/内部アプリは新規登録を無効化。/register 等が実際に 404 になるかをHTTPで実測し、UIライブラリと認証パッケージの両方の登録経路を確認する。
管理系は多層防御
内部・管理用途は、認証だけに頼らず IP 制限や Basic 認証などを重ねる。1枚の壁が抜けても次で止める。
監査ログとアクセスログを“事故る前”に
「誰が・いつ・どのIPで・何を」を残していないと、事故後に『何が見られたか』を追跡できない。最低でもログイン成否の監査ログと、Webアクセスログの保持・ローテーションを用意する。
新規登録・異常を検知する
今回の教訓の核心は「長期間気づかなかった」こと。新規ユーザー登録の通知、定期的なユーザー/データの棚卸しなど、早く気づく仕組みを入れる。検知が無ければ、穴は静かに開いたままになる。
当サイトの視点:ライブラリは『誰か』までしか保証しない
認証ライブラリが面倒を見てくれるのは「誰か」までです。「その人が何をしてよいか」は、設計者であるあなたが書かないと存在しません。そして——1つのシステムで見つかった構造欠陥は、同じ作り方をした他のシステムにもあると考えるのが安全です。1件直して終わりにせず、同種構成を横断で点検しましょう。読まれたかどうかが追跡不能なときは、「読まれた前提」で露出した秘密を失効・ローテートするのが正しい姿勢です。
次に読む
- 用語:IDOR(アクセス制御の不備)とは(他人のIDを指定して他人のデータに届く典型)
- 実装:フレームワーク別セキュリティ(入口)(各フレームワークで「認可をどこに書くか」を具体化)
- 関連:公開ディレクトリに秘密ファイルを置かない(token/credentials/.env の露出点検)
- 入門:秘密の守り方・超入門 / 土台:セキュリティ最低限チェックリスト
出典
- OWASP Top 10 (2021) A01: Broken Access Control: owasp.org
- OWASP Authorization Cheat Sheet: cheatsheetseries.owasp.org
よくある質問
Q認証(Authentication)と認可(Authorization)はどう違うのですか?
認証は『あなたが誰か』を確かめること(ログイン)。認可は『その人が何をしてよいか』を決めること(権限)です。例えるなら、認証は建物の入口で本人確認をすること、認可は『その人が入ってよい部屋はどこか』を制御すること。ログイン機能を付けただけでは認証しか実装できておらず、認可(誰がどのデータに触れてよいか)は別に書く必要があります。ここを混同すると『ログインした人は全員、全データを見られる』状態になります。
Qログイン機能があるのに、なぜ全データが見えてしまうのですか?
データ取得のクエリを『ログイン中の本人の分だけ』に絞り込んでいないからです。たとえば一覧・取得・更新・削除のどれかで所有者(user_id)の条件を付け忘れると、ログインさえ通れば他人の分も含めて全件が返ります。認証の有無とは無関係に起きる設計の穴で、OWASP Top 10 で最上位に位置づけられる Broken Access Control(アクセス制御の不備)の典型です。
Q個人ツールや社内アプリなら、登録を開けっ放しでも大丈夫では?
危険です。多くの認証スキャフォールドは初期状態で新規登録(/register など)が公開されています。URLさえ分かれば第三者が登録でき、認可が無ければそのまま中のデータに到達します。しかも登録経路が二重化(UIライブラリと認証パッケージの両方)していることがあり、片方だけ塞いでも閉じません。不要な登録は即無効化し、管理系はIP制限などの多層防御を重ねるのが安全です。