目标达成 感谢每一位支持者 — 我们达成了 100% 目标!

目标: 1000 元 · 已筹: 1336

100%

CVE-2019-11933 PoC — Facebook WhatsApp for Android libpl_droidsonroids_gif 缓冲区错误漏洞

来源
关联漏洞
标题: Facebook WhatsApp for Android libpl_droidsonroids_gif 缓冲区错误漏洞 (CVE-2019-11933)
Description:Facebook WhatsApp for Android(WhatsApp Messenger)是美国Facebook公司的一套基于Android平台的、利用网络传送短信的移动应用程序。该应用程序通过智能手机中的联络人信息,查找使用该软件的联络人传送文字、图片等。libpl_droidsonroids_gif是其中的一个库。 基于Android平台的Facebook WhatsApp 2.19.291之前版本中的libpl_droidsonroids_gif 1.2.19之前版本存在缓冲区错误漏洞。该漏
Description
Heap corruption in WhatsApp's media picker
介绍
# CVE-2019-11933
Heap corruption in WhatsApp's media picker affecting WhatsApp for android before version 2.19.291

# Background
A GIF file is divided into segments, marked by a specific byte:
* Image (0x2C)
  * The image section describes a single frame in the GIF file, and contains information such as the height, width, as well as the compressed image itself. A GIF can have multiple frames and thus multiple image sections.
* Extension (0x21)
  * The extension section contains data that is used to modify an image.
* Terminate (0x3B)
  * Marks the end of the GIF file

According to the source code, renderFrame calls DDGifSlurp to parse a GIF, and getBitmap to display the GIF. A rasterBits buffer is allocated by the function, and its size calculated by multiply the width by the height of the image it is currently processing. Perhaps to save memory space and time, the same rasterBits buffer will be used for all frames/images in the GIF. Therefore, it is required that the buffer is able to contain the largest image described in the file. As such, the buffer is re-allocated accordingly if another image section within the same GIF describes a larger image (requires more space).

# Vulnerability
DDGifSlurp parses the GIF file in a loop, processing each image/frame in the file, and terminates when the terminate record is encountered. When DGifGetImageDesc to return GIF_ERROR (a), it will result in early termination (in the switch case), causing the code that reallocates the rasterBits buffer to be skipped. A snippet of DDGifSlurp is shown below:
```c
void DDGifSlurp(GifInfo *info, bool decode, bool exitAfterFrame) {
    ...
    do {
        ...
        switch (RecordType) {
            case IMAGE_DESC_RECORD_TYPE:
             
                if (DGifGetImageDesc(gifFilePtr, isInitialPass) == GIF_ERROR) {   <-- [a]
                    break;
                }
                ...
                if (decode) {
                    ...
                    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));
                        ...
                    }
    }while (RecordType != TERMINATE_RECORD_TYPE);
}
```
A GIF image that has the following format will cause a crash:
* Valid image (10 x 10)
* Larger image (10000 x 10000) with an invalid image descriptor

## Stages that lead to crash
1. Parsing Phase
   1. Parse first image (small)
   1. Allocate rasterBits buffer of size (small height * small width)
   1. Parse second image (large)
   1. DGifSetupDecompress/DGifGetImageDesc returns GIF_ERROR
   1. Skip reallocation
1. Rendering Phase
   1. Render first image (success)
   1. Render second image (OOB)
文件快照

登录后查看神龙缓存的 POC 文件快照

登录查看
备注
    1. 建议优先通过来源进行访问。
    2. 本地 POC 快照面向订阅用户开放;当原始来源失效或无法访问时,本地镜像作为订阅权益的一部分提供。
    3. 持续抓取、验证、维护这份 POC 档案需要不少投入,因此本地快照已纳入付费订阅。您的订阅是让这份资料能继续走下去的关键,由衷感谢。 查看订阅方案 →