SharePoint Rce 系列分析(一)
2020-12-10 11:46:00 Author: paper.seebug.org(查看原文) 阅读量:264 收藏

作者:青藤实验室
原文链接: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 发布,如需转载请注明来源。本文地址:https://paper.seebug.org/1424/



文章来源: https://paper.seebug.org/1424/
如有侵权请联系:admin#unsafe.sh