GCSA洞察:Fastjson 1.2.83 “Gadget-Free” 漏洞(0day)深度分析与防御指南

要約
従来のJava逆シリアル化脆弱性防御体制において、業界では「AutoTypeがデフォルトで無効なら安全」、「parseObjectの第二引数(トップレベルのターゲット型)を固定すれば安全」、「ローカルClasspathの逆シリアル化ガジェット依存を排除すれば安全」といった認識の盲点が広く存在していました。しかし、最新の技術的攻防の進化により、これらの楽観的な見方は完全に打ち破られました。
GCSA 全球サイバーセキュリティ連盟は本日、この技術洞察レポートを独占公開します。本レポートは、Fastjson 1.2.83がデフォルトのAutoType=false状態においても、従来のガジェット依存を必要としないリモートコード実行(RCE)を引き起こす可能性がある根本原因を詳細に分析しています。現在、この悪用手法はJDK 8 / 17 / 21 / 25およびSpring Boot Loader隔離環境において、エンドツーエンドでの再現に成功しています。本脆弱性は従来の「ブラックリスト回避後のローカルガジェット探索」ではなく、Fastjson自身のクラスメタデータ探査ロジックを、リモートの悪意あるクラスの取得と承認経路として直接転用するものです。
以下が本文です。
- 発表機関:GCSA 全球サイバーセキュリティ連盟
- レポート種類:独占技術洞察 / 脆弱性詳細分析レポート
- レポート日付:2026-07-21
- レポートステータス:ソースコード監査および隔離環境での再現完了
- 脆弱性番号:内部研究番号
FJ-GETRESOURCE-RCE(公開CVEには未対応)
Fastjson 1.2.83は、デフォルトのAutoType=false状態でも、従来のガジェットを必要としないリモートコード実行を引き起こす可能性があり、JDK 8/17/21/25 + Spring Boot Loader隔離環境で再現済みです。SafeModeを直ちに有効にし、Fastjson 2.xへ移行することを推奨します。
1. エグゼクティブサマリー
Fastjson 1.2.83のParserConfig.checkAutoTypeは、ユーザーが制御可能な@type値をクラスリソース名に変換し、現在のClassLoaderのgetResourceAsStreamに渡します。
String resource = typeName.replace('.', '/') + ".class";
is = ParserConfig.class.getClassLoader().getResourceAsStream(resource);
絶対URLリソース名を解決可能なfat-jar ClassLoader環境において、攻撃者はドット置換を利用してhttp:、jar:http:、jar:file:の各URLを構築し、攻撃サーバーから@JSONTypeアノテーションを持つ悪意あるクラスをダウンロードします。Fastjsonはこのアノテーションを検出するとloadClassを呼び出し、危険な基底クラスのチェックやターゲット型との互換性チェックよりも前に、そのクラスを直接返します。クラスがインスタンス化・初期化される際に任意のコードが実行される可能性があります。
この悪用手法は、ターゲットのクラスパス上に既存の従来型逆シリアル化ガジェットを必要とせず、Fastjsonのデフォルト状態であるAutoType=falseでもトリガー可能です。JSON.parseObjectのターゲット型を固定しても実行を阻止できません。SafeModeを有効にすることで、リソースアクセス前に通常の悪用経路を遮断できます。
本レポートでは、同一のJSONペイロードを使用して、隔離されたLinuxコンテナ内で以下の再現を完了しています。
JDKClassLoader 環境 Fastjson 結果 Temurin 8 U492Spring Boot Loader 2.7.181.2.83RCE 成功 Temurin 17.0.19Spring Boot Loader 3.2.01.2.83RCE 成功 Temurin 21.0.11Spring Boot Loader 3.2.01.2.83RCE 成功 Temurin 25.0.3Spring Boot Loader 3.2.01.2.83RCE 成功
2. 脆弱性評価
プロジェクト結論脆弱性タイプ安全でない逆シリアル化 / リモートクラス注入 / リモートコード実行推奨レベル高リスク;検証済みの展開条件を満たす場合は重大として扱う可能性あり攻撃ベクトルネットワークリモート権限要件なしユーザー操作不要機密性への影響高完全性への影響高可用性への影響高悪用の複雑性ClassLoader、アウトバウンド通信可否、オペレーティングシステムのファイル記述子インターフェースに依存
コンポーネントのバージョンに基づいて一律のCVSS 9.8を割り当てることは推奨しません。通常のAppClassLoaderはネガティブコントロールであり、最新JDKにおける完全なチェーンは、2種類の絶対JAR URLを解決できるローダーと/proc/self/fdに依存します。本レポートで示すポジティブな環境を満たすアプリケーションでは、本脆弱性は認証不要のネットワークRCEとして機能します。
3. 影響範囲と前提条件
3.1 確認済み範囲
- ランタイム確認:Fastjson 1.2.83。
- JDK確認:8、17、21、25。
- オペレーティングシステム確認:Linux;macOSでは
/dev/fdを使用してJDK 17/21/25での再現も完了。 - ローダー確認:
- Spring Boot 2.7.18 classic loader + JDK 8; - Spring Boot 3.2.0 loader + JDK 17/21/25。
- API確認:
JSON.parse、およびトップレベル型を固定したJSON.parseObject。
3.2 バージョン範囲の説明
外部の記述における1.2.68–1.2.83は、脆弱性が導入されたバージョン範囲ではなく、既知のテスト範囲としてより適切です。 ソースコードの照合により、決定的なクラスリソース探査コードは1.2.67および1.2.68に既に存在することが示されています。本レポートは1.2.83に対してのみ完全なクロスJDKランタイム検証を完了しており、これにより以前のバージョン全てが完全に同一のエンドツーエンドの悪用条件を備えると断言することはできません。
3.3 悪用に必要な条件
- 攻撃者はFastjsonに渡すJSONを制御でき、かつ入力内の
@typeが解析されること。 - SafeModeが有効でないこと。
- FastjsonをロードするClassLoaderが、構築後の絶対リソース名をURLとして解決できること。
- 被害プロセスが攻撃側のHTTPサービスに接続可能であること。
- 最新Linuxチェーンでは
/proc/self/fdが読み取り可能であり、かつローダーが
jar:file:/proc/self/fd/N!..."を解決できること。
- JDKが通常のリモートJAR一時キャッシュを作成できること。これは通常、JVMの一時ディレクトリが書き込み可能であることを意味します。
攻撃者に不要なもの:
- ターゲットのクラスパスへのファイル書き込み;
- ターゲットのクラスパスへの
TemplatesImpl、JNDI、C3P0、Commons Collections等のガジェットのプリインストール; - Fastjson AutoTypeの有効化;
JSON.parseObjectの第二引数の制御。
4. 根本原因分析
4.1 ユーザー指定の型名がリソースURLとして扱われる
ソースコード位置:
src/main/java/com/alibaba/fastjson/parser/ParserConfig.java:1479-1498
核心コード:
String resource = typeName.replace('.', '/') + ".class";
if (defaultClassLoader != null) {
is = defaultClassLoader.getResourceAsStream(resource);
} else {
is = ParserConfig.class.getClassLoader().getResourceAsStream(resource);
}
このロジックはresourceが単なる通常のクラスパスパスであると想定していますが、そのプロトコル、絶対パスセマンティクス、またはソースを制限していません。特定のfat-jarローダーの場合、以下の入力は置換後に絶対URLになります。
入力型名: http:..localhost:18081.a リソース名: http://localhost:18081/a.class
したがって、getResourceAsStreamはローカルメタデータのクエリから、攻撃者が制御可能なネットワークリソースのロードへと逸脱します。
4.2 リモートクラスの@JSONTypeが承認根拠として扱われる
Fastjsonは独自のASMClassReaderを使用してリソース内容を解析します。
ClassReader classReader = new ClassReader(is, true);
TypeCollector visitor = new TypeCollector("<clinit>", new Class[0]);
classReader.accept(visitor);
jsonType = visitor.hasJsonType();
攻撃者は、リモートクラスにFastjsonの@JSONTypeアノテーションを持たせるだけで、jsonTypeをtrueに設定できます。ここでチェックされるのは攻撃者が提供するバイトコードであり、信頼できるクラスパスから既にロードされたクラスではありません。
4.3 jsonTypeが実際のクラスロードをトリガーする
ソースコード位置:
ParserConfig.java:1500-1503
TypeUtils.java:1759-1792
if (autoTypeSupport || jsonType || expectClassFlag) {
boolean cacheClass = autoTypeSupport || jsonType;
clazz = TypeUtils.loadClass(typeName, defaultClassLoader, cacheClass);
}
TypeUtils.loadClassは、明示的ローダー、スレッドコンテキストローダー、Class.forNameの順に試行します。 ポジティブな環境では、スレッドコンテキストローダーが再び同じ絶対リソース名を解決し、クラスをダウンロードしてdefineClassを実行します。
4.4 @JSONTypeによる早期リターンが後続のセキュリティチェックをバイパスする
ソースコード位置:
ParserConfig.java:1505-1528
if (clazz != null) {
if (jsonType) {
return clazz;
} // These checks are performed after the jsonType is returned.
if (ClassLoader.class.isAssignableFrom(clazz)
|| DataSource.class.isAssignableFrom(clazz)
|| RowSet.class.isAssignableFrom(clazz)) {
throw new JSONException(...);
} if (expectClass != null) {
// assignability the check is also done later.
}
}
したがって、リモートクラスが一度@JSONTypeを保持すると:
- 危険な基底クラスのチェックは実行されません;
expectClass.isAssignableFrom(clazz)は実行されません;- 固定データバインディング型は、クラスの初期化前に実行を阻止できません。
4.5 Exception/Errorサフィックスによる失敗ソフトチャネルの形成
ソースコード位置:
ParserConfig.java:1537-1542
if (!autoTypeSupport) {
if (typeName.endsWith("Exception") || typeName.endsWith("Error")) {
return null;
}
throw new JSONException("autoType is not support. " + typeName);
}
最新JDKの第一段階では、不正な内部クラス名によりロードが失敗します。型名をExceptionで終わらせることで、FastjsonはJSON全体を終了させず、nullを返すため、パーサーは配列内のFD列挙要素を処理し続けることができます。この分岐は、単一ペイロードによるクロスステージ実行の鍵となります。
4.6 SafeModeの位置
SafeModeチェックはリソースアクセスより前にあります。
ParserConfig.java:1325-1330
したがって、デフォルトのパスではSafeModeがネットワークリクエストを阻止できます。ただし、AutoTypeCheckHandlerはSafeModeより前に位置します(ParserConfig.java:1316-1323)。アプリケーションが型を直接


