新西兰服务器

如何实现微软“照片”应用Raw 格式图像编码器漏洞 CVE-2021-24091的技术分析


如何实现微软“照片”应用Raw 格式图像编码器漏洞 CVE-2021-24091的技术分析

发布时间:2021-12-29 19:13:01 来源:高防服务器网 阅读:66 作者:柒染 栏目:安全技术

如何实现微软“照片”应用Raw 格式图像编码器漏洞 CVE-2021-24091的技术分析,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

前言

2020年12月和2021年2月,微软两次针对“照片”应用的Raw格式图像编码器发布安全更新,其中2月9日修复的是CVE-2021-24091。笔者从事文件格式方面的安全研究工作,找到研究人员提供的poc 后,对该漏洞进行了漏洞验证和分析。

根据MSRC 和漏洞发现者公开的信息,该漏洞存在于Windows Imaging Component解码Olympus E300 相机拍摄的原始图像的相关函数中。由于互联网并没有过多公开资源介绍 E300 RAW 格式(笔者仅找到一份公开资料,见https://myolympus.org/E300/#RAW),所以本文将从漏洞产生机制的角度,分析漏洞产生的原因。

0x00 漏洞验证

1、在Win10 1903 x64系统上,使用gflags工具为图片app开启页堆,双击图片文件打开(图片默认应用为照片App)。一段时间后,App退出进程。

2、使用Windbg附加照片App(Windbg 调试UWP方法详见微软文档),敲击g运行程序。一段时间后,进程崩溃。如下图所示:

0x01 漏洞分析

使用ida pro 加载崩溃的dll,可以确认崩溃发生在一个将数据写入缓冲区的循环之中。

通过这段代码,可初步大致判断循环体条件语句导致循环次数过多,造成越界写入。函数部分变量的初始化如下:

结合函数开始时局部变量的初始化和变量交叉引用的情况来看,可以得出:

1、代码通过读取某个类型对象的成员值,并加以运算,计算结果即为需要申请的缓冲区的大小;

2、缓冲区分为两部分,一部分为size 为*(this+12320*4) * 2的数据块(chunk2)另一部分数据块(chunk1)的大小为*(this+0x12320*4) * 16 / 10个字节。

3、执行初始化后,代码首先执行一个for循环,在这个循环体的内部执行另一个for循环,向chunk2内写入数据。

所以,这段代码的伪代码如下:

chunk2_size = this->mem_12320;chunk1_size = chunk2_size * 16 / 10;char * data = (char *)malloc(chunk1_size + 2 * chunk2_size);for (char *i = data+chunk1_size; v12 < this->mem_12325; a5 = v12){…expresions;…for (char *pdata = data, char *j = i; j < chunk+chunk1_size+2*chunk2_size; pdata += 3, j += 4){if ((pdata – data) %15) pdata++;*(word *)j = pdata[1] << 8 | pdata[0];      //写入两个字节*(word *)(j+1) = pdata[2] << 4 | pdata[1] >> 4; //写入两个字节 }…expressions;…}

按照上面的伪代码,每次循环都写入四个字节,循环次数应该是(chunk2_size * 2 / 4)向上取整的值。在第一个for循环中,当 i = &data[chunk1_size],即从第二个chunk头部开始循环写入字节时,如果chunk2_size为奇数,循环次数 * 4 将大于chunk2_size。也就是说,最后一次循环中,写入后两个字节时,将造成越界,产生访问违例。

0x02 漏洞调试

使用windbg 附加App进程,并在崩溃函数设置断点:

bu WindowsCodecsRaw!COlympusE300LoadRaw::olympus_e300_load_raw

图片App 加载poc 文件时,获取的chunk2_size为0xd79,是一个奇数。

通过上文的伪代码可得:

chunk1_size = 0x158e

data 指向的内存区域是一个大小为0x3080的缓冲区。

代码执行到第二个for循环时,需要写入数据的指针存放在r15中,即为chunk2 缓冲区的起始地址(r15  ==  data + chunk1_size):

所以,在这种情况下,循环次数应为⌈ (0xd79 * 2 / 4) ⌉,即为1725 次。而缓冲区只有2 * chunk2_size, 共6898个字节,不能支持1725*4 = 6900个字节的写入。由此可知,最后一次循环将产生两个字节的越界。至此,漏洞分析完毕。

循环次数记录如下:共命中725次,与分析无误。

0x03 关于这段代码的来源

该漏洞的发现者提到:通过函数名查找,这段代码与LibRaw Lite库的同名函数有较大的相似性,但是这个库目前已经停止维护和更新了,源代码下载地址失效,所以笔者在github上找到了类似的代码片段。(https://github.com/coolshou/DIR-850L_A1/blob/92b64054ac75795429b9a6678baef5b3e69dfc10/progs.gpl/image_tools/netpbm-10.35.81/converter/other/cameratopam/camera.c)

对比可知,这段代码与漏洞函数在实现上基本一致,所以微软的代码应该是在此基础上重新实现了一遍。

因此,基于代码供应链安全的考量,建议使用LibRaw Lite 库函数的代码,由相关人员自行更新补丁。

0x04 微软代码补丁

微软官方在2月9日推出的补丁内容如下:

这个补丁比较简单粗暴,即:复制第二个像素(第二次写入双字节)时,判断指针是否指向缓冲区末端。

看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注高防服务器网行业资讯频道,感谢您对高防服务器网的支持。

[微信提示:高防服务器能助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。

[图文来源于网络,不代表本站立场,如有侵权,请联系高防服务器网删除]
[