OWASP API Security Top 10 (2023) RCを読んでみた
新しいバージョンがRC (Release Candidate、リリース候補バージョン) になっているようです!
せっかくなので読んでみましょう。
正式にリリースされたら別の記事書くか、この記事を更新します。
オリジナルはこちら。まだGithubにあります。
ここからはまだ日本語の翻訳がないので、2019年版からタイトルの表現が変わっていないものは2019年版の日本語訳を踏襲し、表現が変わっているものや新しいものは英語で表現して本文中に適当な訳文をつけておきます。
ここでは概要をご紹介しますが、上記の記事の中に脆弱性の例や守り方など書かれていますので、ご興味があればぜひ直接ご確認ください。
API1:2023 オブジェクトレベルの認可の不備
原文: Broken Object Level Authorization
これは2019年から変わりません。
データベースでいうところのレコードレベルのアクセス権が設定されていないパターンです。
私がAPI関連の演習をするときによく社食の利用履歴を題材として使うのですが、このときにこんな声かけをします。
「社長が今日お昼何食べたか私が覗き見しますけどいいですか?」
例えば /api/cafeteria/v1/history/{userid} といったエンドポイントがあるとします。
このときにこのデータがセンシティブであれば、{userid} 本人にしかアクセスさせないようなアクセスコントロールが必要なのですが、実装が漏れてしまうと誰のトークンであってもどのユーザーIDのデータも返してしまうようなことになります。
従来型のWebアプリケーションであれば、これはあまり意識せずに実装できていたはずです。
従来型のWebアプリケーションであれば、認証の結果Cookieを払出し、なんらかのページへのアクセスがあったときはこのCookieが有効か、およびこのCookieが誰のCookieであるかを同じくサーバー側で確認の上、適切なユーザーのデータを返していたはずです。
機能要件を満たすためのユーザーの特定が、セキュリティを満たす方法にもなっていたんです。
ところが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管理基盤で実装できるものも多いので、ご活用ください。
API5:2023 機能レベルの認可の不備
原文: Broken Function Level Authorization
2019年版にもあったものです。
REST APIは直感的に使えることが長所ですが、直感的に使えるからこそ直感的に悪さもしやすいんです。
例えば
GET /users があるのであれば PUT /users や POST /users も当然あるよね?
APIのドキュメントなどのURLの命名規則から /api/admin/v1/users/all のようなアドレスを割り出して実行するが、公開しないURLであるためかアクセスコントロールが実装されておらず、データが抜き取れてしまった
などです。
API6:2023 Server Side Request Forgery
サーバーサイドリクエストフォージェリー (SSRF)。
これは2019年版にはなかったと記憶してます。
例えばAPI経由でなんらかのURLを登録すると、サーバー側はそのURLにアクセスしてリソースを取得するようなものがあったとしましょう。
このときにアクセスするURLが悪さをするURLであれば、当然悪さをするリソースをサーバーに取り込んでしまいます。
例えばこのnoteで記事を書いた方はご存知かと思いますが、カバー画像を指定できますよね。
noteの場合はnoteの中で登録されたものか、あるいは自分がアップロードしたものを使っているので問題ないと思います。
もしnoteが「任意のインターネット上のどんな画像でもURLがあれば取り込みます!」という機能拡張をしたとします。
このときにはこれが本当に画像なのか、そのホストは信頼できるのかなど、アクセスしようとしているURLやファイルなどをチェックしてから取り込みをする必要があります。
API7:2023 セキュリティ設定ミス
原文: Security Misconfiguration
読んで字の如く。
例えば1年ほど前に公開になったlog4jに脆弱性があったことは有名ですが、このように脆弱性を含む環境はきちんと修正する、ログに不用意な内容が書かれないように注意する、使わないHTTPメソッドは使えないように塞ぐなどきちんと対応しましょう。
API8:2023 Lack of Protection from Automated Threats
自動化された脅威からの保護の欠如とでも訳しましょう。早く日本語訳が出るといいな。
2019年になかったもので、技術的には正規のアクセスに見えるものの、自動化によりビジネス的なインパクトがもたらされるものを脆弱性として上げた点は面白いと思います。
わかりやすい例だと転売ヤー対策ですね!
数量限定の新製品が出るとしましょう。売り出し開始時刻が決まっている場合、製品を買い物かごに入れて購入するまでを自動化したスクリプトを使うことで買い占めができてしまいます。
またゲームのスクリプトを使ったレベル上げなどもこちらに該当します。
守り方がなかなか難しいのですが、想定から外れたおかしな挙動をいかに検知するかにかかっています。
「想定から外れたおかしな挙動」がどういったものであるかを定義すること、またそれをブロックするための仕組みをきちんと盛り込んでおくことです。
例えばツールからのアクセスであればデバイスのフィンガープリントがあるかどうかで見分けがつく、あるいは買い物かごに入れてから購入完了まで1秒以下では成立するはずがないなどです。
API9:2023 Improper Inventory Management
2019年版ではImproper Assets Management、不適切な資産管理と訳されていました。
例えば古いバージョンがリタイアせずに残ってしまうとそこが狙われる、あるいは比較的守りの緩いステージングなどの本番環境以外で同じ機能をなんらかの目的で保持している環境が狙われるなどです。
ドキュメントに明記していないということは、セキュリティを担保しないことを覚えておきましょう。
API10:2023 Unsafe Consumption of APIs
安全でないAPIの利用とでも訳しておきます。
2019年版には完全一致するものはなかったですが、「インジェクション」が形を変えたものではないかと思います。
これはAPIサーバーがAPIクライアントとして別のAPIを呼びに行く時の落とし穴です。
APIを実装する側は、リクエストとして受信したHTTPの内容には気をつけるものの、自分がAPIクライアントとしてどこからか取得したデータは信頼してしまう傾向にあります。その安心感を狙われるパターンです。
外部のデータも守りがゆるければ不正なデータを保持してしまうこともあります。
外部のAPIから取得したデータもきちんとバリデーションしてから処理を実行しましょう。
感想
面白かったです!
個人的に好きなのは [API8:2023 Lack of Protection from Automated Threats] です。こういうのなかなかセキュリティの観点では上がってこないので、OWASPが光を当ててくださって非常にありがたい。
セキュリティというとどうしてもプラットフォーム的なとか、ネットワーク的なとか単純に技術的な領域が注目されがちですが、こういうビジネスレベルから見た時の脆弱性というのが定義されるとまた見方も変わると思います。