「自分のアカウントしか見られないはずのデータが、URLの数字を変えるだけで他人のものも表示されてしまった」——こうした事故が、Webアプリケーションで最も頻繁に発生している脆弱性カテゴリの一つです。
アクセス制御の不備(Broken Access Control)は、OWASP Top 10:2021で第1位に選ばれるほど広く蔓延しており、ログインに成功した後の「誰が何にアクセスできるか」を正しく制限できていないことが原因で起きます。
この記事では、アクセス制御の不備の仕組みと代表的な攻撃パターン、Webアプリケーションの開発・運用現場で今日から実践できる防御手順を、攻撃者の視点を交えて解説します。

アクセス制御の不備(Broken Access Control)とは?
アクセス制御の不備とは、ユーザーが本来許可されていないリソースや機能にアクセスできてしまう脆弱性です。英語では “Broken Access Control”(BAC)と呼ばれ、OWASP Top 10:2021では第1位に分類されています。OWASPの調査によれば、テスト対象アプリケーションの94%で何らかの形のアクセス制御の不備が検出されています。
「認証(Authentication)」と混同されがちですが、アクセス制御は「認可(Authorization)」に関わる問題です。認証は「あなたは誰か」を確認するプロセスで、認可は「あなたには何ができるか」を決めるプロセスです。正しくログインできても、その後のリソースアクセスの制限が不適切であれば、アクセス制御の不備が生じます。
具体的には次のような状況がアクセス制御の不備に該当します。
・他ユーザーのデータを閲覧できる: URLのユーザーIDを変えるだけで他人のアカウント情報や注文履歴が見られる
・一般ユーザーが管理者ページにアクセスできる: ログイン中のユーザーの権限チェックなしで管理機能が使える
・非公開コンテンツのURLに直接アクセスできる: 非公開設定にしても直リンクでアクセス可能
・APIエンドポイントに認証なしでアクセスできる: フロントエンドからは隠れていてもAPIを直接呼び出すと誰でもデータ取得できる
なぜアクセス制御の不備は減らないのか
これほど多く発生する理由は、開発現場の構造的な問題にあります。
「見えなければ安全」という誤解: 管理者メニューへのリンクをHTMLから消しても、URLを知っていれば誰でもアクセスできます。フロントエンドでボタンを非表示にするだけでは、アクセス制御の実装として不十分です。
開発スピードの優先: 機能開発を急ぐあまり、新しく追加したAPIエンドポイントにアクセス制御のコードを組み込む工程が抜け落ちることがあります。また、後から権限モデルを変更した際に、古いエンドポイントへの対応が漏れるケースも見られます。
テスト工程での見落とし: 機能テストは「正規ユーザーが正常に使えるか」を中心に行われることが多く、「権限のないユーザーがアクセスしたらどうなるか」の検証が後回しになりがちです。
攻撃者の視点から見た主な手口
攻撃者は以下の3つのパターンを中心に、アクセス制御の不備を突いてきます。いずれも難しい技術は不要で、ブラウザの開発者ツールとURLの書き換えだけで試せるものが大半です。
1. 水平方向の権限昇格(Horizontal Privilege Escalation)
同じ権限レベルを持つ他ユーザーのリソースへ不正にアクセスする手口です。「IDOR(安全でない直接オブジェクト参照)」と呼ばれることも多く、最も発見しやすい攻撃の一つです。
たとえば、自分の注文詳細ページのURLが https://example.com/orders/12345 だったとき、12345 を 12346 や 12347 に変えることで他人の注文情報が表示される——これが典型的な水平方向の権限昇格です。サーバーサイドで「ログイン中のユーザーが注文番号12346のオーナーであるか」を検証していないことが根本原因です。
2. 垂直方向の権限昇格(Vertical Privilege Escalation)
一般ユーザーが管理者など上位権限のユーザーのみアクセスできる機能を利用する手口です。管理画面のURLを直接入力したり、APIリクエストのパラメータを改ざんして管理者フラグを偽ったりすることで実現します。
たとえば、一般ユーザーとしてログイン後に https://example.com/admin/users へ直接アクセスすると管理者向けのユーザー一覧が表示されてしまう——というケースです。「管理者メニューへのリンクを表示しない」だけでは防げないことがわかります。
3. 機能レベルのアクセス制御欠如
HTTPメソッドを変えることでアクセス制御をすり抜けるケースも見られます。GETリクエストには認可チェックが実装されているのに、同じエンドポイントへのPUTやDELETEリクエストにはチェックが抜けている場合、攻撃者はデータを書き換えたり削除したりできます。
また、JWTトークンに含まれるロール情報をクライアント側で改ざんしてサーバーに送信し、サーバーがその値を無検証で信頼してしまうケースもこのパターンに該当します。
具体的な防御手順
アクセス制御の不備への対策は、開発の設計段階から組み込むことが重要です。後付けで修正しようとすると見落としが生まれやすくなります。
1. デフォルト拒否(Deny by Default)の原則を徹底する
「許可されていないものはすべて拒否」というデフォルト拒否の原則を実装の基本にします。「このユーザーはAにアクセスできる」と明示的に許可リストを定義し、それ以外はすべてアクセスを拒否します。
# デフォルト拒否の考え方(擬似コード) # NG: 管理者でなければ拒否(他の条件が漏れやすい) if not user.is_admin: return 403 # OK: 明示的に許可されたロールのみ通過(許可リスト方式) ALLOWED_ROLES = ['admin', 'editor'] if user.role not in ALLOWED_ROLES: return 403
また、最小権限の原則と組み合わせ、各ユーザーには業務に必要な最小限の権限のみを付与します。管理者権限の安易な付与は厳禁です。
2. サーバーサイドで必ずアクセス制御を実装する
アクセス制御の実装はクライアントサイド(フロントエンド)ではなく、必ずサーバーサイドで行います。JavaScriptでボタンを非表示にしても、APIに直接リクエストを送れば突破できます。
すべてのAPIエンドポイントへのリクエストにおいて、「このユーザーが要求しているリソースのオーナーか、または権限があるか」をサーバーサイドで検証するコードが必要です。
・リソースオーナー検証: データを取得・更新・削除するすべてのエンドポイントで「要求しているユーザー=データのオーナー」を確認する
・ロール検証: 管理機能・特権操作へのアクセス時にユーザーのロールをサーバーサイドで確認する
・HTTPメソッド別チェック: GET・POST・PUT・DELETE・PATCHそれぞれに対してアクセス制御を個別に適用する
・セッション無効化: ログアウト時にセッショントークンを必ず無効化し、再利用を防ぐ
DAC(任意アクセス制御)・MAC(強制アクセス制御)・RBACなど、システムの要件に合ったアクセス制御モデルを選定することも重要です。
3. アクセス失敗をログに記録して監視する
アクセス制御の失敗(403エラーや認可チェック失敗)を必ずログに記録し、不審なパターンを監視します。同一ユーザーや同一IPアドレスによる連続した403エラーは、パラメータを変えながら試行されている可能性を示しています。
ログに含めるべき最低限の情報は次のとおりです。
・タイムスタンプ
・要求ユーザーのID(匿名の場合は送信元IPアドレス)
・要求されたリソースのURL/エンドポイント
・拒否された理由(権限不足・オーナー不一致など)
ログを蓄積するだけでなく、閾値を超えた403エラーが発生した場合にアラートを飛ばす仕組みを整えると、早期発見につながります。
中小企業でも今日からできること
「うちはWebアプリを開発していないから関係ない」と思われるかもしれませんが、社内で使っているERPや勤怠管理システムなどのパッケージソフトも、設定次第でアクセス制御の不備が生まれることがあります。今日から着手できる対策を優先度順に挙げます。
・権限の棚卸し(最優先): 社内システムのユーザーアカウントを全洗い出しし、退職者・異動者のアカウントが残っていないか確認する。不要な管理者権限を削除する
・最小権限の適用: 各ユーザーに「業務に必要な最小限の権限」のみを付与する。「とりあえず管理者にしておく」は厳禁
・定期的な権限レビュー: 四半期ごとに権限の棚卸しを実施し、業務内容と権限が一致しているか確認する
・Webアプリのセキュリティ診断依頼: 自社または委託先が開発したWebアプリには、年1回以上のアクセス制御を含む脆弱性診断を実施する
・OWASP ASVSの参照: OWASPが公開している「Application Security Verification Standard」でアクセス制御の要件を体系的に確認できる
よくある誤解と注意点
【誤解1】「URLを秘密にしておけば安全」
これは “Security Through Obscurity”(隠ぺいによるセキュリティ)と呼ばれる考え方で、セキュリティの基本原則に反します。URLが攻撃者に知られた瞬間に保護は消えます。認可チェックはURLが知られても守れる形で実装する必要があります。
【誤解2】「認証さえできていれば問題ない」
ログインに成功しているユーザーだけを相手にしていても、そのユーザーが「誰の何にアクセスできるか」が制御できていなければ意味がありません。認証(Authentication)と認可(Authorization)は別の問題として設計する必要があります。
【注意】JWTのクライアント側改ざんに注意
フロントエンドからJWTに “role: admin” を追加してサーバーに送り、サーバーがその値を検証せずに信頼してしまうケースが実際に発生しています。JWTの署名検証は必ずサーバーサイドで行い、クライアントから送られてきたロール情報を無検証で使わないことが鉄則です。

本記事のまとめ
アクセス制御の不備(Broken Access Control)は、OWASP Top 10:2021の第1位に選ばれるほど頻繁に発生するWebアプリケーションの脆弱性です。認証に成功したユーザーでも、他人のデータや管理者機能に不正アクセスできる状態がこの脆弱性にあたります。
| 攻撃パターン | 具体例 | 主な対策 |
|---|---|---|
| 水平方向の権限昇格 | URLのIDを変えて他人のデータを閲覧(IDOR) | リソースオーナー検証をサーバーサイドで実装 |
| 垂直方向の権限昇格 | 一般ユーザーが管理者ページに直接アクセス | すべての管理機能にロール検証を実装 |
| 機能レベルの欠如 | HTTPメソッド変更やAPIの直接呼び出し | メソッド別・エンドポイント別に認可チェック |
対策の核心は「デフォルト拒否」と「サーバーサイドでの認可チェック徹底」の2点です。開発段階から設計に組み込み、定期的なセキュリティ診断で抜け漏れを確認することで、このリスクを大幅に低減できます。
Linuxサーバーのファイルパーミッションやユーザー権限管理についてさらに深く学びたい方は、姉妹サイトLinuxMaster.JPの権限管理解説もあわせてご参照ください。
PR
体系的に学ぶ 安全なWebアプリケーションの作り方 第2版(徳丸浩/SBクリエイティブ)
SQLインジェクション・XSS・アクセス制御の不備など、Webアプリケーションの主要な脆弱性を網羅的に解説。攻撃の仕組みから実装レベルの対策まで学べる、現場エンジニア必携の一冊です。
