高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?

608次阅读
没有评论

近日,图像处理库libwebp爆出高危漏洞,该库在网页、软件、App、在线服务等各个方面被广泛的应用于图片的解析和处理,是极具影响的网络与软件基础组件。

高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?

借助于该漏洞,攻击者可以实现远程代码执行(rce),在受影响的目标上执行恶意代码。并且,苹果公司声称已经有黑客利用该漏洞对其相关产品实施了攻击,包括苹果和谷歌在内的知名厂商均发布了紧急安全更新对其进行了修复。

阿里安全对该漏洞的原理进行了详细的分析,希望能够对大家认识和防御该漏洞提供帮助。此外,建议普通用户将所使用的系统、软件、App等更新至最新版,并保持持续更新~

本文亮点


🎈该漏洞的原理🎈PoC分析
高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?

🌟漏洞基本信息

威胁分类:供应链基础组件漏洞

影响组件:libwebp

影响版本:1.3.2之前

漏洞类型:堆缓冲区溢出

漏洞编号:CVE-2023-4863(CVE-2023-41064)

CVSS评分:8.8

这个漏洞最早追溯到2023年9月7日Apple发布的一则紧急安全更新,其针对ImageIO组件修复了一个缓冲区溢出漏洞CVE-2023-41064,并且声称“这个问题可能已经遭到频繁利用;Apple已知晓这一报告”。后续Google于9月11号发布了Chrome的安全更新,修复了CVE-2023-4863。Chrome也提到这个漏洞是有在野利用的,并且漏洞报告人为苹果安全工程与架构团队(Apple Security Engineering and Architecture,SEAR)和加拿大多伦多大学Citizen Lab团队,因此实际上其与CVE-2023-41064为同一个漏洞。
事实上,Citizen Lab团队在9月7号发布的文章中提到他们发现了“NSO Group”使用的0-click iMessage在野利用链,而CVE-2023-41064是其中一个0day漏洞,存在于ImageIO组件的webp解析逻辑中,也就是libwebp的CVE-2023-4863。
虽然漏洞更新时发布了Patch,但由于webp格式的复杂性,仅从diff进行补丁分析构造PoC的难度仍较大。不过,在9月21日,前Google Project Zero创始人之一Ben Hawkes(@benhawkes)发布博客分享了他对于CVE-2023-4863的一些分析和复现过程,同时@mistymntncop发布了PoC。
从以上信息中可以看出,由于libwebp广泛应用于在线图片解析中,该漏洞具有危害大、影响面广的特点。下面让我们深入地分析下这个漏洞的原理。
高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?

🧡 概念介绍

此漏洞位于webp格式的无损格式支持中,也叫做VP8L。简单来说,就是webp无损格式想办法把ARGB图片(一个包含alpha透明度,red红,green绿,blue蓝的像素值的二位数组)的像素进行压缩,减少图片大小,但保证在存储和恢复像素值时保持不变,从而实现无损精度。
核心算法是用顺序数据压缩(LZ77),范式哈夫曼编码和颜色缓存(Color Cache)来压缩批量数据。其中LZ77是一种基于字典的滑动窗口压缩算法,会将重复出现的内容替换成更短的<长度,距离>对。
长度是重复内容所占的字节,距离是后文中重复出现词语首字节,与前文中的重复词语的字节差。而范式哈夫曼编码则是经典的传统哈夫曼编码的延伸:哈夫曼编码用于将更频繁出现的比特流用更短的长度编码,保证总长度最小,范式哈夫曼编码则解决了哈夫曼编码表占用空间过大的问题,仅保留可逆编码长度信息,按照既定规则反推出编码表,后面会展开介绍。颜色缓存则是一个采用哈希地址的小型数组,用于存储最近用过的颜色,以便以更短的编码找回这些颜色。

🧡 PoC分析与漏洞原理分析


我们直接从公开的PoC入手分析,同时阅读libwebp中解码的相关代码。@mistymntncop的代码仓库中包含一个生成PoC图片文件的harness,其主要逻辑位于craft_webp函数中。
高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?
首先,libwebp中负责VP8L解码的主要逻辑位于/src/dec/vp8l_dec.c中,DecodeImageStream为解码图片流的入口函数。
高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?
craft_webp在做了一些基础的初始化操作后,在(1)处调用write_header函数写VP8L格式的文件头,
高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?
这些比特流的含义分别是:1)1字节签名 0x2f。2)指定图片的宽度和高度,都将将解码为14位整数。3)当照片中所有Alpha值都为255时,设置为0,否则has_alpha设置为1。这一项对解码没有实质影响。4)版本号,必须设置为0。所以这里write_header(bw, 1, 1, false)写的是一个1*1的图片。
然后(2)处写入1bit的0,目的是跳过转换(Transformer),因此此漏洞与转换无关。分析DecodeImageStream函数:当VP8LReadBits返回1时进入ReadTransform,所以这里设置为0,得以跳过ReadTransform函数。
高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?
(3)处跳过颜色缓存,逻辑与(2)类似。
高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?
(4)处跟PoC中的原始注释说的类似,就是为了跳过元哈夫曼编码部分。
高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?
然后下面就到了这个漏洞原理最核心的地方了。(5)处的code_lengths_counts是一个5*16的二维数组,每一行表示一个范式霍夫曼树的符号编码长度数组。前面说过,范式霍夫曼算法只记录每个符号的编码长度,根据既定规则从编码长度推导出真正的编码,因此不需要记录庞大的编码表。这里我们先简单了解一下算法的规则:高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?
举个例子,如果我们当前得到的标准霍夫曼编码是:00、01、11、100、101,所以我们可以记录符号编码长度数组为{0,0,3,2}。根据规则(1),00 : 00,也就是第一个编码值必须全为0,长度必须为2。根据规则(2),01:00+1 -> 01根据规则(2),11: 01+1 -> 10根据规则(3),100 :10+1 << 1 -> 110根据规则(2),101 :110+1 -> 111所以范式霍夫曼编码即为00、01、10、110、111。随后我可以便可以用上述编码表去进行解码和还原。回到webp无损格式中来,为什么这里的数组是5*16呢?引用官方文档中的描述,对于任何给定的像素(x, y),都有一组与其关联的五个哈夫曼编码,按比特流顺序这些这些编码分别是:

  • 编码1:用于绿色通道、向后引用长度和颜色缓存
  • 编码2:用于红色通道
  • 编码3:用于蓝色通道
  • 编码4:用于Alpha通道
  • 编码5:用于向后引用距离。

所以libwebp中分别用五个数组来存储这五组编码的编码长度,作为像素压缩和还原的关键,也就是(5)处构造的二维数组。每组编码的最长编码长度硬编码设置为15,所以数组宽度为16。
高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?
另外,libwebp还引入了一个二级表的概念,将长度小于N的叫做根表(一级表,root_table),长度大于等于N为叫做二级表。对于这五组编码对应的霍夫曼表,N设置为8,代码如下:
高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?
(6)处设置每张表的符号总数为{280, 256, 256, 256, 40},其实这里就是说,code_lengths_counts处每一行的符号总和分别为280.....40,这里已经是格式中规定的上限了,这样设置主要为了是比较容易触发crash,又保证符合格式规范!格式规范如下:高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?
libwebp中对应的代码如下:
高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?
两者是一致的。
由于设定了最长编码长度、每张表的最大符号数量和最大一级表长度,像@benhawkes老哥所说,libwebp使用某个叫做“enough”的工具计算了最大可能哈夫曼树查询表的大小,然后根据这个硬编码的大小用WebPSafeMalloc函数预分配了缓冲区。 
高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?
如注释中所说,FIXED_TABLE_SIZE就是5个编码表中后四个的size,即用于红色通道,用于蓝色通道,用于Alpha通道和用于向后引用距离的size都是常数值(630,630,630,410)。而用于第一个编码表的size则根据颜色缓存的size不同而变化,但也是一个常数值(PoC中为654)。
更通俗的解释就是,符号数量为{280, 256, 256, 256, 40}的编码表,通过enough工具生成的预分配霍夫曼表大小即为654+630+630+630+630+410=2954。
问题在于,enough工具,包括libwebp默认图片中保存的范式霍夫曼编码表是合理的,但是范式霍夫曼编码表数据是来自不受信源的,可以由攻击者任意构造,且编码器不会对这些数据进行任何有效性检查。因此在符合{280, 256, 256, 256, 40}的符号数量的前提下,如果我们能构造出令霍夫曼编码表大小超过2954的符号编码长度数组,就可以越界写入堆缓冲区。
目前网上的分析报告大多分析到这个粒度,包括@benhawkes本人一开始也在尝试用黑盒的方法触发缓冲区溢出,因为这个漏洞在我实际分析调试后发现复杂性确实很高。但下面的部分我还是尝试讲解一下自己对这个漏洞内核的理解。
首先在ReadHuffmanCodes函数中会遍历每个表分别调用ReadHuffmanCode函数,传入对应的符号数量alphabet_size,符号编码长度数组code_lengths和指向预分配的哈夫曼表的指针huffman_table。这里huffman_table最早是指向之前malloc分配的缓冲区的,解码完一个表后,会将ReadhuffmanCode的返回值作为size偏移,令huffman_table指针移动。
高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?
然后看ReadHuffmanCode函数,首先if(simple_code)对应的分支判断是为了读取霍夫曼表编码长度数组的编码,这里其实与漏洞无关,PoC中隐去了符号编码长度数组编码的逻辑,我们也无需关心。
高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?
对应的格式规范如下图👇
高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?
然后ReadHuffmanCode就会调用VP8LBuildHuffmanTable函数,并将其返回值作为size返回到ReadHuffmanCodes。这里的调用传入了指向霍夫曼表的指针,N的大小(8),符号编码长度数组code_lengths和符号数量alphabet_size。
VP8LBuildHuffmanTable中主要逻辑是根据符号数量判断是否需要在堆上分配sorted数组,一般走的是用栈分配的分支。最终进入BuildHuffmanTable函数。
高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?
BuildHuffmanTable首先做了一些初始化操作和assert校验,注意这里的count实际上就是PoC中我们布置的code_length_counts,是通过遍历code_lengths计算出来的。
高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?
如果所有的编码都为0,也就是count[0]=符号长度,就直接退出。然后会按照编码长度序和符号序,对所有符号进行排序,存储到sorted数组。
高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?
对于只有一个值的特殊情况特殊处理,注意这里是用ReplicateValue函数写入的,后面写入一级表、二级表的时候也是用这个函数。
高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?
我们先来看一下ReplicateValue函数,是从table指针指向的下标开始,写到end的位置,以step为步长进行写入。
高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?
然后就是对一级表的写入操作。这里table_size是1<<8=256,也就是每次都是从key开始写到256处,步长分别为2、4、8、16、32、64、128、256。而key是什么呢?这就是这个漏洞最核心的点之一。根据147行的注释,是"reversed prefix code",也就是倒序的哈夫曼编码。
高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?
GetNextKey的算法如下👇
高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?
我用Python脚本还原了一份GetNextKey的逻辑,以前述{0,0,3,2}的霍夫曼树为例测试:
高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险? 二者相符。
Python脚本如下:高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?
因此我们知道一级表最多写到256的位置,从每个key对应的下标开始写。接下来对于编码长度大于8的case,代码会开始写入到二级表,也就是真正溢出的位置!
mask设置为0xff,也就是低8位编码;low初始化为0xffffffff。
高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?
从9~15开始,也是每次增加1编码长度。算法会记录key的低8位(由于是反向的实际上是霍夫曼编码的高8位),当新编码的低位与上一个编码不一致时,会用NextTableBitSize计算下一个二级表的size,然后将size增加到total_size,同时从低8位开始写入一级表,作为索引。注意一级表占用了256,所以total_size是从256开始增加的。
NextTableBitSize是根据(编码长度-8)位二进制数能否容纳对应长度的编码决定的,如果不能的话就要增加表的大小。
对于每个符号,会从每个编码高8位(key >> root_bits)对应的位置开始写,写入直到table_size。所以要溢出的话,关键就是key和table_size。
在PoC中,我们首先构造了前四个编码长度数组是合规的,并且成功填满了预分配的霍夫曼表(这一点通过enough工具可以做到)。然后对于最后一个符号大小为40的表,我们期望溢出其大小为410的缓冲区,最终便可以触发越界写。
对应的编码长度数组是{0, 1, 1, 1, 1, 1, 0, 0, 0, 11, 5,  1, 10, 4, 2, 2}。单看起来还是有点抽象,我们再次写Python脚本还原解码逻辑:高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?
运行结果如下:
高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?
可以看出,当编码长度为12时,由于构造的编码长度数组中,大于等于12的符号还有很多,导致NextTableBitSize返回0x7,即分配了2^7=128,因此total_size也超过了410来到414。
通过在Ubuntu 20.04上编译PoC和libwebp,调试可知,在溢出之前,0x555555626590处的大小0x2e30( 2956 * 4)的堆块是我们要写入的堆块,下一个堆块size为0x1cc50。
高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?
在溢出之后,溢出到了下一个堆块的前0x10字节的元数据和前0x8个数据字节,这修改了下一个堆块的size字段,从而在释放堆块时触发libc中的检查报错,使得进程崩溃!
高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?
事实上,通过调整第五个霍夫曼表的编码长度数组,我们可以构造更长的total_size,如{0,1,1,1,1,1,0,0,0,11,1,9,1,1,1,11},利用之前编写的脚本运行可知,total_size达到530,远超预分配的410字节。当然并不是每个字节都会被顺序复写,所以真正编写利用代码的时候需要相当的精心构造与设计
高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?
高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?

由上述分析可知,该漏洞可以溢出预分配的堆缓冲区,执行越界写操作。但是控制所写内容和写入偏移比较困难,不是连续顺序可控的写入,而需要一定的计算和trick。
综上所述,漏洞是可利用的,但门槛很高。鉴于在野攻击利用该漏洞实现了iOS iMessage的RCE,说明漏洞的上限不可忽视,但实现完整攻击所需要的编排可能需要很有经验的攻击者消耗较长时间来实现。建议开发者及时更新补丁,修复漏洞。

📺直播预告

  • 10月31日19:00《追AI的人》第31期

高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?

  • 11月1日19:00《追AI的人》第32期

高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?
📌往期推荐🌟人工智能治理与可持续发展实践白皮书》 精华大图集锦版 | 如何维护电商平台信息真实和竞争公平...👉点击查收白皮书全书连载
🔥《追AI的人》系列直播教你掌握互联网的“流量密码”  | 如何避免ChatGPT被滥用...👉点击查收过往30期直播的全部文字回放
🎈算法治理制度》系列丛书内容和电商领域推荐算法的应用与治理差异“大数据杀熟” 的背后...👉点击阅读更多算法治理干货
📚《AI治理必修》月刊为什么现在的LLM都是Decoder-only的架构? | 大脑视觉信号被Stable Diffusion复现成图像!"AI读脑术"来了...👉点击阅读往期40刊月刊全文
📺 AI治理科普短视频流量为王的时代,教你如何“破圈”创作 | 3分钟Get多模态是什么? 信息茧和马太效应是什么...👉点击观看往期21期精彩视频

👇AAIG课代表,获取最新动态就找她高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?

 关注公众号发现更多干货❤️

高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?
高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?有启发点在看喔👇高危漏洞揭秘!阿里安全深度解析漏洞原理以及如何应对风险?

 

Read More 

正文完
可以使用微信扫码关注公众号(ID:xzluomor)
post-qrcode
 
评论(没有评论)
Generated by Feedzy