見出し画像

OWASP API Security Top 10 2023 リリースバージョンを読んでみた

RCを書き換えようかとも思ったのですが、色々変更があったので別記事にしてみました。
大きな変更ではありませんが、順位が変わった、あるいは表現が変わったなどがRCとの違いです。

内容に変更がない場合は以前の記事をそのままコピペします。

API1:2023 オブジェクトレベルの認可の不備

原文: Broken Object Level Authorization
これは2019年から変わりません。

データベースでいうところのレコードレベルのアクセス権が設定されていないパターンです。
私がAPI関連の演習をするときによく社食の利用履歴を題材として使うのですが、このときにこんな声かけをします。
「社長が今日お昼何食べたか私が覗き見しますけどいいですか?」

例えば /api/cafeteria/v1/history/{userid} といったエンドポイントがあるとします。
このときにこのデータがセンシティブであれば、{userid} 本人にしかアクセスさせないようなアクセスコントロールが必要なのですが、実装が漏れてしまうと誰のトークンであってもどのユーザーIDのデータも返してしまうようなことになります。

従来型のWebアプリケーションであれば、これはあまり意識せずに実装できていたはずです。

従来型のWebアプリケーションのモデルAPI

従来型のWebアプリケーションであれば、認証の結果Cookieを払出し、なんらかのページへのアクセスがあったときはこのCookieが有効か、およびこのCookieが誰のCookieであるかを同じくサーバー側で確認の上、適切なユーザーのデータを返していたはずです。
機能要件を満たすためのユーザーの特定が、セキュリティを満たす方法にもなっていたんです。

ところがAPIの場合は、画面上に出すユーザーの特定をするコンポーネントと、セキュリティを満たすコンポーネントが別々に実装されることになってしまいました。

APIのモデル

画像を見るとおわかりいただけるかと思いますが、画面上に出すユーザーを特定できるのがAPIクライアント側、セキュリティを満たす側がサーバー側と別れてしまったことにより、意図して実装しないと脆弱性になってしまうようになりました。

API2:2023 認証の不備

原文: Broken Authentication
2019年版ではBroken User Authenticationとありましたが、おそらくこれが少し姿を変えたものではないかと思います。APIの場合はユーザーの認証とクライアントの認証がありますので、APIのシナリオをより広くカバーしたものではないでしょうか。

よく認証の自前実装はやめましょうというやつですね。
例えば認証が認証として成立していなかった、パスワードリセットのフローが不十分だった、アイデンティティを証明するトークンであるJWTに署名がなかったなど、不慣れな方が実装するとさまざまな抜け漏れが出ます。

餅は餅屋です。

API3:2023 Broken Object Property Level Authorization

オブジェクト属性レベルの認可の不備とでも訳しましょう。

API1がレコードレベルの認可の不備であれば、これはその中のカラムレベルの認可の不備です。
2019年版の「データの過剰な公開」および「一括割り当て」が一緒になったもののようです。

「データの過剰な公開」では、例えばユーザーオブジェクトで名前やメールアドレスの他に、パスワードやパスポート番号などのセンシティブな情報が同じテーブルにある場合、そのまま公開してしまうことで発生します。

例えばオブジェクトから参照されるサブオブジェクトに対しては、アクセス権の確認に実装漏れがありがちであることが指摘されています。特にGraphQLではやりがちですね。

例えば以下のようなJSONを返すときに、「Owner」以下の属性は全て返していいんでしたっけ。

{
	"id": 12345,
	"name": "abc repository",
	"owner": {
		"name": "Sachiko Kijima",
		"company": "xxx",
		"email": "sachiko.kijima@email.com",
		"phone": "080-1234-5678"             <--- これ大丈夫ですか?
	}
}

「一括割り当て」はユーザーに書き込みを許可していない属性への書き込みを許可してしまっている場合。
わかりやすい話で言うとレコードの作成日時やお買い物カートの「合計金額」のように、API経由の書き込みを許容してはいけないようなものはあるものの、エンドポイントとしては更新を許可しているので、作成日時や合計金額も一緒に更新を許可してしまうとこの問題がおきます。

API4:2023 Unrestricted Resource Consumption

サーバーリソース消費に対する制約の不備と訳しておきます。
2019年版では「リソース不足と帯域制限 (Lack of Resources & Rate Limiting)」という表現になっていました。

APIリクエストに対して守りが緩いと、CPUやメモリ、ディスク容量などを無制限に食ってしまい、パフォーマンストラブルになります。

レートリミットはきちんとかける、ページネーションはきちんと実装して無駄にレコード数を多く返さない、メッセージサイズの上限をきちんと設定して大きすぎるメッセージは許容しない、などなど、API管理基盤で実装できるものも多いので、ご活用ください。

ビジネス的なレートリミットとバックエンド保護のレートリミット

これ似ているようで少し違うので、実装に落とす時のコツとして追加コメントさせてください。
API Gatewayとサービスメッシュでなぜ流量制御の機能 (レートリミット) を持っているのかです。

API Gatewayで得意な流量制御はどちらかと言うとビジネス観点でかけたいレートリミットです。
サービスメッシュやリバースプロキシが得意なのは、バックエンド保護のレートリミットです。

API Gatewayが得意なのは、API Gatewayの外側から見た時にわかりやすい上限です。例えばマネタイズなどの文脈で上限を設けたいなどです。
どこのエンドポイントを呼んだかを正確にレートリミット機能でカウントしているかと言うと製品によります。

対してサービスメッシュやリバースプロキシが得意なのは、バックエンドのAPIサーバーのキャパシティから考えた時の流量制御です。つまりAPI Gatewayの外側から見たわかりやすさではなく、バックエンドのキャパシティが重要です。また、こちらはAPI Gatewayを通さない通信も対象にできます。

Unrestricted Resource Consumptionの対策にはサービスメッシュやリバースプロキシでの保護をお勧めします。

API5:2023 機能レベルの認可の不備

原文: Broken Function Level Authorization
2019年版にもあったものです。

REST APIは直感的に使えることが長所ですが、直感的に使えるからこそ直感的に悪さもしやすいんです。

例えば

  • GET /users があるのであれば PUT /users や POST /users も当然あるよね?

  • APIのドキュメントなどのURLの命名規則から /api/admin/v1/users/all のようなアドレスを割り出して実行するが、公開しないURLであるためかアクセスコントロールが実装されておらず、データが抜き取れてしまった

などです。

URLのパスセグメントを使って階層構造にする設計の方針はGithubなどで見られます。非常に使い勝手が良いのですが、反面パスセグメントが増えるとロールなどのアクセスコントロール単位との組み合わせでどこまでもパターンが増えていくので、実装上は注意する必要があります。

API6:2023 - Unrestricted Access to Sensitive Business Flows

こちらはRCでは [Lack of Protection from Automated Threats] と呼ばれていたものです。

2019年になかったもので、技術的には正規のアクセスに見えるものの、自動化によりビジネス的なインパクトがもたらされるものを脆弱性として上げた点は面白いと思います。

わかりやすい例だと転売ヤー対策ですね!
数量限定の新製品が出るとしましょう。売り出し開始時刻が決まっている場合、製品を買い物かごに入れて購入するまでを自動化したスクリプトを使うことで買い占めができてしまいます。

またゲームのスクリプトを使ったレベル上げなどもこちらに該当します。

守り方がなかなか難しいのですが、想定から外れたおかしな挙動をいかに検知するかにかかっています。
「想定から外れたおかしな挙動」がどういったものであるかを定義すること、またそれをブロックするための仕組みをきちんと盛り込んでおくことです。

例えばツールからのアクセスであればデバイスのフィンガープリントがあるかどうかで見分けがつく、あるいは買い物かごに入れてから購入完了まで1秒以下では成立するはずがないなどです。

API7:2023 - Server Side Request Forgery

サーバーサイドリクエストフォージェリー (SSRF)。
これは2019年版にはなかったと記憶してます。

例えばAPI経由でなんらかのURLを登録すると、サーバー側はそのURLにアクセスしてリソースを取得するようなものがあったとしましょう。
このときにアクセスするURLが悪さをするURLであれば、当然悪さをするリソースをサーバーに取り込んでしまいます。

例えばこのnoteで記事を書いた方はご存知かと思いますが、カバー画像を指定できますよね。
noteの場合はnoteの中で登録されたものか、あるいは自分がアップロードしたものを使っているので問題ないと思います。
もしnoteが「任意のインターネット上のどんな画像でもURLがあれば取り込みます!」という機能拡張をしたとします。
このときにはこれが本当に画像なのか、そのホストは信頼できるのかなど、アクセスしようとしているURLやファイルなどをチェックしてから取り込みをする必要があります。

API8:2023 セキュリティ設定ミス

原文: Security Misconfiguration

読んで字の如く。
例えば1年ほど前に公開になったlog4jに脆弱性があったことは有名ですが、このように脆弱性を含む環境はきちんと修正する、ログに不用意な内容が書かれないように注意する、使わないHTTPメソッドは使えないように塞ぐなどきちんと対応しましょう。

API9:2023 Improper Inventory Management

2019年版ではImproper Assets Management、不適切な資産管理と訳されていました。

例えば古いバージョンがリタイアせずに残ってしまうとそこが狙われる、あるいは比較的守りの緩いステージングなどの本番環境以外で同じ機能をなんらかの目的で保持している環境が狙われるなどです。

ドキュメントに明記していないということは、セキュリティを担保しないことを覚えておきましょう。

API10:2023 Unsafe Consumption of APIs

安全でないAPIの利用とでも訳しておきます。
2019年版には完全一致するものはなかったですが、「インジェクション」が形を変えたものではないかと思います。

これはAPIサーバーがAPIクライアントとして別のAPIを呼びに行く時の落とし穴です。
APIを実装する側は、リクエストとして受信したHTTPの内容には気をつけるものの、自分がAPIクライアントとしてどこからか取得したデータは信頼してしまう傾向にあります。その安心感を狙われるパターンです。

外部のデータも守りがゆるければ不正なデータを保持してしまうこともあります。
外部のAPIから取得したデータもきちんとバリデーションしてから処理を実行しましょう。

この記事が気に入ったらサポートをしてみませんか?