CVE-2020-0618 writeup

安装

可以直接下受影响的老版本,然后添加报表服务

在下载文件夹里可以找到安装包,跟着走下一步,到这里勾上然后装好就行了

分析

我是默认安装的,代码文件就是 C:\Program Files\Microsoft SQL Server\MSRS13.MSSQLSERVER\Reporting Services\ReportServer\bin\ReportingServicesWebServer.dll,没有混淆和加壳,可以直接拖到ILSpy或者DnSpy里直接看代码

问题出在 Microsoft.Reporting.WebForms 中的 BrowserNavigationCorrector,可以看到 OnLoad 方法中

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
// Microsoft.Reporting.WebForms.BrowserNavigationCorrector
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
this.EnsureChildControls();
if (this.get_Page().get_IsPostBack() && string.Equals(this.m_pageState.get_Value(), "NeedsCorrection", 4))
{
string value = this.m_viewerViewState.get_Value();
if (!string.IsNullOrEmpty(value))
{
LosFormatter losFormatter = new LosFormatter();
object obj = null;
try
{
obj = losFormatter.Deserialize(value);
}
catch (Exception ex)
{
RSTrace.UITracer.TraceException(2, "Failed to rebuild the custom ViewState object. \n- Serialized ViewState: \"{0}\". \n- Exception: {1}", new object[]
{
value,
ex.ToString()
});
}
if (obj != null)
{
IPublicViewState publicViewState = (IPublicViewState)this.m_viewer;
publicViewState.LoadViewState(obj);
}
}
}
}

首先判断 pageState 字段是否等于 NeedsCorrection, 接受了一个字段 m_viewerViewState 并判断是否为空,这里其实字段名是ViewState

然后使用了 LosFormatter 来进行反序列化,一个非常典型的反序列化漏洞,感觉都可以直接拿出来当作漏洞demo使用,关于 LosFormatter反序列化漏洞 可以参考虎子哥写的连载文章 .NET高级代码审计(第十一课) LosFormatter反序列化漏洞

搜一下看看这个类在哪儿进行了实例化和调用

很巧合的是,ReportViewerPage 刚好是直接在 OnInit 方法中使用的,页面中的调用顺序 OnInit 是高于其他方法的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Microsoft.ReportingServices.WebServer.ReportViewerPage
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
ReportViewerHost reportViewer = this.ReportViewer;
reportViewer.EnableHybrid = this.ShowHybrid;
if (reportViewer != null)
{
PageRequestManagerErrorHandler pageRequestManagerErrorHandler = new PageRequestManagerErrorHandler();
reportViewer.get_Parent().get_Controls().AddAt(reportViewer.get_Parent().get_Controls().IndexOf(reportViewer), pageRequestManagerErrorHandler);
BrowserNavigationCorrector browserNavigationCorrector = reportViewer.CreateNavigationCorrector();
reportViewer.get_Parent().get_Controls().AddAt(reportViewer.get_Parent().get_Controls().IndexOf(reportViewer), browserNavigationCorrector);
}
if (Globals.ReqContext == null)
{
Globals.InitializeRequestContext(new HttpRequestContext(HttpContext.get_Current()));
}
}

对应的页面为 /ReportServer/pages/ReportViewer.aspx,所以这里我们只需要构造好这两个参数就可以了,主要是构造好反序列化数据,可以用powershell配合 ysoserial.net 使用,直接用一下网上已公开的PoC https://github.com/euphrat1ca/CVE-2020-0618

在本地监听好,登录后直接往页面post就可以看到弹回来的shell


可惜这个漏洞利用成本较高,得有一个能登录reporting services的凭证才能进行攻击

Author: 4uuu Nya
Link: https://qvq.im/2020/02/18/CVE-2020-0618/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.