FlawOpen

flawopen.com/안전하지 않은 역직렬화/TypeNameHandling

Newtonsoft.Json TypeNameHandling: 신뢰할 수 없는 JSON의 안전한 설정

CWE-502: Deserialization of Untrusted Data참고 페이지
요약

일반 JSON은 데이터를 표현하고 .NET 형식은 코드가 선택합니다. TypeNameHandling을 켜면 $type이 역직렬화 중 형식 확인에 영향을 줄 수 있습니다. 신뢰할 수 없는 입력에는 None을 사용하세요. 다형성이 필요하면 엄격한 ISerializationBinder로 검증하거나 코드에 선언된 제한된 판별자 매핑을 사용하세요.

취약
var settings = new JsonSerializerSettings {
    // Any non-None mode needs a strict binder
    TypeNameHandling = TypeNameHandling.Auto,
    // No binder: input $type can resolve CLR types
};

var value = JsonConvert.DeserializeObject<Base>(
    untrustedJson, settings);
수정됨
// Safest default for untrusted JSON
var settings = new JsonSerializerSettings {
    TypeNameHandling = TypeNameHandling.None,
};

// For polymorphism, dispatch over a closed set:
var token = JObject.Parse(json);
Base value = token["kind"]?.ToString() switch {
    "circle" => token.ToObject<Circle>(),
    "square" => token.ToObject<Square>(),
    _ => throw new JsonException("Unknown kind"),
};

// System.Text.Json also supports opt-in derived
// types through [JsonDerivedType] (.NET 7+).

개발자가 TypeNameHandling을 켜는 이유

흔한 이유는 다형성 데이터입니다. Shape 컬렉션을 Circle 또는 Square로 보존해야 할 수 있습니다. Json.NET은 $type으로 형식 이름을 읽고 씁니다. 신뢰할 수 없는 입력의 메타데이터는 런타임 형식에 영향을 줄 수 있으며 위험은 허용 형식과 동작에 달려 있습니다. 위험한 체인에는 부작용이 있는 도달 가능한 형식이 필요하며 JSON만으로는 충분하지 않습니다.

신뢰 경계는 반대로 설계합니다. 검증된 판별자 값의 제한된 집합에서 코드가 하위 형식을 선택합니다. System.Text.Json은 [JsonDerivedType] 같은 특성으로 명시적 다형성을 지원하지만 JSON의 임의 CLR 이름을 활성화하지 않습니다. 관련 경계는 BinaryFormatter 안내를 참조하세요.

사용자 지정 ISerializationBinder면 충분한가요?

외부 데이터에서 TypeNameHandling이 None이 아니면 엄격한 ISerializationBinder가 필요합니다. 앱 소유의 정확한 이름 몇 개만 허용하고 나머지는 거부하세요. 허용 형식, converter, constructor, setter, callback을 검토하세요. binder는 형식 확인을 제한할 뿐 임의 형식을 안전하게 만들지는 않습니다. 가능하면 None과 명시적 분기를 사용하세요.

자주 묻는 질문

TypeNameHandling.Auto는 신뢰할 수 없는 JSON에 안전한가요?

그 자체로는 안전하지 않습니다. Auto는 역직렬화 중 $type을 읽을 수 있습니다. TypeNameHandling.None 또는 검토된 형식만 허용하는 엄격한 binder를 사용하세요.

System.Text.Json은 안전한 다형성을 지원하나요?

예. .NET 7 이상의 [JsonDerivedType]처럼 판별자와 파생 형식을 코드에 선언하는 명시 방식입니다. 허용 형식은 앱 코드가 제한합니다.

.NET 애플리케이션을 어떻게 감사하나요?

전체 솔루션에서 TypeNameHandling, SerializationBinder, JsonConvert.DeserializeObject를 검색하세요. ASP.NET 시작 및 공유 설정을 확인하고 외부 JSON 경로를 추적해 None이 아닌 각 경로에 엄격한 binder가 있는지 확인하세요.

참고자료

함께 보기 안전하지 않은 역직렬화: 위험과 대응 | flawopen.com PHP unserialize()와 신뢰할 수 없는 입력 Python pickle.load(): 신뢰할 수 없는 데이터 위험 Ruby YAML.load는 안전한가요? Psych 버전과 safe_load .NET BinaryFormatter: 위험과 마이그레이션 Java ObjectInputStream 보안과 안전한 역직렬화