185.5. Jackson ObjectMapper
185.5.1. object mapping이란 무엇입니까?
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);
수신자는 클래스의 유형을 미리 알고 있어야 하며, readValue()
의 두 번째 인수로 MyClass.class
유형을 지정해야 합니다.
185.5.2. polymorphic 개체 매핑이란 무엇입니까?
직렬화된 오브젝트를 수신하여 오브젝트의 유형을 미리 알 수 없는 경우도 있습니다. 예를 들어, 이는 다형성 오브젝트 어레이의 경우에 적용됩니다. 추상 유형, Shape
및 해당 하위 유형, Triangle
, Cryostat(
및 등)를 고려하십시오.
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()
의 두 번째 인수로 지정하여 수신자에게 ListOfShape
오브젝트를 예상하도록 지시할 수 있습니다.
MyClass myobject = objectMapper.readValue(serialized, ListOfShape.class); ObjectMapper objectMapper = new ObjectMapper();
그러나 수신자는 목록의 첫 번째 요소가 트라이글이고 두 번째 요소는 트라이 클
임을 알 수 없습니다
. 이 문제를 해결하려면 다음 섹션에 설명된 대로 다형성 오브젝트 매핑 을 활성화해야 합니다.
185.5.3. 다형성 오브젝트 매핑 활성화 방법
다형성 개체 매핑은 배열의 개체 유형을 식별하는 직렬화 배열에 추가 메타데이터를 제공하여 추상 클래스의 배열을 직렬화 및 역직렬화할 수 있는 메커니즘입니다. polymorphic object mapping is a mechanism that makes it possible to serialize and deserialize arrays of abstract classes, by providing additional metadata in the serialized array, which identifies the type of the objects in the array.
다형성 개체 매핑은 메커니즘을 통해 발신자 가 인스턴스화할 클래스를 선택할 수 있으므로 고유 보안 위험을 나타내며, 이는 발신자의 공격을 기반으로 구성할 수 있습니다. Red Hat은 Faster XML Jackson 라이브러리 배포를 통해 이러한 위협에 대한 추가 수준의 보호를 제공하는 화이트리스트 메커니즘을 제공합니다. 추가 보호 계층을 얻으려면 Red Hat의 jackson-databind 라이브러리 배포( Fuse 버전 7.7 이상에서 제공)를 사용하고 있는지 확인해야 합니다. 자세한 내용은 185.5.5절. “다형성 직렬화(polymorphic deserialization)의 보안 위험” 에서 참조하십시오.
수신자가 배열의 개체를 역직렬화할 수 있도록 하려면 직렬화된 데이터에 형식 메타데이터를 제공해야 합니다. 기본적으로 jackson은 직렬화된 오브젝트에 대한 유형 메타데이터를 인코딩하지 않으므로 이 기능을 사용하려면 추가 코드를 작성해야 합니다.
다형성 오브젝트 매핑을 활성화하려면 다음 단계를 수행합니다(예로 ListOfShape
사용).
목록의 요소가 될 수 있는 각 클래스의 경우 다음과 같이
@JsonTypeInfo
로 클래스에 주석을 답니다.@JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY) public class Triangle extends Shape { ... }
Triangle
클래스가 JSON 형식으로 직렬화되면 다음과 같은 형식이 있습니다.{"@class":"com.example.Triangle", "property1":"value1", "property2":"value2", ...}
역직렬화 허용 목록에 이러한 클래스를 추가하여
Triangle
, Cryostat 및 기타 모양 클래스를 역직렬화할 수 있도록 수신자를 구성해야 합니다.허용 목록을 구성하려면
jackson.deserialization.whitelist.packages
시스템 속성을 쉼표로 구분된 클래스 및 패키지 목록으로 설정합니다. 예를 들어 트리사각형 클래스의역직렬화
를 허용하려면 다음과 같이 시스템 속성을 설정합니다.-Djackson.deserialization.whitelist.packages=com.example.Triangle,com.example.Square
또는 전체
com.example
패키지를 허용하도록 시스템 속성을 설정할 수 있습니다.-Djackson.deserialization.whitelist.packages=com.example
참고이 화이트리스트 메커니즘은 jackson-databind 라이브러리의 Red Hat 배포에서만 사용할 수 있습니다. 표준 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", ...}
이 경우 인스턴스는 속성이 있는 개체로 역직렬화됩니다.In this case, the instance will be deserialized to an
Object
with properties.@JsonTypeInfo(use=JsonTypeInfo.Id.CLASS)를 사용하여 include=JsonTypeInfo.As.WRAPPER_ARRAY)
:["com.example.MyClass", {"property1":"value1", "property2":"value2", ...}]
이 경우 인스턴스는 두 개의 필드를 포함하는 JSON 배열로 역직렬화됩니다.
-
값이
com.example.MyClass
인문자열
-
두 개 이상의 속성이 있는
개체
-
값이
With
@JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.WRAPPER_OBJECT)
:{"com.example.MyClass":{"property1":"value1", "property2":"value2", ...}}
이 경우 인스턴스는 단일 필드인
com.example.MyClass
및 값이 두 개(또는 그 이상)가 있는Object
인 JSON 맵에 역직렬화됩니다.
185.5.5. 다형성 직렬화(polymorphic deserialization)의 보안 위험
JSON 콘텐츠를 역직렬화하여 Java 개체를 인스턴스화하기 위해 Faster XML jackson-databind
라이브러리를 사용하는 애플리케이션은 원격 코드 실행 공격에 취약해질 수 있습니다. 그러나 이 취약점은 자동으로 제공되지 않으며 적절한 완화 조치를 취하는 경우 방지할 수 있습니다.
최소한 공격이 가능하려면 먼저 다음 사전 요구 사항을 충족해야 합니다.
jackson-databind
에서 JSON 콘텐츠를 역직렬화하기 위해 다형성 유형 처리를 활성화했습니다. jackson JSON에서 다형성 유형 처리를 활성화하는 두 가지 다른 방법이 있습니다.-
@JsonTypeInfo
및@JsonSubTypes
주석의 조합 사용 -
ObjectMapper.enableDefaultTyping()
메서드를 호출합니다. 이 옵션은 전 세계적으로 다형성 타이핑을 효과적으로 가능하게 하므로 특히 위험합니다.
-
- Java 클래스 경로에는 하나 이상의 가젯 클래스 가 있습니다. 가젯 클래스는 생성자 또는 setter 메서드(직렬화 중에 호출될 수 있는 메서드)를 실행하는 부작용으로 중요한(심각적으로 악용 가능) 작업을 수행하는 모든 클래스로 정의됩니다.
-
Java classpath에서 하나 이상의 가젯 클래스가 아직
jackson-databind
의 현재 버전에 의해 블랙리스트에 추가되지 않았습니다. jackson-databind 라이브러리의 표준 배포를 사용하는 경우 Jackson JSON 라이브러리에서 유지 관리하는 가젯 블랙리스트는 원격 코드 실행 취약점에 대한 방어의 마지막 줄입니다. -
(Red Hat distribution of jackson-databind library only) You explicitly added one of the gadget classes to the deserialization whitelist on the receiver (by setting the
jackson.deserialization.whitelist.packages
system property). 이 작업은 수행하기가 불가능하므로 허용 목록 메커니즘은 기본적으로 모든 가젯 클래스에 대해 효과적인 보호 기능을 제공합니다.