ログインできたのに、別の人の注文まで見えてしまう。

そんなAPIは、ログイン機能が正常に動いていても安全とはいえません。

APIセキュリティでは、誰が呼んだかに加え、その人がどのデータに何をしてよいかを、サーバー側で確かめます。

この記事では、架空の注文APIを例に、設計とテストでどこを見ればよいかを図で整理します。

解説者のアイコン
外資系エンジニア

この記事は以下のような人におすすめ!

  • APIを初めて設計・レビューする人
  • 認証と認可の違いを具体例で知りたい人
  • 公開前に使える確認項目を探している人

APIの入口では「誰が」「何をするか」を分けて見る

1-1. アプリの画面を飛ばしても、同じ制約が必要

注文履歴を開くと、画面の裏ではアプリがAPIに問い合わせ、サーバーが注文を返します。

画面は使いやすい入口ですが、どの注文を返してよいかを最終判断するのはサーバーです。

例えば、一覧画面に自分の注文だけを表示していても、詳細APIが別の注文を返すなら保護はできていません。

ボタンを隠す工夫は操作ミスを減らしますが、アクセス制御の代わりにはなりません。

HTTPSで届いた注文の参照要求は、利用者確認、対象の権限確認を通ってからデータを返します。
図1:APIの入口で、認証と認可を順に確認。サーバーが許可と判断してから、注文データを読み出す説明例です。

1-2. 認証、認可、暗号化が答える質問

認証は「呼び出しているのは誰か」、認可は「その人がその操作をしてよいか」を確かめる処理です。

認証で会員Aと分かっても、会員Bの注文を読んでよいことにはなりません。

HTTPSは、通信の途中でデータを読まれたり書き換えられたりしにくくするために使います。

通信を暗号化しても、サーバーが誤って別人の注文を返す問題は残ります。

守る場所がそれぞれ違う、と覚えると混乱しません。

(参考1)

REST APIとは何か?初心者にもわかりやすく解説します!REST APIとは何か?この記事では、初心者から上級者まで、REST APIがどのようにウェブの世界を支え、私たちの生活を豊かにしているのかをわかりやすく解説します。セキュリティやパフォーマンスのベストプラクティスまで、これを読めば、あなたもREST APIのプロフェッショナルの道を歩み始めることができます。 ...

ログイン済みでも、他人の注文は見せない

2-1. 注文番号は権限の証明にならない

会員Aには A-104、会員Bには B-205 という注文があるとします。

注文詳細のAPIが「指定された番号の注文を探す」だけなら、AからBの注文番号が届いたときも返してしまいます。

サーバーは、認証済みの主体と、対象の注文との関係を確認します。

本人、同じ組織内の担当者、サポート担当など、どの関係で参照が許されるかはサービスごとに決めます。

端末から送られてきた所有者の申告をそのまま信用すると、判断の根拠が利用者の入力に戻ってしまいます。

会員Aが自分の注文を参照すると許可、他の会員の注文なら対象に対する権限がないため拒否する例です。
図2:同じ会員Aでも、参照する注文で結果が変わる。②と③は別々の要求です。ログインに成功した事実はどちらも同じです。

2-2. IDの変更を想定した設計にする

こうした問題は、OWASPのAPI Security Top 10 2023で、オブジェクト単位の認可の不備、BOLAと呼ばれています。

ここでいうオブジェクトは、注文やファイルのように、APIがIDで指定して扱う一つのデータです。

注文番号を推測しにくくすると偶然の発見は減らせますが、別の経路で番号を知った場合にも拒否できる必要があります。

詳細だけでなく、更新、削除、一覧、ダウンロードも、操作ごとに許可条件を揃えてください。

例えば、サポート担当が参照できることと、配送先を変更できることは別です。

(参考2)

トークン・入力・返却データを守る

3-1. 有効なトークンでも、できる操作には範囲がある

アクセストークンは、APIへアクセスするときに使う資格情報です。

発行元や有効期限など、その方式で検査すべき条件を確認します。

JWTを使う設計なら、読み取れたというだけで信用せず、署名や対象サービスも設定したルールで検証します。

注文を「読む」権限を持つトークンを受け付けた後も、その人が指定された注文を読めるかは別に判定します。

OAuthの仕組みを取り入れたことだけで、この対象単位の判断が自動で備わるわけではありません。

(参考1)

トークンの条件、入力の形式、返却項目をそれぞれ確認し、どこか一つで全てを済ませない設計です。
図3:要求を受け付ける前後で見るポイント。署名の確認、入力の検証、項目の選別は、それぞれ別の目的を持ちます。

3-2. 画面に見えない項目も、返せば届いている

例えば、注文一覧に注文日と配送状況しか出さないなら、APIが内部メモまで返す理由はありません。

画面に表示されなくても、応答を受け取る側にはデータが届いています。

反対に、変更時は「受け取ってよい項目」を限定します。

配送希望日を変えるAPIで、金額や承認状態を一緒に受け取ってそのまま保存しないようにします。

読み取りと書き込みを、項目の単位でも分けて考えるのがポイントです。

(参考3)

OAuth2.0とは?基本概念から最新のOAuth2.1まで徹底解説!OAuth2.0とは、Webサービスやアプリで安全に認可を行うための標準プロトコルです。本記事では、OAuth 2.0の基本概念、認証と認可の違い、主要な認可フローの選び方、アクセストークンの管理方法まで解説します。実践的な内容を交えて説明するので、OAuth 2.0を理解し、安全に活用したい方はぜひご覧ください。...

公開前に、許可と拒否をセットで確認する

4-1. 二人分のダミーデータで期待結果を決める

自分の注文が見えることだけをテストすると、他の人の注文も見える実装を見落とします。

許可を受けた検証環境で会員AとBのダミーデータを用意し、正しい要求と、拒否されるべき要求を対にします。

例えば下の表のように、呼び出す主体、対象、操作を固定します。

失敗したときはステータスだけでなく、応答本文に注文情報が含まれていないか、更新処理なら保存された値に変化がないかも確認します。

主体対象と操作確認したい結果
会員A自分の注文 A-104 の参照必要な項目だけ返る
会員A会員Bの注文 B-205 の参照注文の内容を返さない
会員A参照のみ許可された注文の変更変更を拒否し、保存値も不変
認証情報なしA-104 の参照認証を要求し、注文の内容を返さない
検証用の二人の会員を用意し、許可と拒否を試して、本文と保存結果まで照合する手順です。
図4:テストでは画面・応答・保存値を分けて確認。画面にエラーが出ても、データが返ったり更新されたりしていないかまで確認します。

4-2. 拒否理由の手がかりを残す

HTTPの401は、対象への有効な認証資格情報がないことを示します。

403は、要求を理解したうえで実行を拒否する応答です。

存在を隠したい対象について404を返せる場合もあります。

サービスの方針を決め、拒否した画面に内部情報を出しすぎないようにします。

(参考4)

ログでは、追跡用のリクエストID、時刻、操作、結果などを残すと、問い合わせに対応しやすくなります。

一方で、トークンや注文の詳細を丸ごと残すと、ログから漏れる範囲が広がります。

何があれば調べられるかを決めてから、記録する項目を絞りましょう。

4-3. 一度に取得できる量も決めておく

本人の注文でも、1回で大量のデータを返す要求を許すと、処理能力を圧迫する場合があります。

1ページの件数、要求の頻度、重い操作の扱いを、正常な利用の範囲と照らして決めます。

頻度制限の応答を受けたクライアントは、即座に繰り返すと負荷を増やします。

例えばMicrosoft Graphは429を返すときの待機方法を公開しています。

これは製品の例なので、自分が使うAPIでも同じ挙動と決めつけず、提供元の説明を確認してください。

(参考5)

確認やテストは、許可された検証環境とダミーデータで行います。

よくある質問

5-1. APIキーを付ければ利用者の認可も済みますか?

APIキーは、アプリやプロジェクトの識別や利用制限に使われることがあります。

利用者のIDや対象データの権限を表すかはサービスの方式次第です。

キーが有効かどうかだけで、別の利用者の注文を読めると判断しないでください。

5-2. 自分の組織内だけなら認可は省けますか?

社内でも部署や担当によって見てよい情報が違います。

例えば経理と配送担当が同じ注文を参照しても、見せる項目が同じとは限りません。

ネットワークの内側であることは、個別データの許可とは分けて扱います。

5-3. UUIDに変えればBOLAは防げますか?

UUIDのような推測しにくいIDは役立つ場合がありますが、IDが知られたときに拒否できる仕組みが必要です。

注文番号の種類を変えるより先に、対象への権限を判断する処理を確認します。

APIキー、社内ネットワーク、推測しにくいIDだけでは注文単位の認可を置き換えられません。
図5:混同しやすい3つの対策を整理。どの対策も役割があります。対象データを返す判断はサーバーに残します。

まとめ:1つのAPIで、許可と拒否を言葉にする

最初からすべてのAPIを点検するのは大変です。

まずは個人情報や支払い情報を扱うAPIを一つ選び、誰が、どの対象に、何をしてよいかを書き出してみてください。

会員Aが自分の注文を読めること、Bの注文は読めないこと。

その二つを検証環境で同時に確認できれば、仕組みを点検する足場になります。

設計レビューでも「ログインは付いていますか」から一歩進めて、「このIDの注文に対する許可はどこで確認しますか」と聞けます。

守りたいAPIを一つ選び、対象ごとの許可条件を書き、検証で拒否まで確認します。
図6:設計から確認までの小さな一巡。設計書に条件を書くだけで終えず、拒否される場面まで確認します。

参考資料