1 Trillion Dollar Refund – How To Spoof PDF Signatures——欺骗PDF签名


本文将从pdf基础开始讲起,介绍对pdf签名的三种攻击方式。攻击实例请见 PDF攻击实例-USF-ISA-SWA-Shadow Attack.7z

PDF结构

PDF本质上是一个ASCLL文件,我们用普通的文件浏览器打开一个pdf可以看到源代码

在这里插入图片描述

  • Header:是PDF的第一行,他解释了PDF所需要的解释器版本

  • Body:定义了PDF文件的内容,包括文本块、字体、图片和其他数据。Body的主体部分是对象object,
    如:2 0 obj Page。在所给的例子中,Body包含4个对象:Catalog,Pages,Page,Stream。其中

    1. 对象objects由三个部分组成在这里插入图片描述

      1. 首先是一个objects编号
      2. 接下来是一个版本编号,版本编号将会递增(当PDF被增量修改)
      3. 最后是固定字符串 obj
    2. Catalog是文件的根对象,定义了文件的结构,访问权限

    3. Catalog应用了Pages对象,后者包含了页数和Pages对象的引用信息

  • Xref table:包含了文件内所有PDF的位置信息(字节偏移量)

    1. Xref以两个整数a b开头 如:0 5,表示了obj是从0-4
    2. Xref中的每一个对象由3部分组成x,y,z
      1. x表示了相对于文件开头的偏移量
      2. y表示了版本
      3. z属于{n,f}中的一个,n表示in use,f表示free
  • Trailer:当一个PDF文件读入内存,将从尾到头进行处理。这就意味着,Trailer是PDF文档中首先处理的内容,它包含对Catalog和Xref table的引用

PDF签名工作原理

PDF签名依赖于PDF的一项特殊的机制,叫做增量存储(增量更新),允许修改PDF文件而不必改变之前的内容
在这里插入图片描述
原始的文档和这里的文档是一样的。通过对文档进行签名,利用增量存储来添加以下内容:一个新的Catalog,一个签名对象,一个新的Xref table引用了新对象,和一个新的Trailer包含了对旧的catalog或者新的catalog的引用,新的和旧的Xref的偏移量。

  • 新的Catalog:是对旧的Catalog的一个补充,增加了一个新的元素Perms,它定义了文档中更改的限制。并引用了5 0的签名对象
  • Signature对象:包含有哈希和签名文档的密码算法信息。它还有一个Contents参数,其包含一个16进制编码的PKCS7 blob,该blob存有证书信息,以及利用证书中公钥对应私钥创建签名值。ByteRange 参数指定了PDF文件的哪些字节用作签名计算的哈希输入,并定义了2个整数元组:
    1. a,b: 从字节偏移量a开始,后续的b个字节作为哈希运算的第一个输入。通常,a取值为0表示起始位置为文件头部,偏移量b则取值为PKCS#7 blob的起始位置。(即从下图中红框部分就没有算入加密)
    ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210413152246607.png
    2. c,d:通常,偏移量c为PKCS#7 blob的结束位置,而c d则指向PDF文件的最后一个字节的范围,用作哈希运算的第二个输入。即从下图红框部分之后开始加密
    在这里插入图片描述
    4. 位于b和c之间建议不纳入计算

攻击方式

通用签名伪造 USF

思想是控制签名中的原始数据信息,使阅读器程序在打开PDF文件时无法找到其验证所需要的所有数据信息。而且这种操作不会被认为是信息错误,而会被判定为有效。

例如:攻击者控制Signature中的Contents或ByteRange,可以直接删除签名,或者删除签名内容的起始位置信息

在这里插入图片描述
在这里插入图片描述

如果成功,视图应用程序(或联机验证逻辑)将显示一个面板,其中包含的PDF中的签名有效,并且属于特定的个人或实体


增量存储攻击 ISA

滥用了PDF中的合法功能,即允许PDF增加内容来更新(这项功能很有用处,例如存储PDF注释或者在编辑文件时添加新的页面。)

主要思想:利用上述功能来将PDF的内容更改为攻击想要的文本或是整个页面。即可以用更新文档的方式来修改整个文档的结构或内容。因为PDF文件中的数字签名可以精确的保护ByteRange中的文件内容,而由于增量存储ISA会将Body Update追加到文章尾部,不在ByteRange的保护范围内,以达到在签名有效的情况下修改PDF内容

PDF规范并没有禁止此操作,但签名验证应指明已签名的文档已经被篡改。
在这里插入图片描述

若攻击成功:将显示新内容(正文更新)并应用程序不会注意到文档已被修改或更新。


签名包装攻击 SWA

主要思想:迫使验证逻辑处理与应用逻辑不同的数据。

将原始签名使用的范围修改到文档其他位置,并在已分配的位置插入新的内容,以此来定位签名验证的逻辑。攻击的起点是控制ByteRange的值,允许签名使用的范围转移到文档不同的位置

在这里插入图片描述

具体攻击步骤:

  1. (可选)删除Contents中的零字节填充,以获取更多的修改空间
  2. 通过操控c的值来重新定义ByteRange [a b c* d],使其指向文件中处于不同位置的第二个签名部分
  3. 创建指向新对象的Xref Table,但是必须保证新的Xref Table的位置与之前的Xref Table的位置一致,该位置不可更改,因为它已被已经签名的Trailer所引用
  4. 攻击者注入恶意代码,可以放在Xref Table之前或者之后都可,如若不进行第一步,则只能放在之后
  5. 一些PDF阅读器要求在Xref Table值后插入Trailer才能正常读取
  6. 攻击者删除在字节偏移c*处、由c和d定义的已签名内容。值得注意的是,被操控的PDF文件并没有以%%EOF结尾。一些验证程序之所以会提示已签名文件被修改,是由于签名后面的%%EOF。为了绕过此需求,PDF文件无法正常关闭。但是,它仍然可以由其他阅读器处理。

在这里插入图片描述
SWA攻击的变种:
在这里插入图片描述

  1. 第一种变体:在第二步的时候将a=0,b=0,c=c*,d=b+d,即将原来签名的第一部分全部移到第二部分里了
  2. 第二种变体:同第一种变体的思想,但是把b改为5,因为每个pdf文件的0-5的偏移量存储的是pdf的版本信息,不会改变

综上的三种攻击中,SWA是最有效的,其次是ISA

pdf signature被攻击的主要原因

  1. 标准没有规定怎么去验证一个签名,也没有具体示例,所以每个开发者都是用的自己的验证逻辑,而不是最佳示范
  2. pdf浏览器的高容错性,让很多本是错误的文件,一样可以被正常显示

防止以上三种攻击手段的算法例子

INPUT: PDFBytes, SigObj
// ByteRange is mandatory and must be well−formated
byteRange = SigObj.getByteRange
// Preventing USF:
if(byteRange == null OR byteRange.isEmpty)
	return false
// Parse byteRange
if(byteRange.length!=4)
	return false
foreach x in byteRange {
	if x!=instanceof(int)
	return false
}
a, b, c, d = byteRange
// BytRange must cover start of file
if(a!=0)
	return false;
// Ensure that more than zero bytes are protected in hashpart1
if(b≤0)
	return false
// Ensure that sencond hashpart starts after first hashpart
if(c≤b)
return false
// Ensure that more than zero bytes are protected in hashpart2
if(d≤0)
return false
// Preventing ISA. ByteRange must cover the entire file.
if((c+d)!=PDFBytes.length)
return false;
// The pkcs7 blob starts at byte offset (a+b) and goes to offset c
pkcs7Blob = PDFBytes[(a+b):c]
// Preventing USF. Pkcs7Blob value is not allowed to be null or empty.
if(pkcs7Blob == null OR pkcs7Blob.isEmpty)
	return false
// pkcs7Blob must be a hexadecimal string [0−9,a−f,A−F]
if(pkcs7Blob contains other chars than [09,a−f,A−F])
return false
// Parse the PKCS#7 Blob
sig, cert = pkcs7.parse(pkcs7Blob)
// Select (a+b) bytes from input PDF begining at byte a=0, i.e. 0 ... a+b−1
hashpart1=PDFBytes[a:(a+b)]
// Select (c+d) bytes from input PDF begining at byte c, i.e. c ... c+d−1
hashpart2=PDFBytes[c:(c+d)]
// Verify signature34returnpkcs7.verify(sig, cert, hashpart1||hashpart2)

参考:

  • 1 Trillion Dollar Refund– How To Spoof PDF Signatures ——CCS ’19, November 11–15, 2019, London, United Kingdom
  • https://www.pdf-insecurity.org/index.html
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值