令和6年度 春期 情報処理安全確保支援士試験 午後 問1|「署名なし」で他人になりすませたAPI—情報処理安全確保支援士で学ぶJWT・認可不備・Log4Shellの実例
この記事で扱うセキュリティ事例
試験区分: 情報処理安全確保支援士
出典: 令和6年度 春期 情報処理安全確保支援士試験 午後 問1
主なテーマ: APIセキュリティ、JWTの署名検証不備(alg=none攻撃)、オブジェクトレベルの認可不備(BOLA/IDOR)、ブルートフォースとアカウントロック、Log4Shell型のJNDIインジェクション、WAFのルール設計と遮断/検知モードの使い分け
この記事は「情報処理安全確保支援士 午後問題 全70問」シリーズの1本です。→ 全70問の一覧・テーマ別索引はこちら
導入: なぜこの事例が重要なのか
スマホアプリと連携するクラウドサービスは、いまや珍しくありません。食事や体重を記録して健康アドバイスを受ける——そんなヘルスケアサービスの裏側では、アプリとサーバが「API」という窓口を通じて絶え間なくデータをやり取りしています。便利さの裏で、この窓口がどれほど無防備になりうるか。情報処理安全確保支援士試験の令和6年春期午後問1は、まさにその「APIの守り」を正面から扱った事例です。
この事例の怖さは、派手なマルウェアやゼロデイ攻撃ではなく、設計と実装の「当たり前の抜け」が積み重なっている点にあります。署名を確認しているはずのトークンが「署名なし」で通ってしまう。自分のIDしか送れないはずのAPIに他人のIDを入れると、他人のデータが見えてしまう。何度パスワードを間違えてもロックがかからない。そして、世界を震撼させたLog4Shell型の脆弱性が、自社のシステムにも潜んでいるかもしれない——。
この記事を読むと、JWT(ジェイ・ダブリュー・ティー)という認証トークンの仕組みと、その「アルゴリズム指定」を悪用する攻撃、APIで頻発する認可不備(他人になりすませてしまう穴)、そしてJNDIインジェクションというリモートコード実行の流れと、それをWAFでどう食い止めるかが、一本のストーリーとして見えてきます。受験者には頻出の最新論点が詰まっており、SaaSを運営・発注する立場の経営者には「APIの安全はベンダー任せにできない」という現実を突きつける教材になります。
インシデントの概要

舞台は、ヘルスケアサービスの新興企業であるG社です。利用者が食事や体重などを入力すると、そのデータを蓄積し、機械学習で健康リスクの判定や食事メニューのアドバイスを提供する——そんなサービス(以下、サービスY)を立ち上げようとしていました。
サービスYの中核となるのが、クラウド上に構築された「Sシステム」です。利用者は、G社が開発したスマートフォン専用アプリ(以下、G社スマホアプリ)から、このSシステムにアクセスします。将来的には他社のアプリからもアクセスできるよう、SシステムにはRESTful API方式のAPI(以下、S-API)が用意されました。RESTful API(Webの仕組みを使ってデータをやり取りする標準的なAPIの作り方)には、「セッション管理を行わない」という設計原則があります。この、リクエストごとに状態を持ち越さない性質を「ステートレス」と呼びます。これが設問1の空欄aの答えにあたります。
Sシステムの構築は、ITベンダーのF社に委託されました。F社との協議の結果、クラウドサービスプロバイダE社のクラウド上にSシステムを構築する方針となります。E社のクラウドには、APIゲートウェイサービス(サービスK)、イベント駆動型のコンピューティングサービス(サービスL)、マネージド型データベース(サービスM)、そしてマネージド型のWAFサービス(サービスN)が揃っていました。WAF(Web Application Firewall:Webアプリへの通信を検査して不正なリクエストを止める仕組み)であるサービスNは、しかし、Sシステムの構築時点では「導入しない計画」だったのです。この判断が、後の物語に効いてきます。
そして、利用者の本人確認とAPIアクセスの許可には、JWTという技術が使われていました。すべての準備が整い、全機能の動作確認も終わったところで、G社のセキュリティ担当であるRさんは、セキュリティベンダーであるU社に脆弱性診断を依頼します。ここから、Sシステムに潜む穴が次々と明るみに出ていきます。
何が起きたのか

U社の診断レポートが返ってきたとき、Rさんは静かな衝撃を受けたはずです。そこには、リリース直前のシステムに対して、なりすましやデータ改ざんを許す穴がいくつも並んでいました。
最初に問題となったのは、JWTを使った認証の仕組みそのものでした。JWT(JSON Web Token:利用者情報を含む小さなトークンに署名を付け、改ざんを検知できるようにした認証用のデータ)は、「ヘッダ」「ペイロード」「署名」という3つの要素から成り立ちます。ヘッダには署名を作るときのアルゴリズムが書かれ、ペイロードには利用者IDや有効期限が入り、署名はその両者をシークレット(秘密の鍵)で署名したものです。利用者は認証に成功するとJWTを受け取り、以後はそのJWTをリクエストに添えるだけで「本人である」と認められます。SシステムはこのJWTを、F社が開発したJWT管理ライブラリ(ライブラリQ)で検証していました。
ところが、U社のセキュリティコンサルタントで登録セキスペのZ氏が示した検証結果は、ぞっとするものでした。ある利用者「user01」で正規に認証して得たJWTを取り出し、ヘッダに書かれていた署名アルゴリズム「RS256」を、わざと「NONE(なし)」に書き換える。そしてペイロードの利用者IDを、user01から他人のIDに改ざんする。この、署名がもはや正しくないはずの偽造JWTを送りつけたところ——Sシステムは、あっさりと検証を「成功」と判定し、他人へのなりすましを許してしまったのです。
これは「alg=none攻撃」と呼ばれる、JWTの古典的な弱点です。JWTのヘッダには「どのアルゴリズムで署名を検証するか」が書かれていますが、その指定が「none(署名なし)」だった場合に、ライブラリが「署名検証をスキップしてよい」と解釈してしまう実装があるのです。攻撃者が送ってきたトークンに「署名は不要」と書いてあるのを、サーバが鵜呑みにする——いわば、訪問者が自分で「身分証の確認は不要です」と書いた紙を提示し、受付がそれを信じてしまうようなものです。署名という仕組みは、検証する側がアルゴリズムを主導しなければ意味がない。ライブラリQには、この検証が欠けていました。
問題はJWTだけではありませんでした。利用者情報を扱う利用者APIには、利用者IDを表すパラメータ「mid」を指定して、情報の取得(GET)や更新(PUT)を行う仕組みがありました。診断では、このmidに「他人の利用者ID」を指定すると、他人の利用者情報を取得したり、改変したりできてしまうことが判明します。本来、JWTで「あなたはuser01だ」と確認しているのですから、user01はuser01のデータしか触れないはずです。ところが実装は、JWTで本人確認はするものの、「midで指定されたIDが、本人のIDと一致しているか」をまったく確認していませんでした。これが、APIセキュリティで最も頻発する「オブジェクトレベルの認可不備」です。
さらに悪いことに、利用者情報を更新するPUTのリクエストに、仕様には存在しないパラメータ「status」を、値「paid(有償)」付きで追加して送ると、利用者ステータスが無償利用者から有償利用者に書き換えられてしまいました。お金を払わずに有償機能を使えるようになる、という直接的な被害です。利用者APIの実装は、F社が開発済みの「共通モジュールP」を呼び出していましたが、その「P呼出し処理」は、受け取ったパラメータを検証せずにすべて共通モジュールPへ丸ごと渡していました。だから、本来想定していないstatusパラメータまでもが処理され、ステータスが変わってしまったのです。
そして4つ目。認証は「パスワード」と「メールに送られる4桁の数字(文字列X)」による2要素認証になっていましたが、この文字列Xが総当たり攻撃に弱いことが指摘されました。4桁の数字は0000〜9999の1万通り。1秒間に10回試行できる攻撃で、平均すると半分の5000通りを試した時点で当たる計算になります。5000回÷10回毎秒で、平均500秒。わずか8分強で突破されうる——これが設問2(1)の空欄bの「500」です。しかもアカウントロックの仕組みがなかったため、攻撃者は延々と試行を続けられました。
すべての穴をふさぎ、試用モニター向けにサービスを開始した矢先、今度は外からの脅威が襲いかかります。広く使われるオープンソースのライブラリ「ライブラリH」に、深刻な脆弱性Vが公表されたのです。攻撃の流れはこうでした。攻撃者はあらかじめ攻撃用のLDAPサーバとHTTPサーバを用意し、実行させたいコマンドを仕込んだ攻撃文字列を作る。それをHTTPリクエストの「x-api-versionヘッダ」に埋め込んで送りつける。すると、ライブラリHを使う攻撃対象サーバがその文字列を処理する際にJNDI Lookup(Java Naming and Directory Interface Lookup:Javaが外部の名前解決サービスから情報を取得する仕組み)を実行し、攻撃用LDAPサーバへ接続。攻撃用サーバは悪意あるJavaプログラムの在り処を返し、攻撃対象サーバがそれをダウンロードして実行してしまう——任意のコマンドが実行される、リモートコード実行です。脆弱性VのCVSS基本値は9.8という最高水準。これは一般論として、2021年に世界を揺るがしたLog4Shell(CVE-2021-44228、Log4jというログ出力ライブラリのJNDIインジェクション脆弱性)とよく似た構図です。
RさんがライブラリHを使っているかF社に問い合わせても、回答までは時間がかかる。E社のWAFルールも、網羅的なものの提供には最大72時間かかるという。待っている間に攻撃されたら——。Z氏の助言のもと、Rさんは「システムに影響を与えない検証コード」を自ら送り込み、外部から脆弱性Vを悪用できるかを確かめる、緊迫した検証へと踏み出します。
ここから先は

情報処理安全確保支援士(登録セキスペ)の午後問題、「読んでも頭に入らない」と感じていませんか?本シリーズでは、2017年〜2025年の過去…
この記事が気に入ったらチップで応援してみませんか?
