Nitriteに任意コード実行の脆弱性、修正版4.4.1あり
Javaアプリに組み込むNoSQLデータベースNitriteに、細工したデータベースファイルを開くと任意のコードを実行される恐れのある脆弱性が見つかりました。外部からファイルを受け取るアプリを持つ組織は、4.4.1以降への更新を急いでください。
急ぎ度: 早めに
CVSS v3は9.8で修正版の4.4.1が出ており、外部から受け取ったファイルを開く機能があるアプリは最優先、ほかのアプリも早めの更新が望ましい状況です。
関係があるか
Nitriteを組み込んだJavaアプリを自社で開発・運用している組織が対象です。ユーザーがデータベースファイルをインポートしたり、バックアップから復元したりできるアプリは、とくに影響を受けやすくなります。
| 製品 | 影響を受ける版 | 修正版 |
|---|---|---|
| Nitrite(nitrite-java。MavenではCVEの記録上 nitrite-java、勧告上 org.dizitart:nitrite-mvstore-adapter) | 4.4.1より前(勧告の記載は4.4.0以前) | 4.4.1(2026年7月2日にリリース) |
確かめ方
- 1pom.xmlやbuild.gradleで、org.dizitartのNitrite関連の依存が4.4.1より前の版になっていないかを確認します。他のライブラリ経由で入る推移的な依存も、依存ツリーで見ておきます。
- 2アプリがファイルベースのデータベースを開いているかを確認します。ファイルベースのストアは、開くたびに旧v1形式かどうかの検査が走ります。
- 3利用者や外部システムから受け取ったデータベースファイルを開く経路(インポート、バックアップの復元、ファイル連携など)がないかを洗い出します。
- 4アプリのクラスパスに、commons-collectionsなど、シリアライズされたオブジェクトの悪用に使われやすいライブラリが入っていないかを確認します。
何が起きたか
Nitriteの4.4.1より前の版には、細工されたデータベースファイルを開いたとき、アプリ内のクラスを意図しない形で動かされる脆弱性があります。条件がそろうと、任意のコード実行に至ります。
Nitriteはファイルを開くとき、旧v1形式のストアかどうかを自動で調べます。旧形式と判定されるか、開く途中で互換性エラーが出ると、自動移行の処理に入ります。この処理は、保存された値をNitriteDataType.deserialize(byte[])でJavaのオブジェクトに戻しますが、中身はObjectInputStream.readObject()にそのまま渡されます。
独自のサブクラスはreadClassDescriptor()だけを上書きし、旧クラス名7件を現行のクラスに置き換えています。復元してよいクラスを絞る許可リスト、拒否リスト、ObjectInputFilter(JEP 290)はありません。そのため、アプリのクラスパスにあるSerializableなクラスは、すべて生成の対象になります。CWEは502(信頼できないデータのデシリアライズ)で、CVSS v3は9.8です。
4.4.1では、旧形式用の復元処理にJEP 290の許可リスト方式のフィルターが入りました。許可されるのはNitrite自身の型とJDK標準の型だけで、それ以外のクラスは、readObjectやreadResolveが動く前に拒否されます。
攻撃の流れ
-
1
細工ファイルを用意
攻撃者が、悪意あるオブジェクトを埋め込んだデータベースファイルを作ります。
-
2
アプリに読み込ませる
インポートや復元などの機能を通じて、Nitriteがそのファイルを開きます。
-
3
旧形式の移行が始まる
旧v1形式と判定されるか互換性エラーが出ると、保存値の復元がクラスの制限なしで行われます。
-
4
クラスが生成される
クラスパス上のクラスが動き、悪用に使える部品がそろっていると、コード実行に至ります。
どう悪用されるか
CVSS v3のベクトルは、ネットワーク経由で、認証も利用者の操作も要らない想定です。ただ、実際の入り口は、細工されたデータベースファイルがアプリに開かれることです。リリースノートも、信頼できない出所のファイルを開く機能(インポートやバックアップの復元など)を持つアプリに更新を求めています。
コード実行まで進むには、アプリのクラスパスに、悪用に使えるクラス(commons-collectionsなどに含まれるもの)が存在することが前提です。勧告は、これを遠隔コード実行の前提条件として挙げています。部品がなくても任意のクラスを生成されること自体は変わらないため、部品がないから安全とは言い切れません。
悪用が成立すると、アプリを実行しているアカウントの権限でコードが動きます。CVSSの評価は、機密性・完全性・可用性のすべてが高い影響です。
今すぐやること
-
1
Nitriteを使っているアプリを洗い出す
ビルドファイルと依存ツリーで、Nitrite関連のライブラリと版を確認します。自社開発のアプリだけでなく、受託で納品したものや、Nitriteを内部で使うOSSも対象です。
mvn dependency:tree -Dincludes=org.dizitart -
2
外部ファイルを開くアプリから修正版に更新する
インポートや復元の機能があるアプリを最優先にして、Nitriteを4.4.1以降に更新し、再ビルドして配備します。4.4.0を使っている場合は、4.4.0で入った索引の不具合(ConcurrentModificationExceptionや、誤った一意制約違反)も4.4.1で直っています。
-
3
ほかのアプリも更新計画に載せる
外部のファイルを開かないアプリも、同じ更新を早めに予定に入れます。クラスパスに悪用されやすいライブラリがあるかどうかを併せて見ておくと、優先順位をつけやすくなります。
mvn dependency:tree -Dincludes=commons-collections -
4
過去の読み込みを振り返る
修正版は2026年7月から出ています。更新前の版で、出所の怪しいデータベースファイルを読み込んだ履歴がないか、あればその前後にアプリや実行サーバーで不審な動作がなかったかを調べます。
すぐ更新できないとき
更新までのつなぎとして、信頼できない出所のデータベースファイルをアプリに読み込ませない運用にします。インポートや復元の機能を一時的に止める、読み込めるファイルの出所を社内の管理されたものだけに限る、といった方法です。公式に示された回避策ではなく、修正版に更新するまでの暫定措置です。
背景
Nitriteは、サーバーを立てずにJavaアプリへ組み込んで使うNoSQLのドキュメントストアです。データはアプリのそばの1つのファイルに保存され、デスクトップアプリや小さな業務ツールが、設定や業務データの保管に使う例が多いタイプです。今回の問題は、通常の保存形式ではなく、旧v1形式のファイルを読む移行用の経路にあります。ただ、ファイルベースのストアを開くたびに旧形式かどうかの検査が走るため、新形式のファイルを使っているアプリも、この経路の手前を通ります。
Javaの標準のシリアライズを制限なしに復元する処理は、クラスパス上のライブラリの部品と組み合わせてコード実行に使われる型の脆弱性として知られています。勧告もcommons-collectionsを例に挙げています。Javaは復元できるクラスを絞るフィルター機構としてJEP 290を用意しており、4.4.1はこれを旧形式の復元処理に導入しました。
よくある質問
Q.CVEの記録と勧告で、パッケージ名が違うのはなぜですか。
Q.クラスパスに悪用されやすいライブラリがなければ、更新しなくてよいですか。
まだ分かっていないこと
- 影響する版の下限は示されておらず、4.4.1より前、または4.4.0以前という書き方にとどまっています。
この記事は、取得元の公開情報をもとに、人が監修しながらAIを活用して執筆しています。執筆と監修は佐々木 航が担い、公開したあとも人が内容を確認しています。誤りに気づいたときは直し、記事の末尾に訂正の行を残します。対応を決める前に、下の原文と参照先も確認してください。
原文の説明 取得元が公開している説明をそのまま載せています (多くは英語)。
NOsql Object (NO2 a.k.a Nitrite) database is an open source nosql embedded document store. Prior to version 4.4.1, when Nitrite opens a database file, MVStoreUtils.openOrCreate() automatically checks for a legacy v1-format store and, on detecting one (or hitting a compatibility error while opening), triggers an automatic migration path. This path deserializes stored values using NitriteDataType.deserialize(byte[]), which passes the raw bytes directly to java.io.ObjectInputStream.readObject() via a custom NitriteObjectInputStream subclass. That subclass overrides only readClassDescriptor() — solely to remap a handful of known legacy class names to their current equivalents — and implements no class allowlist, blocklist, or ObjectInputFilter (JEP 290). Any Serializable class reachable on the embedding application's classpath can therefore be instantiated via readObject(), with readObject()/readExternal()/readResolve() callbacks invoked unconditionally. If a suitable gadget class (e.g. from commons-collections or similar) happens to be present on the classpath, this is a precondition for remote code execution. This issue has been patched in version 4.4.1.
出典: CVE.org (CVE Program・cvelistV5) NVD