笔记作者:CDra90n

原文作者:Christian Mainka,Vladislav Mladenov,Simon Rohlmann

原文标题:Shadow Attacks: Hiding and Replacing Content in Signed PDFs

发表会议:NDSS 2021

原文链接:https://pdf-insecurity.org/download/Shadow_Attacks__Hiding_and_Replacing_Content_in_Signed_PDFs.pdf

数字签名PDF已经被广泛用于合同和发票中,以确保其内容的真实性和完整性。开启PDF签名的用户希望在文档被修改时会收到警告。本文介绍了一种新型的攻击,称之为影子攻击(Shadow Attack)。影子攻击规避了所有现有的对策,并破坏了数字签名PDF的完整性保护。它基于PDF规范提供的巨大灵活性进行攻击,因此影子文档(shadow document)符合PDF标准,且难以缓解。结果表明,测试的29个PDF查看器中有16个(包括Adobe Acrobat和Foxit Reader)容易受到影子攻击。本文介绍了可自动生成影子攻击的工具PDF-Attacker。此外,提出了检测工具PDF-Detector以防止将影子文档应用于签名,或应用于签名的PDF后对漏洞 进行取证检测。

0x01 Introduction

数字签名可以保护可移植文档格式(PDF,Portable Document Format)免受篡改。此功能可应用于诸如签订合同,协议,付款和发票之类的例子。诸如美国的eSign法案或欧洲的eIDAS法规之类的规定促进了公司和政府对数字签名文件的接受。亚洲和南美国家也接受与手动签名的纸质文档等效的数字签名文档。AdobeCloud是一种用于签名PDF文档的领先在线服务,在2019年就提供了80亿笔电子和数字签名交易。同年,DocuSign可以每天处理1500万份文档。

a)由单个实体创建的签名PDF: PDF签名的一种典型用例是,由一个实体同时创建PDF文档和签名。Amazon的发票是这种情况的常见示例。

b)由多个实体创建的签名PDF: 另一个典型的用例是合同的签订。例如,欧盟的赠款协议就是这种情况,在这种情况下,欧洲研究局和赠款接受者必须签署PDF文档。可以如下描述数字化合同的一般过程:协作者首先准备PDF合同。合作者可以是律师,设计师或不同公司的成员。一旦他们完成了PDF文档的定稿,然后,相关方就对合同进行数字签名。各方按顺序对PDF进行签名,并且PDF可以在各方之间进行多次交换。

c)PDF签名的安全性: 在2019年,对数字签名PDF的安全性进行了全面分析,发现多个应用程序中存在严重缺陷,并发现几乎所有这些漏洞都是易受攻击的。使用了一种攻击者模型,其中,攻击者拥有已由第三方进行数字签名的PDF,并在将签名添加到文档后对其进行操作。供应商已在其最新的PDF查看器版本中修复了这些问题。

在本文中研究了PDF查看器的这些补丁版本的安全性。扩展了攻击者模型并假设攻击者可以在签名之前将自己选择的内容放置到PDF文件中。该假设基于现实世界中多个实体对签名PDF的使用。例如,攻击者1可能会准备包含看似无害的内容的PDF文档。他们通过在签署文档后替换此内容来进行操作,请参见下图。本研究回答以下问题:如果攻击者在PDF签名之前对其进行了操纵,是否可以在不使签名无效的情况下改变数字签名PDF的可见内容?

d)影子攻击: 在模拟世界中,签名者通常在文档的末尾添加一个手写签名。末尾的添加有两个主要缺点:1)可以在带有任意内容的签名页面之前替换所有页面。2)攻击者可以在签名页面上的空白空间打印新内容,或者覆盖现有内容。使用数字签名时,这些操作是不可能的,因为这种类型的签名可以保护整个内容。因此,假设不可能将这种攻击从模拟世界转移到有数字签名的情况。

本文通过引入一种新的攻击类别:影子攻击,表明此假设是错误的。影子攻击的概念是,攻击者创建具有两个不同内容的PDF文档:1)内容被权威机构审查和签署的PDF,以及2)PDF签名后,攻击者可以发现的隐藏内容。在上图显示了攻击的概述。攻击者准备了一份影子文档。在模拟世界中,这是攻击者可以明确留下空白空间的步骤。PDF的签署者会收到文档,对其进行审核并签名。攻击者使用签名的文档,对其进行修改,然后将其发送给受害者。在模拟世界中,攻击者可以在准备好的空白处打印其内容。打开签名的PDF后,受害者的PDF查看器会成功验证数字签名。但是,受害者看到的内容与签名者看到的内容不同。本文介绍影子攻击的三种变体,它们使攻击者可以隐藏(Hide)、替换(Replace)、隐藏加替换(hide-and-replace)数字签名PDF中的内容。影子攻击并不仅仅依赖于动态内容替换。例如,本研究不使用JavaScript或从外部资源加载的内容,这些内容可以在对PDF签名后进行修改。

e)自动生成和预防: 为了促进未来的研究,提供了两种工具:PDF-Attacker和PDF-Detector。两种工具都是用Python编写的,并在 https://pdf-insecurity.org 上以开源形式发布。PDF-Attacker通过使用任意文件作为输入自动生成影子文档。文件签名后,PDF-Attacker会自动执行操作步骤并存储操作过的文件。PDF-Detector在执行的两个阶段检测影子攻击:在文件签名之前和最终操作之后。因此,PDF读者可以使用PDF-Detector拒绝对影子文档进行签名,从而避免造成伤害。为了方便对签名的PDF文件进行取证分析,PDF-Detector还可以分析签名文件并检测随后进行的操作。

f)影子攻击与以前的攻击的比较: 在抽象层面上,影子攻击类似于增量保存攻击(ISA,Incremental Saving Attack)概念。两种攻击都允许在不引发任何警告或错误的情况下操纵经过数字签名的PDF。他们都滥用称为Incremental Update的PDF功能。增量更新允许通过将文档修改附加到文件来更改PDF的内容。但是影子攻击和ISA之间存在本质区别。ISA通过附加格式不正确的增量更新来操作PDF,其中对象丢失或未正确关闭。此方法是的动机是查看器提供的可能危险对象的拒绝列表或允许列表。基于错误的增量更新或拒绝/允许列表中丢失的危险对象。与以前的攻击相比,影子攻击不使用格式错误的增量更新,而是符合标准并使用格式正确的增量更新。因此,在文件结构中不存在不一致。HideHide-and-Replace变体甚至绕过了完美实现的拒绝列表或允许列表。因此,检测恶意的Incremental Updates的对策均无法防止影子攻击。

g)结果: 通过评估29个PDF应用程序并揭示其中16个漏洞(包括Adobe Reader和FoxitReader),展示了影子攻击的适用性。此外,在Adobe产品上实现了提权,使攻击者可以在受害者的计算机上执行高特权操作。

i)责任披露: 本文研究者以负责任的方式向有关供应商披露了所有问题。与CERT-Bund(BSI)合作,并向他们提供了专门的漏洞报告,包括所有漏洞利用。他们与所有供应商建立了初步联系,并管理了报告的分发。在技术查询方面,支持供应商了解并解决问题。一些供应商与本文研究者联系,以重新测试其对策,本研究也提供了对策。

0x02 Basic

a)PDF文件结构: PDF是与平台无关的文档格式。它由三个主要部分组成,如上图所示。Part 1定义主体PDF body。它包含不同的对象,这些对象由它们的对象编号标识。最重要的对象是根对象,称为目录。在上图中,目录的对象标识符为1 0。目录通过链接到正文中的其他对象来定义整个PDF结构。在给定的示例中,目录链接到表单对象AcroForm,PDF MetaData对象和实际的PDF Pages对象。Pages对象可以引用多个Page对象,而后者又引用了实际的Content,Font和Images对象。这些对象引用是通过使用基于对象编号的专用引用字符串在技术上实现的。例如,Pages对象使用reference5 0 R引用Page对象。PDF的Part 2是Xref table。它包含对PDF body中使用的所有对象的字节位置的引用。可以在Xref table中将未使用的对象显式标记为free。例如,图像对象9 0free的,不显示在PDF中。尽管标记为free,但对象9 0Xref表中的条目可以包含空闲对象的字节位置。Part 3是Trailer。它由两个另外的引用组成:一个引用到Xref table开始的字节位置,另一个链接到根对象的标识符(1 0)。

b)增量更新: PDF的内容可能由于不同的原因而更新,例如,通过添加审阅注释或填写PDF表单。从技术角度来看,可以将此新内容直接添加到现有PDF正文中,并在Xref表中添加新引用。然而,根据PDF规范不是这种情况。使用增量更新可实现对PDF的更改。

增量更新将新对象添加到新的PDF主体中,该主体直接附加在前一个Trailer之后。为充分处理新对象,每个增量更新还附加了一个新的Xref表和Trailer(如果开启了增量更新)。综上所述,如果应用了增量更新,则PDF可以具有多个主体,Xref表和Trailer

c)PDF签名: 为了保护PDF的完整性和真实性,可以应用数字签名。为此,使用增量更新创建签名对象并将其附加到PDF。也可以多次签署PDF(例如,合同),从而导致多次增量更新。签名对象包含用于验证签名的所有相关信息,例如使用的算法和签名证书。它还定义了签名保护PDF的哪些字节,即,哪些字节用于计算签名算法使用的加密哈希。典型的签名从尾部的第一个字节开始,到最后一个字节结束。用户打开包含PDF签名的PDF后,查看器应用程序会自动验证签名,如果内容已被修改,则会发出警告。

d)签名文档的增量更新: 即使是在签名的PDF上,也可以应用进一步的增量更新,例如审阅批注或其他签名。签名仍然有效。

在本文中,重点介绍了在增量更新中查看器认为无害的元素,攻击者可以通过既不使签名无效,也不提出任何警告来更改签名文档的表示。影子攻击允许攻击者在PDF签名之前嵌入恶意内容,而不是在应用签名后单独修改PDF。

0x03 Attacker Model

攻击者模型基于真实的用例,在这些用例中签署了PDF文档(例如合同)。在这些用例中,攻击者可以在签名前将不可见的部分(影子内容,shadow content)注入PDF。签名后,攻击者再次操纵已签名的PDF。因此,它们在不使签名无效的情况下,对其内容进行了可见的更改。

a)攻击者能力: 如上图所示,攻击者能力可分为三个阶段。每个阶段的输出是一个PDF文件。

1)攻击者创建了包含不可见影子内容(例如文本或图像)的PDF文档PDF1 = createPDF()。

2)签名者接收PDF1(例如通过电子邮件),并通过对PDF1进行签名来创建新文档PDF2,即PDF2 =sign(PDF1)。

3)攻击者收到PDF2。他们可以再次修改PDF2,例如,攻击者创建PDF3 = manipulate(PDF2)。攻击者将PDF3发送给受害者。

b)成功条件: 如果满足以下条件,则攻击者成功(●):

1)签名人只有在不注意影子内容的情况下才对PDF1进行签名。换句话说,攻击者注入的所有更改必须对签名者是不可见的。

2)一旦受害者打开PDF3,他们就会看到影子内容。

3)PDF3签名验证成功。受害者相信签名者的公钥。受害者不信任任何其他密钥。特别是,他们不信任攻击者的密钥。例如,由于文件格式错误,打开PDF3不会显示任何错误或警告。

某些PDF查看器即使验证未处理的PDF2也会显示警告。如果未操纵的PDF2和操纵的PDF3的签名验证显示的警告完全相同,则称为攻击者实现了有限的成功(◐)。

0x04 Shadow Attack:Overview and Preliminaries

影子攻击的中心概念是,攻击者通过注入不可见的内容(“影子内容”)来准备PDF文档。将此准备好的PDF称为“影子文档”。之后,签名实体(例如,一个人或一个在线签名服务)会接收影子文档,对其进行签名,然后将其发送回攻击者。尽管数字签名提供了完整性保护,攻击者仍可以修改签名的影子文档并更改影子内容的可见性。但是,未检测到该操作,并且数字签名仍然有效。最后,攻击者将修改后的签名影子文件发送给受害者。尽管攻击者进行了更改,但签名验证是成功的,受害者看到的内容与签名实体不同。也就是说,受害者看到影子内容。

A.真实世界中的影子文档

考虑到影子文档的适用性,关注以下两个问题:(1)攻击者如何强制影子文件的签名?(2)为什么攻击者能够修改签名的影子文档?

a)影子文档签名: 在公司和机关中,员工通常会准备合同或协议等相关文件,这些文件会处理大多数细节和技术问题。经过仔细审查后,授权人员才能在文档上签名。另一种情况是共同体中文档的签名过程。通常,一个参与者创建文档的最终版本,然后由所有共同体成员签名。考虑到上述示例,恶意行为的员工或共同体成员可以在编辑过程中注入不可见的影子内容。因此,该内容将被签名。

此外,存在多种云签名服务,例如AdobeCloud,DocuSign或数字签名服务。除其他功能外,此类服务还会收到文档和签名。此类服务还可以用于对影子文档进行签名。

b)处理影子文档: 假定已签名的PDF文档不能更改,并且它是最终文档。由于所需的功能(例如多个签名或注释),因此不存在这种假设。例如,一个PDF文档可以被多次签名。在很多情况下,此过程都是必不可少的,因为它允许共同体中的利益相关者拥有包含所有合作伙伴签名的单个文档。从技术角度来看,每个新签名都会在已经签名的文档上添加新信息。但是,对于每个签名,仍应成功验证该文档。此外,PDF规范还定义了诸如注释(例如,便笺和文本突出显示)之类的交互功能。由于注释不会更改内容,而只会在其上添加注释,因此这些更改被认为是无害的。因此,PDF规范允许在看似无害的对象中注入看似无害的对象,而不会使签名无效。

B.文件修改分析

当前,PDF应用程序会分析签名后所做的更改,并尝试估计这些更改是否合法。例如,不允许覆盖文档页面上的内容,从而导致无效的签名验证。在本文中,首先分析了PDF应用程序认为哪些更改无害,并滥用这些更改来替换PDF文档中的内容。存在关于可能的操作的空白区域,允许的更改可总结如下。

a)追加新的Xref表和Trailer: 在PDF文档的每次更改上都附加新的新的Xref表和Trailer。例如,对于使用签名信息的每个签名过程,都会生成一个新的Xref表和Trailer。因此,将这些附加在文件末尾被认为是无害的。

b)覆盖无害对象: 增量保存攻击仅考虑对象类型:Catalog, Pages, Page和Contents。这是合理的,因为这些对象通过打开文档直接影响显示的内容。应用程序的供应商通过在应用签名后检测此类对象的定义来修复漏洞。本研究考虑了其他对象(如字体或元数据)的定义,这些对象也影响所呈现的内容。

c)重叠对象: 在分析中,提出了关于重叠内容的可见表示的问题。更准确地说:“如果两个对象在页面上共享同一位置,那么哪个对象在应用程序前台显示,哪个对象在后台显示?” 本文确定文档中对象的声明是决定性的。在重叠的情况下,第一个对象显示在第二个对象的顶部。因此,可以将相同的对象添加到PDF文件中,但顺序不同。由于对象的内容未更改,因此该增量更新也被认为是无害的。但是,打开PDF文件时可见内容会更改。

d)更改交互式表单: 本研究观察到一种应用于交互式表单的意外功能,该功能覆盖了文本字段的内容。通过单击文本字段,将显示其内容,并且叠加层消失。尽管避免讨论此功能的有效性,但发现叠加层上的更改被认为是无害的,并且不会使签名无效。

C.总结

PDF规范通过软化有关数字签名文档的完整性保护的规则,定义了可用性和安全性之间的折衷。这意味着可以通过应用增量更新来扩展签名的PDF文档。攻击者可以在附加到签名文档末尾的增量更新中注入内容。由于PDF签名是在PDF文件的固定字节范围内计算的,因此增量更新不在该范围内,并且不会违反该加密保护。通过定义允许和禁止的更改的例外,开发人员团队负责检测和分类每个Incremental Update中包含的危险元素。错误的决定会导致漏洞。在下一节中,将展示归类为无害的更改如何在不使签名无效的情况下实现内容替换。

0x05 Shadow Attack:Hide, Replace, Hide-and-Replace

在本节中介绍了影子攻击的三种不同类别:隐藏,替换和隐藏加替换。每个攻击类别都引入了一种不同的技术,可以在签名验证过程中隐秘地操作分配的PDF,而不会引起任何警告或异常。

每次攻击都基于攻击者进行的两个操作步骤,如前图所示。在步骤1中,攻击者通过注入影子内容来准备文档。此影子文档将发送给签名者。在步骤2中,攻击者收到签名的文档,并使影子内容可见。该文件已发送给受害者。总而言之,创建了八种涵盖所有攻击方差的漏洞利用程序。在以下各节中,将解释每种攻击的概念及其执行。

A.影子攻击:隐藏

此类影子攻击旨在将与受害者相关的内容隐藏在可见层后面。例如,攻击者可以在全页图片“签名以获得奖励!”后面隐藏文本“您已被解雇!”。攻击者一旦收到签名的文档,便会操纵该文档,以使查看器应用程序不再呈现图片。从攻击者的角度来看,隐藏攻击具有两个优点:

1)如果使用增量更新添加了新的可见内容,则许多查看器会显示警告。但是,在大多数情况下,如果内容被删除,它们不会发出警告。

2)对象仍可在PDF中访问。在上面的示例中,文字“您被解雇了!”仍可以通过搜索功能检测到。如果使用在线签名服务,并且通过搜索特定的关键字来查看文档,则可能需要进行此检测。本文确定了此攻击类别的两个变体,下面将对其进行进一步说明。

1)变体1通过引用的对象隐藏内容Hide Content via Referenced Object):在此攻击变体中,攻击者创建覆盖对象(例如图像或表单域),并在文档签名后隐藏它们,以显示这些对象下面的内容。创建了三种不同的漏洞利用方法,它们分别通过恶意图像隐藏内容,通过恶意表单字段隐藏表单字段以及通过恶意表单字段隐藏内容。

a)步骤1 –注入影子内容: 如上图所示,攻击者注入一个或多个图像并将其放置在原始内容上。图像可以覆盖整个页面或仅覆盖部分内容,例如,数字或文本段落。攻击者完全控制所放置图像的位置和可见性。

b)第2步–使影子内容可见: 最简单的方法是创建一个增量更新,该更新仅通过将overlay对象设置为free来更新Xref表。但是,许多查看器(例如Adobe)将该更改分类为危险并抛出错误或警告。因此,使用另一种方法:在增量更新中使用相同的对象ID,但将其定义为不同的对象类型。例如,将叠加层类型Image更改为XML/Metadata。此外,添加了一个Xref表更新,该更新指向元数据对象,但保留了叠加层的对象ID。当打开此操作过的文档时,由于无法显示元数据,因此叠加层被隐藏。由于使用 Incremental Update将元数据添加到签名的PDF被认为是无害的,因此签名保持有效。

此外观察到,如果攻击者将其引用更改为空对象,则它们可能会隐藏表单域。为了执行攻击,攻击者将恶意形式的字段放在攻击者放置预定义值的原始字段的上方。被操纵的文档被发送给签名者。他们只会看到恶意表格字段。攻击者收到已签名的文档后,将恶意字段引用为空对象,从而使这些恶意字段消失。这样,原始表单字段(包括攻击者的预定义值)就会显示给受害者。

2)变体2-按对象顺序隐藏内容Hide Content via Object’s Order):在分析过程中发现,对于两个大小相同且在文档中x-y位置相同的不同表单域,仅显示最后一个域。此外,只要内容没有更改,就可以在增量更新中重新声明相同的表单字段。基于这两种观察,攻击者可以建立以下利用。

a)第1步–注入影子内容: 攻击者将shadow form字段注入到原始未签名文档中,该影子表单字段与要隐藏的内容位于相同的x-y位置,但是他们在原始对象之前声明了它们的表单对象。签名者只能看到原始表单字段,因为它们是在影子字段之后定义的。

b)第2步–使影子内容可见: 攻击者收到文档后,将附加一个Incremental Update,该Update将复制并粘贴原始字段和影子表单字段。但是,在这种情况下,他们首先放置原始图像,然后放置影子表单字段。结果,显示了影子表单字段及其值,而不是原始字段。由于对象本身并没有修改,只是它们的声明顺序而已,因此增量更新被认为是无害的。

B.影子攻击:替换

该影子攻击类的主要思想是使用直接更改先前声明的对象的增量更新。由于不允许对所有类型的对象进行修改,因此攻击者只能更改认为无害的对象,但仍然可以更改文档的可见内容。例如,字体的(重新)定义不会直接更改内容。但是,它会影响所显示内容的视图并使数字或字符交换成为可能。确定了此攻击类别的两个变体。

1)变体1-通过重叠替换Replace via Overlay):PDF表单支持不同的输入,例如文本字段,文本区域和单选/选择按钮。表单可以具有默认值,例如预定义的文本。用户可以动态更改这些值并将其存储在PDF文档中。

该攻击滥用了PDF文本字段的专有属性。一个文本字段可以显示两个不同的值:实际字段值和叠加值,一旦选择了文本字段,该值就会消失。表单字段的实际值包含在名为/V的对象键中。叠加元素的内容在/ BBox对象中定义。/ BBox对象与HTML表单中已知的提示标签具有可比性。例如,提示用户名指示应将用户名输入特定的登录字段。与HTML相比,PDF中的提示和实际值之间没有视觉上的区别,在上图中描述了一个示例攻击。

a)步骤1 –注入影子内容: 首先,攻击者创建一个包含交互式表单的转账传票(PDF1),签名者在签署文档之前完成该表单。攻击者使用默认值初始化某些表单元素。在上图提供的示例中,攻击者将前三个表单字段的值/V设置为Attacker和攻击者的IBAN和BIC。其次,攻击者将叠加值(/ BBox)设置为unicef并设置相应的IBAN和BIC。只要签名者不关注准备的值,他们就认为正确的值已经预先填充。

b)第2步–使影子内容可见: 签名者可以在不更改预填写表单的情况下对PDF进行签名。一旦攻击者收到PDF2,他们就会通过使用不同的值替换存储在/BBox中的叠加层来更新文本字段。/V中存储的值保持不变。由于原始文本字段值未更改,而仅覆盖了更改,因此查看器认为此替换无害。

受害者打开PDF3后,查看器首先验证每个文本字段中/V中存储的值是否已更改,并且是否与已签名的值不同。如果值已更改且与已签名的值不同,则签名验证失败。由于攻击者未更改/V中存储的任何值,因此签名仍然有效。然后,查看器处理每个文本字段对象,并显示/BBox值(如果它映射到已签名的对象)。否则,将显示存储在/V中的值。由于攻击者更改了/BBox的值,因此显示了/V(成为攻击者)的值,并且相应的恶意交易也通过了。结果,签名者和受害者在同一文档中看到不同的内容,这本应该通过数字签名来防止。对于每种攻击变体,都创建一个漏洞利用程序。

2)变体2-通过覆盖替换Replace via Overwrite):攻击的思想是ISA。因此,供应商实施了一系列被认为是危险的对象,并不允许它们在增量更新中出现。但是,在许多应用程序中,字体被认为是无害的,因此可以在增量更新中定义它们。这种攻击变体被证明是相反的。

a)步骤1 –注入影子内容: 攻击者分析与该内容相关的原始文档和馏出物中使用的字体。其次,PDF中通常不包含默认字体,例如Verdana或Times New Roman。在这种情况下,攻击者需要注入字体说明。

b)第2步–使影子内容可见: 文档签名后,攻击者将添加新的字体描述并覆盖以前的字体描述。新的字体描述完全改变了原始文本的显示方式。例如,创建了一个漏洞利用程序,将原始文本US90 5628 3174 5628 3174的显示方式更改为US01 2345 678923456789。由于新字体的定义被认为是无害的,因此验证签名的应用程序不会警告所做的更改。创建恶意字体描述的流行软件是FontForge.4。

C.影子攻击:隐藏加替换

在此影子攻击类中,攻击者创建一个影子PDF文档,该文档将发送给签名者。PDF文档包含内容不同的另一个文档的隐藏说明。由于签名者无法检测到隐藏的(恶意)内容,因此他们对文档进行签名。签名后,攻击者将收到文档,并仅附加一个启用了隐藏对象的newXref表和Trailer。确定了此攻击类别的两个变体,两种变体的不同之处在于,攻击者在文档签名后启用隐藏内容的方式不同。对于每种攻击变体,创建了一个漏洞利用程序。

1)变体1-更改对象引用( Change Object References):此攻击变体的想法是使用外部参照表将对文档目录(或任何其他隐藏对象)的引用更改为指向影子文档。在上图中,描述了攻击的示例,并将进一步说明。

a)步骤1 –注入影子内容: 攻击者创建一个PDF文件,其中包含两个具有相同objectID(例如4 0 obj)但内容不同的对象:“对文档签名以获取奖励!”和“您被解雇了。立即离开”。如上图左侧所示,在Xref表部分中,引用了看似无害的内容。签名者只能看到此内容并签名PDF文件。

b)步骤2 –使影子内容可见: 攻击者收到签名的PDF后,将添加一个新的Xref表,并将该引用与具有恶意内容“您被解雇了。立即离开”的对象(例如4 0 obj)交换。还添加了新Trailer。由于在指向区域内包含指向已定义对象的Xreft表被认为是无害的,因此不会对所做的更改发出警告。签名验证成功。但是,受害者看到的内容与签名者看到的内容不同。

2)变体2-更改对象用法Change Objects Usage):此攻击变体的想法再次是使用外部参照表。但是,攻击者没有更改对对象的引用,而是指定了哪些对象“正在使用”和哪些对象未被使用(即free)。使用此Xreft表功能,攻击者可以修改先前包含的对象的可见性。通过这种方式,攻击者可以隐藏“使用中”的对象并显示free对象。这可以在不更改对象本身的情况下实现。攻击者只接触Xreft表,但是可以完全更改已签名文档的表示。

a)步骤1 –注入影子内容: 与第一个攻击变体类似,攻击者插入正确引用但在Xref表中标记为未使用的恶意内容。因此,仅原始文档的内容显示给签名者。

b)第2步–使影子内容可见: 攻击者一旦收到签名的操纵文档,便会附加一个新的Xreft表。新的外部参照表启用了隐藏内容并禁用了原始内容。

攻击者通过注入新对象来操纵原始文档。在给定的示例中是9 0 obj。攻击者通过使用外部参照表禁用该对象的使用,从而隐藏了该对象。

攻击者通过附加Xref表来操纵已签名的文档。在给定的示例中,具有定义页面内容的ID 2的对象被禁用,具有ID 9的对象被启用并因此可见。

D.影子攻击的隐蔽性

影子攻击需要与签名者和受害者互动。因此,攻击者必须创建文档,以使两个实体都不会因为仅打开和查看文档而变得可疑。所有攻击变体的情况确实如此。但是,诸如文本选择,粘贴文本或在文档内搜索之类的进一步操作可能会使暴露攻击的隐隐蔽性。对于所有攻击类别,都要求受害者不能以任何方式检测影子内容。因此,集中讨论签名者可能检测到攻击的情况。

Hide and Replace类对签名者完全隐藏。从签名者的角度来看,不可能检测到影子内容。攻击的变体2仅限于形成区域,因为许多查看器认为其隐藏是无害的。

通过在叠加层后面搜索特定文本或选择覆盖的内容,可以检测到Hide变体1((Hide via Referenced Object)。关于此限制,覆盖的内容只能是数字或文本区域,使攻击难以检测。考虑到Hide变体2(Hide via Object’s Order),由于可以隐藏先前显示的字段,因此对于表单域完全隐藏了攻击。

关于Replace 变体1(Replace via Overlay),只有在表单字段是可编辑的并且用户单击该字段时,才能检测到攻击。值得注意的是,攻击者定义了表单字段的功能,并且始终可以停用可编辑性。可以通过搜索原始内容或将操作内容复制粘贴来检测Replace变体2(Replace via Object’s Order),复制的文本包含原始值。

E.影子攻击与增量保存攻击

在本节中,着重介绍影子攻击与ISA攻击之间的区别,以避免两种攻击概念之间的混淆。首先,通过分析所有已知的和公开可用的ISA攻击媒介及其相应的对策来提供有关ISA的方法。其次,解释了为什么这些对策不足以减轻影子攻击。

a)攻击媒介: ISA直接覆盖内容对象,或者使用格式错误的增量更新来绕过保护机制。分析了所有可用的ISA攻击向量,并将它们分为四类:禁止对象,无效对象,缺少Xref表和缺少Trailer,这四个类别都不是通用的。每个类别都取决于相应的查看器,甚至取决于其版本。此外,它们对误用对象和增量更新的解释都不同。最后,可以说ISA的通用性和软件依赖性较小。

相反,影子攻击依赖于格式正确的增量更新,因此不依赖于每个观看者的特定解释,而是依赖于符合标准的功能。考虑到恶意PDF文档的创建,ISA的扩展能力优于影子攻击。要执行ISA,攻击者必须由受信任的机构拥有一个签名文件,并且他们可以创建包含任何内容的恶意PDF文档。攻击者只能显示在签名过程中隐藏的内容,而该内容已经是签名文件的一部分。结果,攻击者可以创建的恶意PDF文档数量受到限制。

b)攻击者模型: 两种攻击都依赖于不同的攻击者模型:ISA依赖于拥有经过数字签名的PDF文档的攻击者。影子攻击还假定攻击者在对PDF进行签名之前已注入恶意内容。

c)对策:在下表中总结了已实施的ISA对策。

第一个对策是在增量更新中定义禁止对象,即将对象/Pages,/Page,/Contents列入黑名单。这是合理的,因为这些对象中的每个对象都通过打开PDF直接影响呈现的内容。所有其他对策均针对格式错误的增量更新。

影子攻击不受任何这些对策的影响,因为它们不依赖格式错误的IncrementalUpdate。可以通过扩展带有禁止对象的当前列表来检测新字体的定义,但是Replace via Overlay不会受到影响。只要查看器允许增量更新,HideHide-and-Replace 变体始终适用。总之,PDF查看器必须选择是否符合标准(允许增量更新)和易受攻击,或者是否安全和不符合标准。

0x06 PDF-Attacker

在本节中介绍PDF-Attacker,这是一个自动创建影子攻击漏洞的工具集。

a)PDF-Attacker的设计: PDF-Attacker是使用Jupyter Notebook用Python编写的。这种设计实现了类似于影子攻击所必需的高灵活性。针对每种影子攻击类别的每种攻击变体,创建了一个单独的Jupyter Notebook,以便可以独立研究和扩展所有攻击。

最初目标是对所有攻击使用单个Python PDF库。事实证明,这不是理想的,因为每个攻击都针对不同的PDF功能。例如,对于使用表单的攻击,reportlab库提供了许多有用的功能。相比之下,Hide-and-Replace攻击要求对PDF对象的低级别访问,而pypdf4则可以做到这一点。最后,对不同的攻击使用了不同的库,以最大限度地发挥工具的功能。

b)PDF-Attacker的配置: 在开始使用PDF-Attacker之前,需要执行一些配置步骤。配置步骤可以总结如下:

•要操纵的内容: 与攻击变体无关,PDF-Attacker需要知道攻击范围内的内容。这可以是整个页面,字段值或字体描述。

•影子内容: 根据攻击的变体,还需要准备影子内容。该内容可以是与某些内容,恶意字体,恶意值或具有特定内容的整个文档重叠的图像。

•关键材料: 许多PDF应用程序都提供仅在商业版本中对PDF进行数字签名的功能。由于不想依赖外部软件,因此决定实现签名模块。还可以使用与提供的密钥不同的密钥来指定相应的密钥材料。

c)使用PDF-Attacker进行漏洞利用生成: 使用PDF-Attacker进行漏洞利用生成分为三个阶段,如上图所示。在第一阶段生成影子PDF中,PDF-Attacker将任意PDF用作输入并根据其插入影子元素到所选的攻击变量。此阶段是攻击最复杂的部分。因此,PDF标准具有复杂性和灵活性。该工具应能够处理不同的PDF版本,新功能和交互式元素。该工具应在复杂结构中找到相关内容,并以可用的方式放置攻击向量。能够通过使用多个库解析PDF文件并找到相关内容来减少这种复杂性。相关库可以总结如下:

•隐藏: wand库可将任意PDF转换为图像,并可以将其用作叠加层。

•替换: python库reportlab和fitz提供用于处理表单并更改其值的接口。某些攻击变体要求对PDF源代码进行低级别访问,以操纵外观或交换现有字体。对于这种情况,另外使用pypdf4库。

•隐藏加替换: 准备此攻击需要创建完整的影子文档和相应的Xref表。只有pypdf4库提供了这样的低级接口,能够自动执行这些步骤。但是,任何库均不支持某些攻击步骤。因此,直接处理了PDF。

影子PDF签名阶段使用endesive库在Python中模拟签名过程。该决定允许轻松地模拟准备和修改阶段。通常,此步骤也可以在外部执行,例如,通过使用Adobe Acrobat对准备好的PDF进行签名。影子内容可见阶段中,对签名的PDF进行操作,以显示影子内容。

考虑到Replace via Overwrite攻击,本研究创建了一种恶意字体。因此,只有具有该字体的文件才能被攻击。通过自动提取PDF文件中包含的字体并使用诸如FontForge 5之类的工具来动态生成恶意字体,可以避免这种限制。关于影子内容,为每个攻击变体准备了概念证明,允许对此内容进行更改。但是,不支持或仅部分支持更复杂的更改,包括对多个表单或页面的操作。

0x07 Evalution

在本节中介绍评估的结果。在下表中列出的所有查看应用程序中,本研究创建的处理过的PDF文档都被作为黑盒程序进行了测试。

A.测试环境

使用三个计算机系统来模拟攻击者,签名者和受害者这三个实体。当攻击者和签名者的系统基于Windows 10时,将受害者的系统分为Windows 10,macOS Catalina和Ubuntu 18.04.3 LTS。因此,可以测试操作对所有标准操作系统的影响。作为Adobe Acrobat中创建的数字ID的一部分,签名系统是唯一包含用于数字签名的私钥的系统。要签署PDF文档,使用了Apache PDFBox库,AdobeAcrobat Pro 2017和PDF-Attacker。为所有攻击变体创建了8种不同的漏洞,并在受害者系统上的所有查看程序下评估了这些操作。

B.应用

包含了可以正确处理签名的PDF文档的PDF查看应用程序。总共找到了29个适用于Windows,macOS和Linux的PDF应用程序。即使版本号没有直接表明这一点,应用程序PDF Editor 6 Pro和PDFelement在2020年1月以适用于macOS和Windows的最新版本发布。

a)排除的应用程序: 仅考虑了支持签名验证的应用程序。通过这种方式,排除了流行的Linux PDF应用程序,例如Evince和Okular。出于同样的原因,排除了Sumatra(Windows)以及Preview and Skim(MacOS)。排除了制造商不再维护的过时应用程序,例如Adobe Reader for Linux。进一步排除了在线签名服务,例如DocuSign和AdobeSign,因为它们不提供可见性层。这些服务输出一个报告,该报告指示PDF签名有效还是无效。但是,它不提供是否显示影子内容的任何信息。由于库不提供查看PDF文档的功能,因此无法评估攻击的成功程度。

C.结果

总体而言,如上表所示,在29个PDF查看应用程序中,有16个易受至少一个存在的攻击(●)。令人惊讶的是,对于12个PDF查看器,这三个攻击类别均获得了成功。某些应用程序具有有限的漏洞(◐)。有限的漏洞意味着即使进行合法修改,应用程序也始终会发出警告,例如第二次分配文档(例如,用于合同)。因此,用户无法区分合法更改和恶意更改,例如揭示影子内容。

a)操作系统的差异: 虽然找不到Windows和macOS版本之间Adobe产品的差异,但发现在这些操作系统中的Master PDF Editor,PDF Editor Pro和PDFelement的签名验证方面存在显着差异。在这三个查看应用程序上没有经过测试的攻击是成功的。这些差异的原因在于打开签名的PDF后显示的不同验证消息。在macOS上,三个应用程序会发出警告,指出每次检测到增量更新时签名均无效。比较起来,在Windows上,查看器显示签名是有效的,并且在某些情况下,警告已进行了更改。

应用程序的不同版本证明了操作系统依赖性的不同结果是另一个原因。例如,在Windows上,Foxit Reader的版本为9.7,而在macOS上,其版本为3.4。该观察结果得出这样的假设,即两种应用程序在处理PDF的方式上都可能会有所不同。该假设在上表中得到证实。两种应用在签名验证方面都有很大的不同,这导致了关于影子攻击的不同结果。有趣的是,在macOS下,Foxit的应用程序具有独特的功能,即只有在macOS的密钥串包含私钥的情况下,签名状态才从未知变为有效。

b)隐藏Hide影子攻击类别已成功用于12个PDF查看应用程序。对于该漏洞利用,在使用Incremental Updates时,将覆盖图像文件重新声明为/ Subtype / XML / Type / Metadata和/ Subtype / Image / Type / XObject。然后,Adobe Acrobat应用程序淡出了图像文件,但同时,这些应用程序在UI层1和2中确认了PDF文档的有效签名。手动启动的签名检查返回错误代码109,但签名状态不受影响。

c)替换: 共有16个PDF查看应用程序易受Replace影子攻击类别的攻击。他们分为两种不同的攻击方式:通过叠加替换和通过覆盖替换。尽管Adobe查看器将fontexchange正确地分类为未经授权的增量更新,但在替换表单中的字段文本时,签名仍然有效。在PDF Editor 6 Pro和 PDFelement中观察到了完全相反的情况。虽然可以成功地操作字体,但是在交换字段内容时,签名状态更改为无效。Foxit Reader显示了另一项行为。从版本9.5.0.20723更新到9.7.0.29455之后,增量更新允许在不使签名无效的情况下交换字体。由于LibreOffice Draw忽略了PDF文档中包含的字体,因此应用程序不受这种类型的攻击。但是,可以在不使签名无效的情况下交换字段文本。

d)隐藏加替换: 在16个PDF查看应用程序中,可以识别Hide-and-Replace漏洞。这两个Adobe查看应用程序成功显示了文档中隐藏的内容。相反,他们在UI层1和2中将签名显示为有效。手动启动的签名检查会提供有关页面结构数据中无效节点的消息,但签名状态不受影响。

e)责任披露: 根据上表中所示的评估,针对26个易受攻击的应用程序(包括16个完全易受攻击的应用程序和10个漏洞有限的应用程序)启动了负责任的公开流程。与CERT-Bund(BSI)合作进行了责任披露,并创建了专门的漏洞报告。CERT-Bund非常感谢与所有受影响的供应商以及使用数字签名PDF的相关组织的联系。一些供应商迅速做出反应,并告知已经实施了修复(Adobe,Foxit,LibreOffice,Power PDF,Soda PDF)。在某些情况下,供应商联系以寻求技术咨询。在其他情况下会收到消息确认消息,但没有有关补丁的反馈(Master PDF,Nitro,PDF Architect,PDF-XChange,PowerPDF)。此外,尽管在七个月以上进行了多次接触尝试,有的阅读器仍有任何反馈(Expert PDF,PDF Editor Pro,Perfect PDF,PDFelement)。报告发布七个月后,使用最新的可用软件版本对表II中列出的所有PDF应用程序进行了重新评估。修复程序的当前状态可以总结如下。

修复的应用程序: 验证了供应商对15个PDF应用程序的修复。对于PDF Architect,PDFelement和Soda PDF,有必要升级到下一个程序版本:PDF Architect 8,PDFelement 8,Soda PDF 12。

未修复的应用程序: 6个PDF应用程序中的安全漏洞仍未消除(Windows和Linux中的Master PDF,Nitro Pro,PDF-XChange Editor,Perfect PDF Reader)。同时,还有尚未的更新五个应用程序(Expert PDF 14,Nitro Reader,PDF Editor 6 Pro,PerfectPDF 8 Reader,Perfect PDF 10 Premium)。因此,在这十一种情况下,仍然存在所报告的漏洞。

0x08 PDF-Detector

在抽象层面上,影子攻击分两步执行。首先,攻击者准备一个隐藏文件,其中隐藏了恶意内容。然后签署该文件。其次,攻击者操纵已签名的文档以显示隐藏的内容,同时保持签名状态有效。本研究开发了PDF-Detector,这是一种预防和检测影子攻击的工具。PDF-Detector提出了两种不同的方法来缓解和检测有关对策的影子文档。

A.预防

在本节中介绍一种能够检测隐藏内容的算法。因此,可以在签名前警告用户。要查找隐藏的(非活动)影子内容,必须可靠地从PDF文档中提取文本,图像和表格以进行分析。Hide类别的攻击使用不同对象的覆盖,例如,将文本隐藏在图像下方。要检测这些覆盖,PDF检测器必须在PDF文档中提取对象的直角坐标。然后,可以使用这些坐标(左,下,右,上)确定对象在页面中的确切位置。可以通过使用坐标计算两个对象的碰撞来识别覆盖文本框的图像。创建PDF文档时,图像和文本框略有重叠并不罕见。因此,碰撞计算应以百分比计算覆盖值。值越低,对象所覆盖的内容就越少。对于Replace类别,无法合理地执行预防阶段。第一步“注入影子内容”与良性注入是无法区分的。例如,在创建PDF文档时插入多种字体并不是一种常见的恶意行为。对于Hide-and-Replace类别,这根本不适用。在此,由于影子文档路径包含在文档中,因此可以检测到第一步。认识到这一点的一种有前途的方法是将对Kids对象的引用交换为allPages对象。随后,将新创建的PDF文档的所有正确引用的对象与源文档进行比较。在未处理的PDF文档中,仅交换所包含页面的位置。假设PDF文档包含Hide-and-Replace类别的影子内容。在这种情况下,攻击者可以通过引用它在第二步中使其可见。因此,可以识别它。

B.检测

虽然在预防阶段应发现有效(隐藏)影子内容,但有效(可见)影子内容是检测阶段的重点。在实践中,这意味着攻击者创建了一个影子文件,签名者对其进行了签名。然后,攻击者使影子内容可见。为了检测Hide,Hide-and-Replace以及Replace 类的overlay变体,PDF-Detector可以比较当前文件签名之前的文件。这种比较可以从技术上通过删除第一个签名后的所有数据(即所有增量更新)来实现。在Hide攻击的第二步中,两个文件之间的差异会变得很明显,因为签名文件中没有对象,例如,一个隐藏的图像对象。相反,在Hide-and-Replace的第二步中,与未签名的文档相比,攻击者提供了不同的总体内容。在Font变体中检测替换攻击并不那么复杂。为此,在签名添加的FontFile对象后扫描更新并将它们的对象编号与已经包含的FontFiles比较就足够了。

C.实施细节

PDF-Detector使用Python库PDFMiner和pdfrw的组合。在实践中,由于pdfrw无法处理PDF中使用的Deflate压缩算法,因此通常会压缩PDF文档,这会使内容的分析更加复杂。因此,必要时,PDF检测器使用pypdftk和pdftk解压缩整个PDF文档。

命令行工具接受PDF文档作为输入,首先,它检查文档是否已经包含签名以选择正确的模式。如果未找到签名,则按前文所述,预防模式将启动并分析文档。如果文档已经签名,则检测模式将启动并按照前文中的说明检查文档中是否有任何可见的影子内容。如果未找到可见的影子内容,则另外在预防模式下开始分析以搜索隐藏的(不活动的)影子内容。

为了确保正确检测所有漏洞利用,使用了由PDF-Attacker实施生成的PDF文件。此处理过程确保可以同时进行预防和检测两个阶段的测试。能够基于这26个PDF文档验证并微调正确的分析,包括4个未签名的文档,7个无效的影子文档,7个已签名但无效的影子文档和8个有效的影子文档。

0x09 Shdow Attack:Beyond Signature Bypass

影子攻击的概念不仅限于对PDF签名的攻击。通过分析PDF规范和Adobe产品,观察到了令人兴奋的功能和配置可能性。

a)**PDF中的高特权动作:**PDF规范基本上定义了两种代码执行(CE)-PDF动作和JavaScript。动作的功能受到限制。URL调用是常见的操作示例,相比之下,JavaScript提供了巨大的功能集,包括控件结构(例如if,while)。出于安全原因,CE的两种类型均受PDF限制。例如,URL调用需要用户确认,并且对其他文档和文件的访问被阻止。在研究中,确定两个CE变体都可以特权模式运行。此模式允许执行对安全性要求较高的操作,而无需任何限制或用户同意。例如,特权JavaScript可以更改查看器应用程序菜单项的UI和功能。它可以读取其他打开的PDF选项卡的内容,甚至可以读取存储在机器上的文件的内容。它也可以在没有任何确认的情况下调用URL。通常,如果没有用户确认或在PDF查看器中进行配置更改,则不允许PDF执行特权JavaScript或操作。

使用数字签名的PDF(更具体的认证PDF)是一种例外。Adobe Products用户可以将使用特定证书签名的PDF配置为具有执行高特权操作的权限。默认情况下,对于大多数预配置的CA和所有手动信任的证书,此设置是禁用的。在Adobe产品中发现了一个例外:如果已知证书的私钥,则自动允许使用此特定证书签名的PDF文档执行高特权代码。

b)**攻击理念:**受影子攻击概念的启发,提出了一个问题,即攻击者是否可以在PDF中隐藏影子动作或影子JavaScript,以便在签名后执行。

为此,基于以下简化的攻击者模型创建新的攻击。假设签名者和受害者是同一实体。此外,攻击者无需在PDF文档签名后对其进行操作。注意攻击者执行的唯一步骤是创建PDF1并将高特权代码嵌入其中。PDF1签名后,高特权代码将在签名者的计算机上自动执行。

c)攻击说明: 该攻击的工作方式如下:

1)攻击者生成包含恶意,高特权代码的PDF,例如,使用特权JavaScript读取对其他PDFtab的访问权限。该代码存储在特定的执行事件上,该事件将在签名文档后触发,例如,在willCloseevent期间,或在签名后触发的任何其他事件(例如willSave,didSave)。

2)将PDF发送给签名者。他们在文件上签名。

3)签名后,受害者保存并关闭PDF。

4)关闭文档会触发willClose事件,并执行PDF中的恶意代码。

5)通常,不执行特权JavaScript,因为未授予特权JavaScript的特殊权限。但是,应用程序认为用于签名PDF的证书的私钥是已知的。这错误地说服了应用程序执行特权JavaScript –应用程序认为签名者打算执行脚本,因为他们对脚本进行了签名。此攻击仅限于Adobe产品,因为它们定义了有关CE的特殊策略,并且与未签名的PDF区别对待。

d)责任披露: 当最初向Adobe报告此问题时,他们的安全团队拒绝将本文发现归类为漏洞。他们假定正在处理文档的所有协作者都相互信任。经过简短的讨论,使他们相信情况并非总是如此。作为研究发现的直接结果,Adobe已在其2020年5月版中实施了安全控制措施。

0x0A Conclusion

PDF签名旨在保护PDF的完整性和真实性。与传统的数字签名本质上的用例仅在目标上应用一次签名相反,PDF签名处理更复杂的用例。PDF允许在没有使签名无效的情况下更新已签名的文档,但仅在特定情况下才可以。此外,PDF可以连续签名几次。在本文中展示了如何在不使签名无效的情况下滥用这种灵活性来替换PDF的整个内容,发现29个应用程序中有16个是易受攻击的,可以在当前的PDF规范中找到这种状态的原因:(1)它不精确地描述了如何执行签名验证。(2)它没有记录案例,也没有提出解决方案或指南,因此,开发人员必须自行解决这些问题。(3)PDF规范应重新考虑功能丰富性,这会削弱安全性。它应在密码保护方面应用更严格的限制和更有限的处理。

声明:本文来自安全学术圈,版权归作者所有。文章内容仅代表作者独立观点,不代表士冗科技立场,转载目的在于传递更多信息。如有侵权,请联系 service@expshell.com。