午前I問題
データのシリアライゼーション(直列化)とデシリアライゼーション(非直列化)に関する記述として、適切なものはどれか。
ア)シリアライゼーションとは、バイナリデータをテキスト形式のJSONに変換する処理のことであり、暗号化と同等のセキュリティ効果を持つ。
イ)デシリアライゼーションとは、シリアライズされたデータ(オブジェクトの状態を表す文字列やバイト列)から元のオブジェクトを復元する処理であり、信頼できない入力を復元する場合は任意コード実行につながる危険がある。
ウ)JSON形式はXML形式と異なり外部実体参照(External Entity)の仕組みを持たないため、JSONを扱う処理には脆弱性が一切存在しない。
エ)デシリアライゼーションは復元対象のデータ構造が固定されているため、入力検証を行わなくても安全である。
午前I の解答・解説を見る
正解: イ
解説:
- ア)不正解。シリアライゼーションは単なるデータ形式の変換であり、暗号化のような機密性保護の効果はない。
- イ)正解。デシリアライゼーションで信頼できない(攻撃者が細工可能な)データを復元すると、オブジェクトの生成過程でコンストラクタやマジックメソッドが呼び出され、任意コード実行(RCE)に至る場合がある。これはOWASP Top 10でも重要な脆弱性カテゴリとして扱われる。
- ウ)不正解。JSONにXXEのような外部実体参照機構はないが、JSONインジェクションや型混同(Type Confusion)、プロトタイプ汚染など別種の脆弱性が存在する。
- エ)不正解。データ構造が固定であっても、値の内容や型を検証しなければ不正なオブジェクト注入やロジック改ざんが可能になる。
午前II問題
Javaや.NET、PHP等で発生する「安全でないデシリアライゼーション」を悪用した攻撃に関する記述のうち、最も適切なものはどれか。
ア)攻撃者は、正規のシリアライズ済みオブジェクトを暗号化することで、サーバ側の復号処理を無限ループに陥らせるDoS攻撃を行う。
イ)攻撃者は、アプリケーションが利用しているクラスライブラリ中に存在する複数のクラスを組み合わせ、デシリアライズ時に連鎖的にメソッドが呼び出されるようにした悪意あるオブジェクト(ガジェットチェーン)を含むシリアライズデータを送り込み、任意コード実行を狙う。
ウ)攻撃者は、Webサーバの証明書のシリアル番号を推測することで、中間者攻撃を成立させる。
エ)攻撃者は、デシリアライズ処理そのものを標的にせず、常にネットワーク層でのパケットキャプチャによって認証情報を窃取する。
午前II の解答・解説を見る
正解: イ
解説:
- ア)不正解。暗号化は攻撃の本質ではなく、DoSに焦点を当てた説明も不正確である。
- イ)正解。「ガジェットチェーン(Gadget Chain)」は、アプリケーションが依存するライブラリ内に存在する既存クラスの
readObjectや__wakeup、__destruct等のマジックメソッドを連鎖的に悪用し、デシリアライズ処理だけで任意コード実行を実現する典型的な攻撃手法である(例:Javaのysoserial、PHPのPOP chain)。 - ウ)不正解。証明書のシリアル番号推測は本テーマと無関係。
- エ)不正解。デシリアライゼーション攻撃はアプリケーション層の脆弱性であり、パケットキャプチャとは異なる攻撃経路である。
午後問題
D社は自社の受発注システムを刷新し、社内システム間の連携にJSON形式のAPIを、一部のレガシー連携にはJavaのオブジェクトシリアライゼーションを利用している。セキュリティ診断で以下の指摘を受けた。
指摘①:JSON API(/api/orders/import)
- リクエストボディのJSONをそのままバックエンドのDBクエリ組み立てやログ出力に利用しており、JSON文字列中に制御文字や特殊文字を混入させることで、ログ改ざんや後続処理の解釈違いを引き起こせることが確認された。
指摘②:レガシー連携API(/api/legacy/sync)
- クライアントから送信されたBase64エンコード済みのシリアライズオブジェクトを、アプリケーションが型チェックなしに
ObjectInputStream#readObject()で復元していた。診断者は、クラスパス上に存在する商用ライブラリのクラスを利用したガジェットチェーンを作成し、この復元処理だけでサーバ上に任意コマンドを実行できることを実証した。
設問1
指摘①のような攻撃は一般に何と呼ばれるか。また、この攻撃を防ぐための入力・出力それぞれの対策を1つずつ述べよ。
設問1の解答・解説を見る
正解例:
- 攻撃名:JSONインジェクション
- 入力側の対策:受信したJSONをスキーマ(型・必須項目・許容文字種)に照らして厳格に検証(バリデーション)し、想定外の構造や制御文字を含む値を拒否する。
- 出力側の対策:ログや後続処理へ値を渡す際は、JSON専用のシリアライザ(エスケープ処理を自動で行うライブラリ)を用いて再構成し、文字列連結によるJSON組み立てを行わない。
解説: JSONインジェクションは、ユーザ入力をエスケープせずにJSON文字列へ直接連結することで、意図しないキーの追加やログの改ざん、構造破壊を引き起こす攻撃である。対策の本質はSQLインジェクションやXSSと同様、信頼できない入力の構造的検証と出力時の専用ライブラリによる安全な組み立てである。
解説・採点基準(計15点):
| 採点項目 | キーワード | 配点 |
|---|---|---|
| 攻撃名を正しく回答 | JSONインジェクション | 4点 |
| 入力対策にスキーマ/型検証への言及 | スキーマ検証、バリデーション | 5点 |
| 出力対策にシリアライザ/エスケープへの言及 | JSONライブラリ、エスケープ、文字列連結の回避 | 6点(部分点:どちらか一方の要素のみでも3点) |
設問2
指摘②について、(1) この攻撃を成立させている根本原因を40字以内で述べよ。(2) レガシー連携を廃止できない前提で、直ちに実施すべき対策を2つ挙げよ。
設問2の解答・解説を見る
正解例:
(1) 根本原因:信頼できない外部入力のシリアライズデータを、型を制限せずデシリアライズしている点(38字)。
(2) 対策:
- デシリアライズ時に許可するクラスをホワイトリスト(許可リスト)で明示的に制限し、それ以外のクラスの復元を拒否する仕組み(look-ahead deserialization、
ObjectInputFilter等)を導入する。 - 可能であれば
ObjectInputStreamを用いた形式をやめ、JSONなど構造が単純でクラス任意生成を伴わないデータ形式へ移行する。あわせて受信データへのデジタル署名検証を追加し、改ざんされたシリアライズデータを拒否する。
解説: 安全でないデシリアライゼーションの根本原因は「攻撃者が構造を制御可能なデータから、任意のクラスのオブジェクトを生成できてしまう」点にある。Javaでは ObjectInputFilter(JEP 290)によるクラス制限、.NETでは TypeNameHandling の無効化、PHPでは unserialize() の利用を避け json_decode を使う、といった言語ごとの対策が知られる。根本解決が難しい場合は署名検証や許可リスト方式による緩和策を組み合わせる。
解説・採点基準(計15点):
| 採点項目 | キーワード | 配点 |
|---|---|---|
| (1) 根本原因に「信頼できない入力」「型/クラスを制限しない」の要素 | 信頼できない入力、任意クラス生成 | 5点 |
| (2) ホワイトリスト/許可リストによるクラス制限 | ホワイトリスト、ObjectInputFilter | 5点 |
| (2) 形式変更・署名検証等の追加対策 | 署名検証、JSON移行 | 5点(部分点:具体策が1つのみでも3点) |
重要キーワード
| 用語 | 説明 |
|---|---|
| デシリアライゼーション | シリアライズされたデータ(文字列・バイト列)から元のオブジェクトを復元する処理 |
| ガジェットチェーン | アプリケーションが依存するライブラリ内の既存クラスを連鎖的に悪用し、デシリアライズだけで任意コード実行を実現する手法 |
| JSONインジェクション | JSON文字列をエスケープせず連結することで構造やログを改ざんする攻撃 |
| ObjectInputFilter | Javaでデシリアライズ時に許可するクラスを制限する仕組み(JEP 290) |
| 許可リスト(ホワイトリスト) | 復元を許可するクラス・型を明示的に列挙し、それ以外を拒否する方式 |
| クロスサイトスクリプティング(XSS) | 出力時の未エスケープが原因となる点でデシリアライゼーション脆弱性と対策思想が共通する攻撃 |
まとめ
- 午前I視点: シリアライゼーション/デシリアライゼーションの定義と、信頼できない入力を復元する危険性を正確に理解する
- 午前II視点: ガジェットチェーンによるRCEの成立過程(既存クラスのマジックメソッド連鎖)を言語(Java/PHP/.NET)ごとの特徴とあわせて押さえる
- 午後視点: JSONインジェクションは入力検証と出力時の専用シリアライザ利用、デシリアライゼーション脆弱性はクラスの許可リスト化や形式移行・署名検証といった多層的対策を具体的に説明できるようにする