作者:青藤实验室
原文链接:https://mp.weixin.qq.com/s/ZLSFXUoNNAFxqeiD9RpYZg
在 SharePoint Rce 系列分析(一) 里我简单介绍了 SP 的沙箱机制,并且通过 CVE-2020-0974 展示了 bypass 原理:
VerifyControlOnSafeList(..., false)
这类漏洞原理简单,正则特征明显,可以借助自动化手段检测,除非找到新的 bypass 点,之后再出现同类型的漏洞概率不大。
本文介绍的是议题中的另一个漏洞:CVE-2020-1444。它在所有安全机制开启,没有方法参数使用不当情况下,通过 TOCTOU 实现了 rce;这种漏洞很难通过有效的漏洞模型去自动化检测,所以后续出现这种漏洞的可能性仍然存在,比如 CVE-2020-16951。
Server2016
SP2016
dnSpy
通过 proexp 找到管理 web 的 pid dnSpy attach 进程后在触发 url 被处理的地方下断点
通过 ObjectDataSource 定义 知道在 asp.net 中 ObjectDataSource
可以调用任意运行时方法,类似 ObjectDataProvider
<%-- ... -- %>
表示注释
<%@ ... %>
表示指令
以上都是 asp.net 的内联表达式,更具体点,比如下面 Register 指令实例:
<%@ Register TagPrefix="asp3" Namespace="System.Web.UI.WebControls" Assembly="System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" %>
<asp3:ObjectDataSource ID="ODS1" runat="server" SelectMethod="Start" TypeName="System.Diagnostics.Process" >
<SelectParameters>
<asp3:Parameter Direction="input" Type="string" Name="fileName" DefaultValue="calc"/>
</SelectParameters>
</asp3:ObjectDataSource>
<asp3:ListBox ID="LB1" runat="server" DataSourceID = "ODS1" />
第1行注册了对 System.Web.UI.WebControls
命名空间的引用,类似 python 中的 import
,别名是 asp3。
之后的 <asp3:ObjectDataSource...>
表示 System.Web.UI.WebControls
下必有一个名为 ObjectDataSource
的类。
借用议题中的原图来概括漏洞过程: 用户输入在经过服务端校验后,被服务端修改后再使用,这个顺序显然是有问题的,也是漏洞成因,具体到代码里: 为了方便理解,我把 "change and use" 指向了 "check" 下一行,实际上这里只是 change 的开始,也是漏洞成因的一个关键地方,不是最终解析的地方。
SP 的沙箱机制在议题中有详细介绍,上篇文章也说过,下面直接说漏洞相关的部分。
在 design mode 下,Check 通过 VerifyControlOnSafeList
完成。它位于:
请求发生时的调用栈
通过 call stack 可以看到 check 始于 ConvertWebPartMarkup
。
暂时不考虑具体的校验逻辑,试想一下,假如上传的整个网页文件是个注释,比如:
这时 Check 肯定能通过。
Change 发生在 ConvertMarkupToTree
。通过 OnLoad
前几行代码可以看出有两个必须提供的参数:WebPartUrl 和 Url。
Url 参数暂时不管,在后面漏洞利用章节会去讨论。通过对代码 trace 可以发现 WebPartUrl 指向的文件必须是一个 xml,这个 xml 还有其他要求,暂且不提。从服务端取参到 ConvertMarkupToTree
的处理步骤是:
从上面可以看出 string -> xml tree 发生在校验之后,看看具体做了哪些事
下面是正则定义:
这个正则匹配的是内联表达式中的 Register
指令,有两个命名捕获:TagPrefix 和 DllInfo。
TagPrefix 用正则捕获,DllInfo 是 TagPrefix 之后的所有内容。比如下面的例子:
再来看 ConvertMarkupToTree:首先把所有 Register
指令从字符串流中取出来做特殊处理(比如全部放到 xml 首尾这样的特殊位置),把剩下的内容简单处理一下,比如去掉转义、重新添加一个 root 就转成 xml tree 了:
回忆一下刚才通过 Check 的 demo:
由于正则匹配到了其中的 Register 指令,取出 Register 指令之后:
webPartMarkup = webPartMarkup.Replace(match.Value, "")
demo 就变成了: 之后会继续构造 xml tree,在最终网页解析之前肯定还要转回字符串流,那么这里本应该是注释的内容({unsafe ...})就在变成了一个 ASPX 标签,实现了沙箱逃逸。
BH 上作者给出了一部分 poc: 我参考了 CVE-2020-16951 的 poc,另一个 SP 的 TOCTOU 漏洞,结合上述分析,明白上述 xml 是这个漏洞利用的第一步,这个漏洞是分两步实现:
// put xml
PUT /poc.xml HTTP/1.1
...
// trigger rce
GET /_layouts/15/WebPartEditingSurface.aspx?WebPartUrl=http://.../poc.xml&Url=? HTTP/1.1
问题就出在 GET 请求的 URL 参数上,作者对这个参数的要求进行了简单说明: 我自然就想到了 Master Page Gallery 里的几个 master 文件 CVE-2020-16951 的 poc 就用了其中的 seattle.master 我尝试也用这个文件作为参数响应报错,calc 进程也没启动 在 SMP 中开启了启用详细日志:
Set-SPLogLevel –TraceSeverity VerboseEx
New-SPLogFile
Get-SPDiagnosticConfig | select LogLocation
Clear-SPLogLevel
通过重新错误的报错信息得到了报错时的 call stack:
Application error when access /_layouts/15/WebPartEditingSurface.aspx, Error=The field b510aac1-bba3-4652-ab70-2d756c29540f does not exist in the list item _catalogs/masterpage/seattle.master.
at Microsoft.SharePoint.Publishing.Internal.WebControls.ComponentRibbonHelper.GetContentTypeFieldValue(String pathToPageLayout)
at Microsoft.SharePoint.Publishing.Internal.WebControls.ComponentRibbonHelper.IsPageLayout(String pathToPageLayout, ContentTypeIdFieldValue& associatedContentTypeFieldValue)
at Microsoft.SharePoint.Publishing.Internal.WebControls.ComponentRibbonHelper.OnPreRender(EventArgs e)
at System.Web.UI.Control.PreRenderRecursiveInternal()
at System.Web.UI.Control.PreRenderRecursiveInternal()
at System.Web.UI.Control.PreRenderRecursiveInternal()
at System.Web.... 2c6c909f-e9be-00ce-823a-6efbede23872
...
进而确定了出错位置:
跟进后发现 b510aac1-bba3-4652-ab70-2d756c29540f
是 FieldId.AssociatedContentType
的 GUID:
正好和漏洞作者说的一致
It should contain the relative address of any file from the SharePoint
DataBase with the FieldId.AssociatedContentType field
我怎么判断 seattle.master 是否存在某个指定的 GUID 比如 b5..0f
呢。
通过了解 Onet.xml 文件这篇文章我知道了 Onet.xml 定义了所有的 BaseTypes,我在所有 Onet.xml 里搜索这个 GUID 并没有找到,之后我扩大了搜索范围在
C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\TEMPLATE
最终在
C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\TEMPLATE\FEATURES\PublishingResources
下找到了包含这个 GUID 的两个 xml
参考 CVE-2020-16951 的 poc,url 如果是个 master 文件肯定没问题,不管 master 如何和 xml 关联,此时我想直接把PublishingMasterTemplate.master
作为 url,如果这样我必须通过 web 能访问到这个 master 文件。
google 了一下 PublishingMasterTemplate.master
得到一个别人报错信息中的 url:
/_catalogs/masterpage/Forms/Publishing Master Page/PublishingMasterTemplate.master
尝试直接访问这个 path 得到 404,进一步研究发现这个东西似乎和 publishingresources 这个 feature 有关,默认关闭。
我用 SMP 打开了这个 feature
之后再尝试那个 path 仍然 404,但是尝试原请求不再报 GUID 找不到的错误了
也不再进入 catch 分支
在 list 中能看到 FieldId.AssociatedContentType
项
calc 进程启动
我确定 publishingresources 这个 feature 在 SP2016 默认安装条件下不会开启,看漏洞作者和 @mr_me 用的也是 SP2016 测试但没提到这个,查了下官方漏洞公告也没提到。所以我不确定这个是否是漏洞利用的条件之一,但是我确实是在开启了这个功能后复现成功,感兴趣的朋友可以研究一下。
https://srcincite.io/pocs/cve-2020-16951.py.txt
https://msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2020-1444
本文由 Seebug Paper 发布,如需转载请注明来源。本文地址:https://paper.seebug.org/1430/