.NET高级代码审计(第八课)SoapFormatter反序列化漏洞
字数 1606 2025-08-18 11:38:28
.NET SoapFormatter反序列化漏洞深度分析与防御指南
一、SoapFormatter概述
SoapFormatter是.NET框架中用于序列化和反序列化对象为SOAP格式的类,实现了IFormatter接口。它可以将.NET对象转换为SOAP格式的XML数据,也可以将SOAP数据反序列化为.NET对象。
核心特性
- 实现了
IFormatter和IRemotingFormatter接口 - 使用SOAP(Simple Object Access Protocol)格式进行序列化
- 包含CLR类型信息,支持类型精确性
- 从.NET Framework 2.0开始逐渐被BinaryFormatter替代
二、SoapFormatter序列化机制
基本序列化示例
[Serializable]
public class TestClass
{
public string classname;
public string name;
public int age;
public static void ClassMethod()
{
Process.Start("calc.exe");
}
}
// 序列化代码
TestClass test = new TestClass();
test.classname = "360";
test.name = "Ivan1ee";
test.age = 18;
SoapFormatter formatter = new SoapFormatter();
using (FileStream fs = new FileStream("data.xml", FileMode.Create))
{
formatter.Serialize(fs, test);
}
序列化输出示例
生成的SOAP-XML包含完整的程序集信息:
<SOAP-ENV:Envelope
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:clr="http://schemas.microsoft.com/soap/encoding/clr/1.0"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<a1:TestClass id="ref-1" xmlns:a1="http://schemas.microsoft.com/clr/nsassem/WpfApp1/WpfApp1%2C%20Version%3D1.0.0.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull">
<classname id="ref-3">360</classname>
<name id="ref-4">Ivan1ee</name>
<age>18</age>
</a1:TestClass>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
三、SoapFormatter反序列化漏洞
基本反序列化流程
SoapFormatter formatter = new SoapFormatter();
using (FileStream fs = new FileStream("data.xml", FileMode.Open))
{
TestClass obj = (TestClass)formatter.Deserialize(fs);
Console.WriteLine(obj.name); // 输出: Ivan1ee
}
漏洞原理
当SoapFormatter反序列化不受信任的SOAP数据时,攻击者可以构造恶意SOAP-XML,利用.NET类型系统中的特定类型实现远程代码执行(RCE)。
四、攻击向量分析
1. ActivitySurrogateSelector攻击向量
这是SoapFormatter反序列化中最危险的攻击向量之一,利用工作流组件中的代理选择器实现代码执行。
攻击原理
- 利用
System.Workflow.ComponentModel.Serialization.ActivitySurrogateSelector类 - 通过实现
ISerializationSurrogate接口控制序列化过程 - 结合
ISerializable接口完全控制序列化数据
关键代码结构
public class PayloadClass : ISerializable
{
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
List<byte[]> list = new List<byte[]>();
list.Add(new PocClass());
IEnumerable map_type = typeof(Type).Assembly.GetTypes();
var e3 = Activator.CreateInstance(map_type.GetType(), list);
// 填充分页控件数据源
PageDataSource pageDataSource = new PageDataSource();
pageDataSource.DataSource = e3;
// 配合填充MenuCommand类properties属性
DesignerVerb verb = new DesignerVerb("test", null);
MenuCommand command = new MenuCommand(null, verb);
// 使用DataSet和DataTable对象
DataSet dataSet = new DataSet();
dataSet.RemotingFormat = SerializationFormat.Binary;
dataSet.CaseSensitive = false;
// 使用BinaryFormatter序列化
BinaryFormatter binaryFormatter = new BinaryFormatter();
binaryFormatter.SurrogateSelector = new MySurrogateSelector();
// 序列化操作...
}
}
2. PSObject攻击向量 (CVE-2017-8565)
利用Windows PowerShell远程处理中的漏洞,通过System.Management.Automation.PSObject类型实现代码执行。
注意:此漏洞已在微软补丁中修复,打了补丁的系统无法利用。
五、漏洞利用场景分析
1. 直接XML载入
public void VulnerableMethod(string source)
{
SoapFormatter formatter = new SoapFormatter();
using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(source)))
{
formatter.Deserialize(ms); // 危险操作
}
}
攻击者只需控制传入的source参数,提供恶意构造的SOAP-XML即可实现攻击。
2. 文件读取场景
public object DeserializeSOAP(string path)
{
SoapFormatter formatter = new SoapFormatter();
using (FileStream fs = new FileStream(path, FileMode.Open))
{
return formatter.Deserialize(fs); // 危险操作
}
}
如果path参数可控,攻击者可以指定包含恶意SOAP-XML的文件路径。
六、防御措施
1. 最佳实践
- 避免使用SoapFormatter:从.NET Framework 2.0开始,官方建议使用BinaryFormatter替代SoapFormatter
- 使用安全序列化器:考虑使用DataContractSerializer或Json.NET等更安全的序列化器
2. 代码层面防御
// 安全反序列化模式
public object SafeDeserialize(byte[] data)
{
// 创建受限的SerializationBinder
var binder = new RestrictedSerializationBinder();
SoapFormatter formatter = new SoapFormatter();
formatter.Binder = binder;
using (MemoryStream ms = new MemoryStream(data))
{
// 添加额外的验证逻辑
if (!IsSafeData(ms))
{
throw new SecurityException("Unsafe data detected");
}
return formatter.Deserialize(ms);
}
}
// 自定义受限的SerializationBinder
public sealed class RestrictedSerializationBinder : SerializationBinder
{
public override Type BindToType(string assemblyName, string typeName)
{
// 只允许反序列化安全的类型
if (typeName == typeof(SafeClass).FullName)
{
return typeof(SafeClass);
}
throw new SerializationException($"Type {typeName} is not allowed");
}
}
3. 配置层面防御
- 实施代码访问安全策略(CAS)
- 使用.NET Framework的最新安全更新
- 在反序列化前验证输入数据的签名或哈希
七、代码审计要点
- 查找SoapFormatter使用:全局搜索
SoapFormatter类的使用 - 检查输入源:确认反序列化的数据来源是否可控
- 文件读取路径
- 网络传输数据
- 用户输入数据
- 验证类型限制:检查是否实现了
SerializationBinder限制反序列化类型 - 检查SurrogateSelector:确认是否使用了自定义的安全代理选择器
八、总结
SoapFormatter反序列化漏洞是.NET应用程序中严重的安全威胁,攻击者可以通过精心构造的SOAP-XML实现远程代码执行。开发人员应当:
- 尽量避免使用SoapFormatter
- 如果必须使用,实施严格的类型限制
- 对所有反序列化操作进行输入验证
- 保持.NET Framework和所有安全补丁更新
随着.NET的发展,更安全的序列化方案不断出现,开发人员应当及时评估和迁移到更安全的替代方案。