.NET高级代码审计(第二课) Json.Net反序列化漏洞
字数 1810 2025-08-18 11:38:08

.NET高级代码审计:Json.Net反序列化漏洞深度解析

一、Json.Net库概述

Newtonsoft.Json(Json.NET)是一个高性能的.NET JSON操作类库,主要功能包括:

  • 实现.NET对象与JSON之间的转换
  • 提供序列化(SerializeObject)和反序列化(DeserializeObject)方法
  • 支持丰富的自定义序列化配置选项

性能对比:Json.NET在性能上优于微软内置的DataContractJsonSerializer和JavaScriptSerializer

二、Json.Net序列化机制

基本序列化示例

public class TestClass
{
    [JsonIgnore]
    public string Classname { get; set; }  // 被忽略的属性
    
    public string Name { get; set; }
    public int Age { get; set; }
    
    public static void ClassMethod(string file)
    {
        Process.Start(file);
    }
}

// 序列化过程
var testClass = new TestClass { Name = "Ivan1ee", Age = 18 };
string jsonString = JsonConvert.SerializeObject(testClass);

关键点

  • 静态方法不参与序列化过程
  • 使用[JsonIgnore]特性可忽略特定属性

高级序列化配置

var settings = new JsonSerializerSettings
{
    TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Full,
    TypeNameHandling = TypeNameHandling.All
};
string testString = JsonConvert.SerializeObject(testClass, settings);

配置选项

  • TypeNameAssemblyFormatHandling:控制程序集名称格式
  • TypeNameHandling:控制类型名称处理方式

三、Json.Net反序列化漏洞

3.1 反序列化基本用法

var settings = new JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.All
};
var obj = JsonConvert.DeserializeObject(jsonString, settings);

TypeNameHandling枚举值

  • None:默认值,不读取/写入类型名称
  • Objects:仅处理对象
  • Arrays:仅处理数组
  • Auto:自动识别
  • All:处理所有值

3.2 攻击向量分析

攻击向量1:ObjectDataProvider

漏洞原理
当TypeNameHandling设置为非None值时,攻击者可构造恶意JSON实现RCE

PoC构造步骤

  1. 序列化TestClass获取基础JSON结构
  2. 替换关键字段:
    • 修改$type为攻击目标类型
    • 设置MethodName为要执行的方法
    • 配置MethodParameters参数

示例攻击JSON

{
    "$type": "System.Diagnostics.Process, System",
    "StartInfo": {
        "$type": "System.Diagnostics.ProcessStartInfo, System",
        "FileName": "calc.exe",
        "Arguments": ""
    }
}

攻击向量2:WindowsIdentity

漏洞原理
利用WindowsIdentity类的ISerializable接口实现和BootstrapContext属性

关键类分析

  • System.Security.Principal.WindowsIdentity
  • System.Security.Claims.ClaimsIdentity
  • System.Runtime.Serialization.ISerializable

攻击步骤

  1. 构造恶意BootstrapContext值(base64编码的payload)
  2. 通过ISerializable接口的GetObjectData方法注入恶意数据
  3. 反序列化时触发代码执行

示例代码

var identity = new WindowsIdentityTest();
string json = JsonConvert.SerializeObject(identity, new JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.All
});

// 修改$type为WindowsIdentity完全限定名
json = json.Replace(
    "\"$type\":\"WindowsIdentityTest\"", 
    "\"$type\":\"System.Security.Principal.WindowsIdentity\"");

3.3 漏洞触发条件

  1. 反序列化时TypeNameHandling设置为非None值
  2. 攻击者能够控制输入JSON数据
  3. 目标环境中存在可利用的类和方法

四、代码审计要点

危险模式识别

  1. 直接风险
JsonConvert.DeserializeObject(inputJson, new JsonSerializerSettings {
    TypeNameHandling = TypeNameHandling.All  // 高风险
});
  1. 间接风险
JsonConvert.DeserializeObject(inputJson, new JsonSerializerSettings {
    TypeNameHandling = TypeNameHandling.Auto  // 仍然危险
});
  1. 安全模式
JsonConvert.DeserializeObject(inputJson, new JsonSerializerSettings {
    TypeNameHandling = TypeNameHandling.None  // 安全
});

审计关注点

  1. 查找所有JsonConvert.DeserializeObject调用
  2. 检查TypeNameHandling参数设置
  3. 确认输入数据是否可控
  4. 检查是否有自定义JsonConverter实现

五、防御建议

  1. 输入验证

    • 严格验证反序列化的JSON输入
    • 使用白名单限制允许的类型
  2. 安全配置

    • 尽可能使用TypeNameHandling.None
    • 如需使用类型信息,限制反序列化类型:
      var settings = new JsonSerializerSettings
      {
          TypeNameHandling = TypeNameHandling.Objects,
          SerializationBinder = new MyCustomBinder()  // 自定义绑定器限制类型
      };
      
  3. 替代方案

    • 考虑使用System.Text.Json(.NET Core 3.0+)替代Newtonsoft.Json
    • 使用安全反序列化库

六、漏洞复现案例

复现步骤

  1. 构造恶意JSON payload
  2. 通过Web接口提交payload
  3. 服务器端反序列化触发RCE

示例攻击流程

  1. 访问http://localhost:5651/DefaultPost
  2. 提交恶意JSON数据
  3. 服务器调用JsonConvert.DeserializeObject反序列化
  4. 触发计算器弹出(证明RCE成功)

七、总结

  1. Json.NET反序列化漏洞源于不安全的TypeNameHandling配置
  2. 主要攻击向量包括ObjectDataProvider和WindowsIdentity
  3. 漏洞危害严重,可导致远程代码执行
  4. 代码审计时应重点关注TypeNameHandling配置和输入控制
  5. 防御关键在于限制类型处理和验证输入数据

扩展资源

.NET高级代码审计:Json.Net反序列化漏洞深度解析 一、Json.Net库概述 Newtonsoft.Json(Json.NET)是一个高性能的.NET JSON操作类库,主要功能包括: 实现.NET对象与JSON之间的转换 提供序列化(SerializeObject)和反序列化(DeserializeObject)方法 支持丰富的自定义序列化配置选项 性能对比 :Json.NET在性能上优于微软内置的DataContractJsonSerializer和JavaScriptSerializer 二、Json.Net序列化机制 基本序列化示例 关键点 : 静态方法不参与序列化过程 使用 [JsonIgnore] 特性可忽略特定属性 高级序列化配置 配置选项 : TypeNameAssemblyFormatHandling :控制程序集名称格式 TypeNameHandling :控制类型名称处理方式 三、Json.Net反序列化漏洞 3.1 反序列化基本用法 TypeNameHandling枚举值 : None :默认值,不读取/写入类型名称 Objects :仅处理对象 Arrays :仅处理数组 Auto :自动识别 All :处理所有值 3.2 攻击向量分析 攻击向量1:ObjectDataProvider 漏洞原理 : 当TypeNameHandling设置为非None值时,攻击者可构造恶意JSON实现RCE PoC构造步骤 : 序列化TestClass获取基础JSON结构 替换关键字段: 修改 $type 为攻击目标类型 设置 MethodName 为要执行的方法 配置 MethodParameters 参数 示例攻击JSON : 攻击向量2:WindowsIdentity 漏洞原理 : 利用WindowsIdentity类的ISerializable接口实现和BootstrapContext属性 关键类分析 : System.Security.Principal.WindowsIdentity System.Security.Claims.ClaimsIdentity System.Runtime.Serialization.ISerializable 攻击步骤 : 构造恶意BootstrapContext值(base64编码的payload) 通过ISerializable接口的GetObjectData方法注入恶意数据 反序列化时触发代码执行 示例代码 : 3.3 漏洞触发条件 反序列化时TypeNameHandling设置为非None值 攻击者能够控制输入JSON数据 目标环境中存在可利用的类和方法 四、代码审计要点 危险模式识别 直接风险 : 间接风险 : 安全模式 : 审计关注点 查找所有JsonConvert.DeserializeObject调用 检查TypeNameHandling参数设置 确认输入数据是否可控 检查是否有自定义JsonConverter实现 五、防御建议 输入验证 : 严格验证反序列化的JSON输入 使用白名单限制允许的类型 安全配置 : 尽可能使用TypeNameHandling.None 如需使用类型信息,限制反序列化类型: 替代方案 : 考虑使用System.Text.Json(.NET Core 3.0+)替代Newtonsoft.Json 使用安全反序列化库 六、漏洞复现案例 复现步骤 构造恶意JSON payload 通过Web接口提交payload 服务器端反序列化触发RCE 示例攻击流程 : 访问 http://localhost:5651/DefaultPost 提交恶意JSON数据 服务器调用 JsonConvert.DeserializeObject 反序列化 触发计算器弹出(证明RCE成功) 七、总结 Json.NET反序列化漏洞源于不安全的TypeNameHandling配置 主要攻击向量包括ObjectDataProvider和WindowsIdentity 漏洞危害严重,可导致远程代码执行 代码审计时应重点关注TypeNameHandling配置和输入控制 防御关键在于限制类型处理和验证输入数据 扩展资源 : 官方文档警告 GitHub漏洞示例 .NET反序列化系列课程