如何避免aCropalypse - The Trail of Bits博客
上周,关于CVE-2023-21036(绰号"aCropalypse")的新闻在Twitter和其他媒体上传播开来,我很快意识到我们的工具PolyTracker可以检测到这个底层缺陷。我将解释PolyTracker如何在不具备特定文件格式知识的情况下检测受漏洞影响的文件,哪些文件部分可以通过acropalypse.app进行恢复,以及谷歌和微软如何通过使用我们的工具来捕获这个漏洞。
巧合的是,我和同事Evan Sultanik、Marek Surovič合写了一篇论文,描述了这类漏洞,定义了一种新颖的检测方法,并介绍了我们的实现和工具。该论文将出现在今年IEEE安全与隐私研讨会上的语言理论安全(LangSec)研讨会上。
使用PolyTracker检测漏洞
我们使用PolyTracker来检测图像解析器libpng。(任何解析器都可以,不仅仅是aCropalyptic解析器。)PolyTracker检测告诉我们输入文件的哪些部分被解析器完全忽略,我们称之为盲区。盲区几乎总是文件格式设计缺陷、输入文件畸形和/或解析器错误的指标。正常图像应该几乎没有盲区,但通过libpng解析畸形的aCropalyptic图像会在大盲区中显示裁剪的数据。
如果易受攻击的产品使用了PolyTracker进行检测并测试了输出的盲区,aCropalypse漏洞本可以被发现。
|
|
理解aCropalypse
根据这条推文,可以从裁剪或编辑的截图中恢复原始图像的部分内容。简而言之,当使用谷歌Pixel内置截图编辑工具Markup裁剪或调整图像大小时,它会覆盖原始图像,但只覆盖到新图像结束的偏移量。该偏移量之后原始图像的任何数据都保留在文件中。David Buchanan设计了一种算法来恢复文件中仍保留的原始图像数据;您可以在他的博客上阅读更多详细信息。
最近,Chris Blume发现了Windows截图工具的类似漏洞。我们在此描述的Markup工具方法可以用于Windows截图工具生成的图像。
PolyTracker有一个我们在几年前引入的功能,称为盲区检测。我们将盲区定义为输入字节集,其数据流从不影响导致输出的控制流或输出本身。或者,用外行的话说,未使用的文件数据可以更改为任何内容而不影响输出。根据定义,aCropalypse图像的裁剪区域是盲区,因此PolyTracker应该能够检测到它们!
跟踪输入字节和检测真实世界输入(如PNG图像或PDF文档)的盲区的一个挑战是污染爆炸。PNG文件格式包含压缩的图像数据块。压缩特别容易导致污染爆炸,因为输入字节以多种方式组合产生输出字节。PolyTracker独特的污染结构表示允许我们跟踪2^31个独特的污染标签,这对于分析图像数据zlib解压缩期间传播的污染是必要的。
处理时aCropalyptic文件会有盲区
要理解为什么aCropalypse漏洞会产生盲区,我们需要将我们对漏洞的了解与盲区的描述结合起来。当使用PNG解析器解析PNG文件时,解析器将解释头部数据并根据PNG规范使用块。特别是,它将在类型为IEND的块处结束,即使该块不在文件的实际末尾。
我们使用PolyTracker来检测一个工具(来自libpng项目的pngtest),该工具读取PNG文件并将其再次写入磁盘。这将产生一个额外的输出文件,称为polytracker.tdag,它捕获来自运行时跟踪的数据流。使用该文件和PolyTracker的盲区检测功能,我们可以枚举不影响结果图像的输入字节。请记住,这些是输入文件的字节,既不影响任何控制流,也不(可能与其他数据混合)出现在输出文件中。对于给定的解析器,它们在解释格式时没有实际意义。
演示!
使用PolyTracker检测的pngtest应用程序,我们再次加载、解析并将下图存储到磁盘。在此处理过程中,我们通过PNG和zlib处理跟踪所有输入字节,直到它们以某种形式到达输出文件。
我们使用包含PolyTracker检测的pngtest应用程序的Docker镜像。
|
|
re3eot.png图像的大小为1044358字节,而out_re3eot.png为697,182字节。尽管这表明大小显著减少,但此时我们无法确定原因;例如,可能是不同压缩设置的结果。
接下来,让我们从这个过程中找到盲区:
|
|
我们感兴趣的输出是: re3eot.png,697120,1044358
这告诉我们,从偏移量697,120到文件末尾的数据在生成输出图像时被忽略。我们找到了一个盲区!额外的347,238字节未使用数据可能来自原始图像——这是aCropalypse漏洞的迹象。让我们使用acropalypse.app网页看看是否可以恢复它。
这表明该文件实际上是由易受攻击的应用程序生成的。此时,我们知道图像末尾包含来自原始图像的数据,因为这是漏洞的核心。我们还知道该数据的确切位置和范围(根据盲区的起始偏移量和大小)。为了确认数据实际上是盲区,让我们手动裁剪原始图像并重新进行pngtest操作,以确保结果文件实际上相等。首先,让我们只复制不是盲区的部分——用于生成输出图像的数据。
|
|
接下来,让我们再次运行pngtest应用程序:
|
|
如果我们的假设——只有前697,120字节用于生成输出图像——是正确的,我们应该有两个相同的输出文件,尽管从manually_cropped_re3eot.png输入文件中删除了347,238字节。
|
|
成功!为了确保手动裁剪的文件仍然不受漏洞影响,让我们使用网页尝试重建文件中的其他图像数据。此尝试未成功,因为我们已经删除了原始图像内容。(是的,我已经检查了裁剪截图的盲区😁)。
为了更好地理解为什么盲区从特定偏移量开始,我们需要检查原始图像的结构。
PolyFile来救援
PolyTracker有一个姊妹工具:PolyFile,一个纯Python的libmagic清洁室实现,具有来自Kaitai结构的检测解析和交互式十六进制查看器。我们将使用PolyFile生成文件结构的HTML渲染的能力来理解为什么文件处理在文件结束之前结束。
首先,我们使用以下命令生成表示文件格式的HTML文件:
|
|
当我们在浏览器中打开re3eot.html文件时,我们将看到文件的初始表示。
通过重复展开左侧的文件结构,我们最终到达最后一个块。
如上图所示,在解释PNG格式时,最后一个块的类型为IEND。该块之后是来自原始文件的剩余数据。注意多余数据从偏移量0xaa320开始——即697,120,与识别的盲区偏移量完全相同。如果您一直滚动到最后,您会发现一个额外的IEND结构(来自原始图像),但这不被解释为PNG文件的有效部分。
不止于此
几乎不了解PNG文件格式,我们能够使用PolyTracker检测现有的PNG处理应用程序,不仅检测具有盲区的文件,还检测它们的精确位置和范围。
PolyTracker可以检测文件中任何位置的盲区,而不仅仅是在末尾。尽管我们分析了PNG文件,但PolyTracker不限于特定格式。我们之前使用MμPDF分析了PDF到PostScript的转换。相同的技术适用于任何执行加载/存储或反序列化/序列化操作的应用程序。为了进一步增加我们对格式和漏洞影响的理解,我们使用PolyFile检查文件结构。
这些只是我们工具的几个用例,还有很多其他用例!我们鼓励您自己尝试我们的PolyTracker和PolyFile工具,看看它们如何帮助您识别意外处理并防止应用程序中出现类似aCropalypse的漏洞。
致谢
这项研究部分由国防高级研究计划局(DARPA)SafeDocs计划支持,作为Galois的子承包商,合同号为HR0011-19-C-0073。所表达的观点、意见和发现是作者的观点、意见和发现,不应解释为代表国防部或美国政府的官方观点或政策。
非常感谢Evan Sultanik、Marek Surovič、Michael Brown、Trent Brunson、Filipe Casal、Peter Goodman、Kelly Kaoudis、Lisa Overall、Stefan Nagy、Bill Harris、Nichole Schimanski、Mark Tullsen、Walt Woods、Peter Wyatt、Ange Albertini和Sergey Bratus对方法和工具的宝贵反馈。感谢Ange Albertini建议使用"angles morts"(法语中的"盲区")来命名这个概念,以及Will Tan分享受漏洞影响的文件。特别感谢PolyTracker的原始创建者Carson Harmon,他的想法和讨论孕育了这项研究,以及Evan Sultanik帮助撰写这篇博客文章。