C#(.NET)中Newtonsoft.Json不安全反序列化相关问题咨询
关于.NET Web API反序列化安全与类型控制的解决方案
问题1:设置TypeNameHandling.None是否不足以避免不安全反序列化?
TypeNameHandling.None是防御不安全反序列化的核心措施:它禁止Newtonsoft.Json在序列化/反序列化流程中嵌入或读取类型元数据,从根源上切断了攻击者通过注入恶意类型名称触发危险实例化的路径,能大幅降低风险。- 安全评审的顾虑源于
object类型的契约模糊性:即使关闭类型名称处理,object反序列化的结果仍不确定(可能是JObject、值类型等),评审可能担心后续代码中存在强制类型转换操作,或第三方依赖处理逻辑存在潜在漏洞。简言之,TypeNameHandling.None能解决大部分反序列化风险,但object类型的存在会让契约不明确,留下模糊的风险判定空间。
问题2:是否存在替代Custom ModelBinder的方案,既能严格控制允许的类型,又不会反序列化为JObject?
无需为900+功能单独创建端点,以下几种方案可满足需求:
1. 带显式类型鉴别器的多态序列化(配合类型白名单)
- 定义抽象基类,为每个功能的配置类实现该基类;
- 使用
JsonSubtypes配合固定鉴别字段,将JSON中的标识映射到白名单内的具体类型,避免抽象类无法实例化的问题:
[JsonConverter(typeof(JsonSubtypes), "FunctionType")] [JsonSubtypes.KnownSubType(typeof(DemoContract1), "Demo1")] [JsonSubtypes.KnownSubType(typeof(DemoContract2), "Demo2")] public abstract class BaseSetting { } public class DemoContract1 : BaseSetting { public string SpecificProp1 { get; set; } } public class DemoContract2 : BaseSetting { public int SpecificProp2 { get; set; } }
- 该方案会严格按照白名单反序列化得到强类型实例,不会生成
JObject,同时契约明确了允许的类型范围。
2. 基于功能标识的强类型请求解析
- 定义统一请求契约,包含功能标识字段和泛型配置字段:
public class GodApiRequest<T> where T : BaseSetting { public string FunctionId { get; set; } public T Config { get; set; } }
- 在API端点中,根据
FunctionId从预定义的类型字典(如Dictionary<string, Type>)中获取对应的BaseSetting实现类型,手动将配置JSON反序列化为该类型,全程避免使用object。
3. 自定义JsonConverter实现严格类型控制
- 编写自定义
JsonConverter,在反序列化时读取JSON中的功能标识,仅允许白名单内的类型被实例化,直接返回强类型对象,无需经过JObject转换:
public class StrictSettingConverter : JsonConverter<BaseSetting> { private readonly Dictionary<string, Type> _allowedTypes = new() { { "Demo1", typeof(DemoContract1) }, { "Demo2", typeof(DemoContract2) } }; public override BaseSetting ReadJson(JsonReader reader, Type objectType, BaseSetting existingValue, bool hasExistingValue, JsonSerializer serializer) { var jObj = JObject.Load(reader); var functionType = jObj["FunctionType"]?.ToString(); if (!_allowedTypes.TryGetValue(functionType, out var targetType)) { throw new JsonSerializationException("不允许的配置类型"); } return (BaseSetting)jObj.ToObject(targetType, serializer); } public override void WriteJson(JsonWriter writer, BaseSetting value, JsonSerializer serializer) { serializer.Serialize(writer, value); } }
- 注册该转换器后,框架会自动按规则反序列化为指定的强类型实例。
内容的提问来源于stack exchange,提问作者Paul Nogas
相关产品推荐
相关产品推荐

