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

得益于 @pwntester@Oleksandr 在 blackhat 上做的兩次關于 .net 安全的分享,.net 應用的攻擊面被越來越多的安全研究者了解。除了常規的反序列化,在今年的 blackhat-us 上兩人更是通過一系列的 SharePoint(以下簡稱 SP) Rce 漏洞展示了如何通過各種手段 bypass SP 的安全沙箱,以至于此后,SP 成了微軟月更新上的常客,后續的 SP Rce 漏洞大多使用了類似的手法,只是觸發點不同,或者 bypass 了之前的 patch。

上個月花了點時間學習了該議題,該議題實際上分為 java.net 兩部分,java 部分比較直觀也很精彩,本文不做討論。由于之前對 .net 以及 SP 不太熟悉,于是搭了環境逐個調試了文中提到的漏洞。看議題的 writeup 時由于作者的講述邏輯很清晰,感覺沒啥問題,實際上手調試時仍遇到不少問題,在此記錄這些問題與我的理解。

調試環境

Server2016
SP2016

背景知識

SP 一句話概括:微軟用 .net 開發的一套 cms。既然是 cms 肯定允許用戶上傳,普通用戶通過 PUT /my.aspx 的方式就可以上傳自己寫的任何內容,之后通過 GET /my.aspx 可以看到。

雖然我可以在 my.aspx 中寫任何內容,但并不是我寫的任何內容都會被 SP 服務端解析,不然任何 authed 用戶都可以 rce 了。這里就要提到 SP 的沙箱機制。

-w700

上圖是 writeup 中對 SP 沙箱的抽象,翻譯過來就是,出于安全性考慮,通過 web 上傳的用戶網頁文件存儲在數據庫中而非文件系統。如此,在網頁解析時,從數據庫中取出的網頁文件被閹割了一部分功能,比如本地文件包含指令 <!-- #include PathType = FileName -->,這類 aspx 就像運行在一個沙箱中。

上述邏輯具體是通過Microsoft.SharePoint.ApplicationRuntime.SPPageParserFilter 來實現,實際上是通過網頁文件的 path 來區分: -w625 如果進入了if分支,沙箱就會生效,簡稱 filter 機制。

但是,在服務端最終用System.Web.UI.TemplateControl.ParseControl()解析網頁時,如果按照下面的方式使用:

ParseControl(content);
ParseControl(content, ?true?);

filter 機制就會失效,只有第2個參數顯示指定為 false 時才 ok,我猜作者大概按照這個思路沒有找到直接可用的漏洞,但是發現在 design mode 下,filter 機制都會失效,但是會有新的校驗方法:Microsoft.SharePoint.EditingPageParser.VerifyControlOnSafeList()

// Microsoft.SharePoint.EditingPageParser
internal static void VerifyControlOnSafeList(string dscXml, RegisterDirectiveManager registerDirectiveManager, SPWeb web, bool blockServerSideIncludes = false)

這個方法簡稱 verify 機制,和ParseControl一樣,最后一個參數也會影響安全因素,當最后一個參數為 false 時(默認 false),允許使用 include 指令。

我在之前的 CVE-2020-17083:Exchange Authed Rce 分析 里提到過在 Exchange、SharePoint 里一旦可以任意讀利用反序列化就可以 rce,include 指令就能實現任意讀。

CVE-2020-0974

漏洞原理很簡單,背景知識里說了,在 verify 機制中,VerifyControlOnSafeList 方法的 blockServerSideIncludes 參數(最后一個參數)為 false 時允許使用 include 指令。

writeup 給出了漏洞利用方法的觸發點: -w676 下面是 SP 自帶的 RenderWebPartForEdit 用法 -w1437 直接測作者給出的 poc 返回 400 -w1287 發送空字符串時我注意到響應中 RenderWebPartForEditResult 的值都是 html 轉碼 -w1431 就明白了這里請求中的 webPartXml 參數也需要 html 轉碼 結果進行了4次 html 實例編碼,不用解碼,直接找 machineKey 對比 C:\inetpub\wwwroot\wss\VirtualDirectories\80\web.config 里的反序列化密鑰完全一致。 -w915 另外,在 HMACSHA256 加密的情況下,我只需要 validationKey 字段就可以完成反序列化利用,別的加密方式需要更多參數本文不做討論。

漏洞利用到此結束?并沒有。這個 validationKey 不是我需要的。在分析 CVE-2020-16952 時我就發現 SP2016 中存在一個穩定的反序列化利用點:

_layouts/15/zoombldr.aspx

它位于管理 web 下,所以在 SP 中能讀到 web.config 中的 machineKey 部分就能實現 rce,這也是大多數分析文章或者 poc 到實現讀取 machineKey 就結束了,因為之后的流程是 SP 反序列化利用的常識。

簡單解釋一下,SP 下每個站的 web 根目錄都有一個 web.config,這里面的反序列化加解密不是一樣的,比如我的測試機上在 C:\inetpub\wwwroot\wss\VirtualDirectories 目錄下有兩個目錄: -w1432 VirtualDirectories 后面的 80 和 15594 命名看著很像端口但是不是,參考 How to: Find the Web Application Root 可以知道默認安裝會有兩個,一個是 80 命名固定,另一個是管理 web 的 GUID,具體值隨機比如這里是 15594。爆破是一個思路,另外由于 #include 指令支持兩種模式 -w426 我測試了下面的指令沒有成功 <!-- #include virtual ="/web.config" --> 如何更方便地獲取管理 web 的 GUID 后期可能還需要探索,可以嘗試在 layouts 目錄下找找是否有能返回 GUID 的功能。

這里就直接用 15594 重新獲取我需要的 machineKey -w1439

拿到 machineKey 后用 ysoserial.net 生成 payload 發送給 SP 即可,由于利用 _layouts/15/zoombldr.aspx 反序列化 rce 在 SP 利用中是個比較常見的需求,我改了一下 @mr_me 的利用腳本,去掉了讀 machineKey 的部分,做完這些就可以彈出 calc 了 -w1424

參考

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

https://srcincite.io/pocs/cve-2020-16952.py.txt


Paper 本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/1424/