深度剖析Windows系统下的XPS文档漏洞攻击面
0X01 漏洞背景
CVE-2020-0605 就是这样的一种潜在的攻击案例,接下来跟随笔者一步步揭开它的神秘面纱。0X02 漏洞复现
XPS文件实际上是一组包含字体、图像以及文本内容的ZIP压缩文件,默认的扩展名为.xps,笔者环境是WIN10 + .NET FrameWork3.5,4.0以上不能成功触发。首先创建一个XPS文件,重命名为zip扩展名,解压后编辑Document/1/Pages/1.fpage文件,在FixedPage标记处添加 xmlns:sd="clr-namespace:System.Diagnostics;assembly=System" ,然后在
0X03 XPS介绍
XPS文档的浏览和打印通常使用在WPF开发领域, 全称为 XML Paper Specification,XPS 格式的一个重要特点是所有文档内容和静态资源都存储在一个文件内,文件存储结构和内容以及各个部分之间的关??系如下图
3.1 Fixed document sequense.fdseq 文件
Fixeddocumentsequense.fdseq 文件是树的根,如下该文件包含了XPS文档列表信息,明显是一组XAML,我们知道XAML里的所有的标签对应的都是.NET里的对象,所以这里的子标签DocumentReference就是一个内置对象,它的Source属性指向FixedDocument,既可指定本地文件也可以加载远程文件 *.xaml
// 加载本地文件
// 加载远程文件
3.2 [Content_Type].xml 文件
[Content_Type].xml 包含XPS文档里文件扩展名和相应内容类型之间的映射关系,如下扩展名.fdoc 对应fixeddocoument,在WPF里表示打印固定文档
3.3 FixedDocument.fdoc 文件
Documentsm目录结构下的 FixedDocument.fdoc文件 包含PageContent对象页面内容的引用列表信息,PageContent标记的Source属性指向FixedPage,既可指定本地文件也可以加载远程文件 *.xaml
3.4 *.fpage 文件
FixedPage包含页面呈现的所有可视元素内容,如
3.5 *.rels 文件
rels目录结构下的 *.fpage.rels文件保存了资源之间的关联关系,文件有引用的页面资源,例如字体和图片
3.6 Resources目录
Resources文件夹通常字体和图像都包含在其中,XPS中所有字体都具有 TrueType 字体的 *.TTF 扩展名或混淆 TrueType 字体的 *.ODTTF 扩展名,字体混淆是为了禁止提取字体并在未经许可的情况下在其他地方使用,图像可以是 PNG、JPEG格式。
0X04 XPS用法
在WPF中可将文档分为固定文档(FixedDocument)和流文档(FlowDocument),固定文档表示已经排版好准备打印的文档,所有的文本、图像内容位置都是固定的,从概念上相当于PDF文件。流文档能够根据各种细节动态布局内容,相比固定文档具有更高级的布局特性。WPF提供DocumentViewer容器加载FixedDocument,如下XAML 在固定页码标签放置两个TextBlock文本块填入字符串,Image标签引入图片所在的物理路径,渲染预览如下图
公众号:dotNet安全矩阵
网址:https://www.cnblogs.com/Ivan1ee/
除了界面UI创建XPS加载显示外,也支持以编程的方式创建一个XPS文件,将上述提到的XAML文件中FixedDocument标记所有内容保存到 testFixed.xaml,程序通过XamlReader.Load方法解析XAML生成testFixedPage.xps
第2小节提到XPS文件本身就是一个zip压缩包,将生成的testFixedPage.xps文件重命名为testFixedPage.zip,可见目录和文件结构如下
0X05 漏洞攻击面
5.1 FixedDocumentSequence远程加载恶意载荷
本地和远程加载均可以触发漏洞,笔者以远程加载为例打开根目录下的 FixedDocumentSequence.fdseq 文件,DocumentReference标记的Source属性指向远程xaml文件
笔者在本地用python启动了一个简易的web服务,在web目录下放置payload.xaml,请求地址为 http://127.0.0.1:8080/payload.xaml ,Payload.xaml内容如下
cmd
/c winver
WPF里程序初始化打印对话框显示文档内容时可触发漏洞,将XPS文件加载到内存并在DocumentViewer容器中显示,如下代码提供GetFixedDocumentSequence()方法返回文档根元素的引用,当漏洞被触发时web服务会接收到来自外部的HTTP请求
XPSDemo.App.Current.Dispatcher.Invoke((Action)(() =>
{
XpsDocument myDoc = new XpsDocument(@"createxps.xps", FileAccess.Read);
docView1.Document = myDoc.GetFixedDocumentSequence();
}
));
从调用栈能清晰看到 XpsDocument.GetFixedDocumentSequence()方法调用后进入一个内部实现的代理类XamlReaderProxy的Load方法,在Load方法里最终调用XamlReader.Load,该方法和XamlReader.Parse一样可以解析运行XAML代码,本质上XamlReader.Parse方法底层也是调用了XamlReader.Load实现文本解析。
6.2 FixedPage本地加载恶意载荷
打开 Documents/1/ FixedDocument.fdoc 文件,编辑 PageContent 标记的Source属性,同样可以加载远程xaml文件
同样也可以本地加载资源字典里的Payload,编辑 Documents/1/Pages/1.fpage 在
WPF中的PrintQueue 类表示一台打印机以及与其关联的输出作业队列, 允许对服务器的打印作业进行高级管理, AddJob 方法用于将新的打印作业插入队列。添加任务打印文档验证内容和进度通知时也可触发此漏洞请求远程的xaml文件
XPSDemo.App.Current.Dispatcher.Invoke((Action)(() =>
{
PrintQueue defaultPrintQueue = LocalPrintServer.GetDefaultPrintQueue();
PrintSystemJobInfo xpsPrintJob = defaultPrintQueue.AddJob("test", @"createxps.xps", false);
}
));
0X06 结语
XPS 文件在Windows操作系统中可使用 XPS Viewer打开,但是由于XPS Viewer 应用程序不使用 WPF 来显示 XPS 文件,因此不受该漏洞影响。但需要说明的是 Microsoft 开发的Exchange、SharePoint 或其他应用预览XPS文档时也许会触发此类攻击利用的实践场景。文章涉及的PDF和Demo已打包发布在星球,欢迎对.NET安全关注和关心的同学加入我们,在这里能遇到有情有义的小伙伴,大家聚在一起做一件有意义的事。本文首发于 公众号 dotNet安全矩阵