SoapFormatter是.NET框架中的一个类,用于将对象序列化为SOAP格式或从SOAP格式反序列化对象。与BinaryFormatter类似,SoapFormatter也存在反序列化漏洞,可能导致远程代码执行(RCE)。
SoapFormatter在反序列化过程中会完全信任输入数据,自动实例化并执行对象中包含的任何类型,而不进行适当的验证。攻击者可以构造恶意的SOAP消息,在反序列化时执行任意代码。
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Soap;
using System.Diagnostics;
[Serializable]
public class ExploitClass
{
private string command;
public ExploitClass(string cmd)
{
command = cmd;
}
// 当对象被反序列化时会自动调用的方法
public void OnDeserialization(object sender)
{
Process.Start(new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = "/c " + command,
WindowStyle = ProcessWindowStyle.Hidden
});
}
}
class Program
{
static void Main()
{
// 恶意对象序列化
ExploitClass exploit = new ExploitClass("calc.exe");
SoapFormatter formatter = new SoapFormatter();
using (MemoryStream ms = new MemoryStream())
{
formatter.Serialize(ms, exploit);
byte[] serializedData = ms.ToArray();
// 模拟攻击者发送的恶意数据
Console.WriteLine("Serialized malicious SOAP data created.");
// 受害者反序列化恶意数据
Console.WriteLine("Victim deserializing the data...");
ms.Position = 0;
formatter.Deserialize(ms); // 这将执行calc.exe
}
}
}
避免使用SoapFormatter:改用安全的序列化方式如Json.NET或System.Text.Json
使用替代方案:如果需要SOAP格式,考虑使用XmlSerializer
类型限制:如果必须使用SoapFormatter,实现SerializationBinder来限制允许的类型:
public class SafeBinder : SerializationBinder
{
public override Type BindToType(string assemblyName, string typeName)
{
// 只允许特定安全类型
if (typeName == "System.String" || typeName == "System.Int32")
return Type.GetType($"{typeName}, {assemblyName}");
throw new SerializationException("Unsafe type attempted");
}
}
// 使用方式
SoapFormatter formatter = new SoapFormatter();
formatter.Binder = new SafeBinder();
输入验证:验证所有反序列化的数据来源
最小权限原则:确保应用程序以最小必要权限运行
SoapFormatter漏洞与BinaryFormatter漏洞类似,可能导致: - 远程代码执行 - 拒绝服务攻击 - 敏感信息泄露
微软已标记SoapFormatter为不安全,并建议开发人员避免使用它处理不受信任的数据。在.NET Core和.NET 5+中,SoapFormatter已被移除。
SoapFormatter反序列化漏洞是一个严重的安全问题,可能导致完全的系统入侵。开发人员应避免使用SoapFormatter处理不受信任的数据,或实施严格的安全控制来减轻风险。