検索

185.5. Jackson ObjectMapper

download PDF

185.5.1. オブジェクトマッピングとは

Jackson は、com.fasterxml.jackson.databind.ObjectMapper クラスを使用して、Java オブジェクトをシリアライズするメカニズムを提供します。たとえば、次のように ObjectMapper を使用して MyClass Java オブジェクトをシリアライズできます。

ObjectMapper objectMapper = new ObjectMapper();
MyClass myobject = new MyClass("foo", "bar");
objectMapper.writeValue(new File("myobject.json"), myobject);

オブジェクト myobject は JSON 形式にシリアル化され、ファイル myobject.json に書き込まれます (Jackson は XML および YAML 形式への変換もサポートしています)。

ファイル myobject.json の JSON コンテンツをデシリアライズするには、次のように ObjectMapper を呼び出します。

ObjectMapper objectMapper = new ObjectMapper();
MyClass myobject = objectMapper.readValue(new File("myobject.json"), MyClass.class);

受信者は事前にクラスの型を知っている必要があり、型 MyClass.classreadValue () の 2 番目の引数として指定する必要があることに注意してください。

185.5.2. ポリモーフィックオブジェクトマッピングとは

場合によっては、シリアル化されたオブジェクトの受信者がオブジェクトの型を事前に知ることができないことがあります。たとえば、これは多相オブジェクト配列の場合に当てはまります。抽象型 Shape とそのサブタイプ TriangleSquare (など) について考えてみましょう。

package com.example;
...
public abstract class Shape {
}

public class Triangle extends Shape {
  ...
}

public class Square extends Shape {
  ...
}

public class ListOfShape {
  public List<Shape> shapes;
  ...
}

次のように、形状の配列リスト (ListOfShape) をインスタンス化してシリアル化できます。

ObjectMapper objectMapper = new ObjectMapper();

ListOfShape shapeList = new ListOfShape();
shapeList.shapes = new ArrayList<Shape>();
shapeList.shapes.add(new Triangle());
shapeList.shapes.add(new Square());

String serialized = objectMapper.writeValueAsString(shapeList);

しかし、今は受信側に問題があります。この型を readValue() の 2 番目の引数として指定することで、受信側に ListOfShape オブジェクトを期待するように指示できます。

MyClass myobject = objectMapper.readValue(serialized, ListOfShape.class);
ObjectMapper objectMapper = new ObjectMapper();

ただし、リストの最初の要素が Triangle で 2 番目の要素が Square であることを受信者が知る方法はありません。この問題を回避するには、次のセクションで説明するように、ポリモーフィックオブジェクトマッピング を有効にする必要があります。

185.5.3. ポリモーフィックオブジェクトマッピングを有効にする方法

ポリモーフィックオブジェクトマッピングは、配列内のオブジェクトの型を識別する追加のメタデータをシリアル化された配列に提供することによって、抽象クラスの配列をシリアル化および逆シリアル化できるようにするメカニズムです。

重要

ポリモーフィックオブジェクトマッピングには固有のセキュリティーリスクがあります。このメカニズムでは、インスタンス化するクラスを 送信者 が選択できるため、送信者による攻撃の基礎となる可能性があります。Red Hat の FasterXML Jackson ライブラリーのディストリビューションは、この脅威に対する追加レベルの保護を提供するホワイトリストメカニズムを特徴としています。この追加の保護レイヤーを取得するには、Red Hat の jackson-databind ライブラリーのディストリビューション (Fuse バージョン 7.7 以降で提供) を使用していることを確認する必要があります。詳細は、「ポリモーフィックデシリアライゼーションによるセキュリティーリスク」 を参照してください。

受信者が配列内のオブジェクトを逆シリアル化できるようにするには、シリアル化されたデータに型メタデータを提供する必要があります。デフォルトでは、Jackson はシリアル化されたオブジェクトのタイプメタデータをエンコードしないため、この機能を有効にするには追加のコードを記述する必要があります。

ポリモーフィックオブジェクトマッピングを有効にするには、次の手順を実行します (例として ListOfShape を使用)。

  1. リストの要素となるクラス (Shape のサブクラス) ごとに、次のように @JsonTypeInfo でクラスにアノテーションを付けます。

    @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY)
    public class Triangle extends Shape {
      ...
    }
  2. Triangle クラスを JSON 形式にシリアル化すると、次の形式になります。

    {"@class":"com.example.Triangle", "property1":"value1", "property2":"value2", ...}
  3. TriangleSquare、およびその他の形状クラスを逆シリアル化ホワイトリストに追加して、これらのクラスの逆シリアル化を許可するようにレシーバーを設定する必要があります。ホワイトリストを設定するには、jackson.deserialization.whitelist.packages システムプロパティーを、クラスおよびパッケージのコンマ区切りリストに設定します。たとえば、Triangle クラスと Square クラスのデシリアライズを許可するには、システムプロパティーを以下のように設定します。

    -Djackson.deserialization.whitelist.packages=com.example.Triangle,com.example.Square

    または、システムプロパティーを設定して、com.example パッケージ全体を許可することもできます。

    -Djackson.deserialization.whitelist.packages=com.example
    注記

    このホワイトリストメカニズムは、Red Hat の jackson-databind ライブラリーのディストリビューションでのみ使用できます。標準の jackson-databind ライブラリーは代わりにブラックリストメカニズムを使用します。このメカニズムは、潜在的に危険な新しいガジェットクラスが発見されるたびに更新する必要があります。

185.5.4. ポリモーフィックデシリアライゼーションのデフォルトマッピング

特定の Java クラス com.example.MyClass がホワイトリストに登録されていない場合でも、クラスのインスタンスをシリアライズすることは可能ですが、受信側では、インスタンスは汎用のデフォルトマッピングを使用してデシリアライズされます。

Jackson でポリモーフィックオブジェクトマッピングが有効になっている場合、オブジェクトをエンコードする別の方法がいくつかあります。

  • @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY) の場合:

    {"@class":"com.example.MyClass", "property1":"value1", "property2":"value2", ...}

    この場合、インスタンスはプロパティーを持つ Object に逆シリアル化されます。

  • @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.WRAPPER_ARRAY) の場合:

    ["com.example.MyClass", {"property1":"value1", "property2":"value2", ...}]

    この場合、インスタンスは 2 つのフィールドを含む JSON 配列に逆シリアル化されます。

    • 値が com.example.MyClassString
    • 2 つ (またはそれ以上) のプロパティーを持つ Object
  • @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.WRAPPER_OBJECT) の場合:

    {"com.example.MyClass":{"property1":"value1", "property2":"value2", ...}}

    この場合、インスタンスは、1 つのフィールド com.example.MyClass と、2 つ (またはそれ以上) のプロパティーを持つ Object としての値を持つ JSON マップに逆シリアル化されます。

185.5.5. ポリモーフィックデシリアライゼーションによるセキュリティーリスク

FasterXML jackson-databind ライブラリーを使用し、JSON コンテンツをデシリアライズして Java オブジェクトをインスタンス化するアプリケーションは、潜在的に リモートコード実行 攻撃に脆弱です。しかし、脆弱性は自動的に発生せず、適切な軽減策を講じれば回避することができます。

最低でも以下の前提条件をすべて満たさなければ攻撃を実行することはできません。

  1. jackson-databind の JSON コンテンツのデシリアライズに対し、ポリモーフィックな型の処理を有効にする必要があります。Jackson JSON でポリモーフィックな型の処理を有効にする方法は 2 つあります。

    1. @JsonTypeInfo および @JsonSubTypes アノテーションの組み合わせを使用します。
    2. ObjectMapper.enableDefaultTyping() メソッドを呼び出します。この方法はポリモーフィックな型をグローバルで有効にするため、危険です。
  2. Java クラスパスに 1 つ以上の ガジェットクラス があります。ガジェットクラスは、機密性の高い (潜在的に悪用可能な) 操作を、constructor または setter メソッド (デシリアライズ中に呼び出しできるメソッド) の実行による副次的な影響として定義します。
  3. Java クラスパス内の 1 つ以上のガジェットクラスが、現在のバージョンの jackson-databind によってまだブラックリストに登録されていません。jackson-databind ライブラリーの標準ディストリビューションを使用している場合、Jackson JSON ライブラリーによって維持されるガジェットのブラックリストは、リモートコード実行の脆弱性に対する最後の防衛線です。
  4. (jackson-databind ライブラリーの Red Hat ディストリビューションのみ) (jackson.deserialization.whitelist.packages システムプロパティーを設定することにより) レシーバーの逆シリアル化ホワイトリストにガジェットクラスの 1 つを明示的に追加しました。これを行う可能性は低いため、ホワイトリストメカニズムはデフォルトですべてのガジェットクラスに対して効果的な保護を提供します。
Red Hat logoGithubRedditYoutubeTwitter

詳細情報

試用、購入および販売

コミュニティー

Red Hat ドキュメントについて

Red Hat をお使いのお客様が、信頼できるコンテンツが含まれている製品やサービスを活用することで、イノベーションを行い、目標を達成できるようにします。

多様性を受け入れるオープンソースの強化

Red Hat では、コード、ドキュメント、Web プロパティーにおける配慮に欠ける用語の置き換えに取り組んでいます。このような変更は、段階的に実施される予定です。詳細情報: Red Hat ブログ.

会社概要

Red Hat は、企業がコアとなるデータセンターからネットワークエッジに至るまで、各種プラットフォームや環境全体で作業を簡素化できるように、強化されたソリューションを提供しています。

© 2024 Red Hat, Inc.