如何防止 Apache PDFBox 中的通用签名伪造 (USF)、增量保存攻击 (ISA)、签名包装 (SWA)
Posted
技术标签:
【中文标题】如何防止 Apache PDFBox 中的通用签名伪造 (USF)、增量保存攻击 (ISA)、签名包装 (SWA)【英文标题】:How can i prevent Universal Signature Forgery (USF) , Incremental Saving Attack (ISA), Signature Wrapping (SWA) in Apache PDFBox 【发布时间】:2019-07-29 15:54:45 【问题描述】:目前我正在使用 apache pdfbox 创建数字和电子签名。 最近我开始了解数字和电子签名中的漏洞,例如通用签名伪造 (USF)、增量保存攻击 (ISA) 和签名包装 (SWA)。 PDFBox 是否会自动处理此问题,还是我们需要在代码中额外执行以处理此问题
【问题讨论】:
对于不了解这些条款的任何人,请查看PDF insecurity site。 攻击类“签名排除”(又名USF)中包含的攻击的基本思想是混淆签名验证逻辑和信息显示逻辑PDF 处理应用程序。 因此,PDFBox 本身可能不会返回肯定的验证结果,但它可能会例如返回一个您(作为 PDFBox 验证代码的调用者)没有预料到的异常,因此,处理不充分会导致验证结果的错误或误导性呈现。 阅读论文在我的待办事项清单上……我确实尝试了许多漏洞利用但从未得到积极的结果,如果其中包括“签名覆盖整个文档”检查。我还打算做的是在打开 PDF 文件时删除签名检查的宽松模式。 您的问题有点“错误”,因为这些攻击与签名创建无关,仅与签名检查有关。 啊,ShowSignature
做了一定的验证,输出验证结果。
【参考方案1】:
关于攻击本身
首先,提到的攻击是在 2019 年 2 月公开发表的硕士论文中开发的("Security of PDF Signatures" 由波鸿鲁尔大学的 Karsten Meyer zu Selhausen 撰写)。派生的 "Vulnerability Report" 的预发布已在 2018 年 11 月与多家信息安全相关组织共享和讨论,因此论文中测试的一些 PDF 签名验证器同时已修复,以正确显示签名有效性违规或限制。您可以在the PDF insecurity site 上找到概述。
阅读论文并查看示例我得到的印象是作者和他的顾问们还没有很长时间处理 PDF,至少没有深入。造成这种印象的两个例子:
论文明确基于 2006 年出版的 PDF 参考 1.7,它知道 PDF 已于 2008 年成为 ISO 标准(ISO 32000-1),同时在 2017 年已更新(ISO 32000-2) .
效果是它的某些方面已经过时了。例如
它描述为未来工作“针对对象摘要的攻击”的主题,但对象摘要尚未包含在 2008 年的 ISO 32000-1 标准中,它们在发布时已经过时了 10 多年论文。 此外,从论文中得出的“漏洞报告”包含改进验证的建议,但作为缺点提到它需要更改将 ByteRange 定义为可选的 PDF 规范参数...但自 2008 年以来在 ISO 32000-1 中一直需要它(至少对于此处感兴趣的签名)!这些操作(主要是在 USF 攻击的背景下)是在没有充分尊重生成的 PDF 的有效性的情况下完成的。
可见的效果是例如在 Adobe Reader 中打开测试 PDF 后,再次关闭它会导致查看器询问是否应该保存 更改,即查看器必须对文件进行修复以使其对查看器以正确显示它。一方面,这种行为可以让用户对操纵保持警惕,另一方面,这些修复本身已经可以使签名失效,从而导致可能是好的攻击失败。
对于某些攻击场景,无效的 PDF 是可以的,甚至可能是有效的,但在许多场景中它们是不必要的,应该避免。
尽管如此,这些攻击很有趣,尤其是它们让我想知道那些对 PDF 有更深入了解的攻击者可能会设计什么攻击...
作为基于 PDFBox 的签名者防止即将发生的攻击
OP 正在“使用 apache pdfbox 创建数字和电子签名”,对于上述攻击,想知道他作为签名创建者可以做些什么来防止攻击。
实际上,签名创建者几乎无法阻止攻击,主要是签名验证器的工作来识别操纵。
不过,他可以通过一种方式提供帮助:签名包装攻击的一些变体使用签名内容中尾随字符串 00 字节的区域;所以他可以通过使字符串尽可能短来帮助防止一些攻击。不幸的是,有许多签名设置,其中很难预测要嵌入此处的签名容器的大小,因此难以避免一定数量的尾随 00 字节。
此外,您可以使您的签名认证签名为“不允许更改” - 以这种方式尊重认证级别的验证器可以更轻松地识别和报告任何不允许的更改。不过,如果在长期验证扩展的上下文中使用,这可能会有点障碍。
将攻击正确识别为基于 PDFBox 的验证器
首先,PDFBox 不提供随时可用的实用程序来检查增量更新中所做的更改类型。因此,除非您自己实现,否则您的验证者只能对覆盖整个文档的签名说他们签署文件显示的内容。对于以前的签名,它只能说各自的签名签署了文档的某个较早版本,但不能说该版本是否与当前版本相对应。
基于 PDFBox 的验证器(对修订比较没有很大的贡献)在其报告中对不覆盖整个文档的签名必须表明这一事实,并要求用户手动确定修订之间的更改。
针对来自 PDF 安全站点 (here) 的示例攻击文件运行 PDFBox 签名验证示例 ShowSignature
,得到以下结果:
NoSuchAlgorithmException
。
通常(大多数 USF 文件)有一个 NullPointerException
。
在一个 USF 案例中,有一个 ClassCastException
。
在一个 USF 案例中,有一个 CMSException
。
(SecurityThesisValidation 测试的结果)
因此,只要基于 PDFBox 的验证器在适用的情况下正确输出“签名不覆盖整个文档”警告并在出现任意异常时输出“失败”或“未知”,它就不会成为当前的牺牲品攻击文件。
正如@Tilman 在对该问题的评论中所说,在加载 PDF 进行验证时停用宽松模式可能是一个好主意。这将在任何验证例程被愚弄之前捕获大多数 ISA 和一些 USF 攻击......
但请注意:如上所述,论文和示例文件显示了一些缺陷。因此,PDFBox 有可能受到改进版本的攻击。特别是签名包装方法看起来很有希望,因为 PDFBox 仅使用 Contents 字符串,并且不将其与字节范围间隙的内容进行比较。
【讨论】:
"... 不将其与字节范围间隙的内容进行比较" - 这不是我们在这里所做的吗?byteRange[1] + contentLen != byteRange[2]
@Tilman 哦,是的,你是对的,这至少是一个长度检查。我更多地考虑检查间隙是否包含 equal byte-by-byte 到 Content 值的十六进制字符串。啊,欺骗您的一种方法是将 Content 的十六进制字符串值替换为具有相同内容的文字字符串。通常,该文字字符串将比contentLen
计算中假定的十六进制字符串短。因此,即使保持字节范围间隙长度等于 Content 值的十六进制字符串表示的长度,攻击者也会有一些恶作剧空间。
有趣的想法。我也在考虑将 signedData.getEncoded() 与内容进行比较,并检查其余部分是否为 00,但您提到的更好。
@Tilman 顺便说一句,使用文字字符串进行签名并非完全闻所未闻:Adobe Acrobat 使用权签名曾经如此编码...以上是关于如何防止 Apache PDFBox 中的通用签名伪造 (USF)、增量保存攻击 (ISA)、签名包装 (SWA)的主要内容,如果未能解决你的问题,请参考以下文章