flawopen.com/안전하지 않은 역직렬화/TypeNameHandling
Newtonsoft.Json TypeNameHandling: 신뢰할 수 없는 JSON의 안전한 설정
일반 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과 명시적 분기를 사용하세요.
자주 묻는 질문
그 자체로는 안전하지 않습니다. Auto는 역직렬화 중 $type을 읽을 수 있습니다. TypeNameHandling.None 또는 검토된 형식만 허용하는 엄격한 binder를 사용하세요.
예. .NET 7 이상의 [JsonDerivedType]처럼 판별자와 파생 형식을 코드에 선언하는 명시 방식입니다. 허용 형식은 앱 코드가 제한합니다.
전체 솔루션에서 TypeNameHandling, SerializationBinder, JsonConvert.DeserializeObject를 검색하세요. ASP.NET 시작 및 공유 설정을 확인하고 외부 JSON 경로를 추적해 None이 아닌 각 경로에 엄격한 binder가 있는지 확인하세요.