Skip to content

Open Broadcaster Software (OBS): Heap Overflow Vulnerability

High
rcorrea35 published GHSA-mf24-5fxf-f4x5 Aug 19, 2024

Package

No package listed

Affected versions

> https://github.com/obsproject/obs-studio/commit/13890a46e6efc14a64ab5ee4f539d3a8607837a0

Patched versions

None

Description

Summary

OBS (Open Broadcaster Software) is a well-known open source and cross platform software for screen recording and streaming. Unfortunately, a crafted GIF file with malicious LZW compressed data may trigger a heap overflow bug in the OBS image parser library after commit 13890a46e6efc14a64ab5ee4f539d3a8607837a0 in Jan 2016.

Severity

High - an attacker could exploit this to write data beyond the allocated boundaries of memory on the heap.

Proof of Concept

The OBS heap overflow bug recorded by OBS: video
When applying the image source with the malicious GIF file in Ubuntu, OBS will crash immediately. Core dump reports libc tcache heap corruption:

Program terminated with signal SIGSEGV, Segmentation fault.
#0  tcache_get (tc_idx=<optimized out>) at ./malloc/malloc.c:3196
3196	./malloc/malloc.c: No such file or directory.
[Current thread is 1 (Thread 0xffff5ee2d480 (LWP 17380))]
gef➤  bt
#0  tcache_get (tc_idx=<optimized out>) at ./malloc/malloc.c:3196
#1  __GI___libc_malloc (bytes=0x3) at ./malloc/malloc.c:3313
#2  0x0000ffffb36aeb70 in av_strdup () at /lib/aarch64-linux-gnu/libavutil.so.56
#3  0x0000ffffb36b0df0 in av_opt_set_defaults2 () at /lib/aarch64-linux-gnu/libavutil.so.56
#4  0x0000ffffb3530038 in avformat_alloc_context () at /lib/aarch64-linux-gnu/libavformat.so.58
#5  0x0000ffff62fc6e80 in  () at /usr//lib/aarch64-linux-gnu/obs-plugins/obs-ffmpeg.so
#6  0x0000ffffb158d5c8 in start_thread (arg=0x0) at ./nptl/pthread_create.c:442
#7  0x0000ffffb15f5edc in thread_start () at ../sysdeps/unix/sysv/linux/aarch64/clone.S:79

Further Analysis

By using LD_PRELOAD=/usr/aarch64-linux-gnu/lib/libasan.so.6.0.0 obs command, it appears that the heap overflow happens in libobs module:

==30002==ERROR: AddressSanitizer: SEGV on unknown address 0xffff96210000 (pc 0xffffb0df54dc bp 0xffff896c1600 sp 0xffff896c1600 T11)
==30002==The signal is caused by a WRITE memory access.
    #0 0xffffb0df54dc  (/lib/aarch64-linux-gnu/libobs.so.0+0x254dc)
    #1 0xffffb0dffb5c  (/lib/aarch64-linux-gnu/libobs.so.0+0x2fb5c)
    #2 0xffffb0e008e4 in gs_image_file3_init (/lib/aarch64-linux-gnu/libobs.so.0+0x308e4)
    #3 0xffff97cd37cc  (/usr//lib/aarch64-linux-gnu/obs-plugins/image-source.so+0x37cc)
    #4 0xffffb0e84fc4  (/lib/aarch64-linux-gnu/libobs.so.0+0xb4fc4)
    #5 0xffffafddd5c4 in start_thread nptl/pthread_create.c:442
    #6 0xffffafe45ed8  (/lib/aarch64-linux-gnu/libc.so.6+0xe5ed8)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV (/lib/aarch64-linux-gnu/libobs.so.0+0x254dc) 
Thread T11 created by T0 here:
AddressSanitizer:DEADLYSIGNAL
AddressSanitizer: nested bug in the same thread, aborting.

The corruption happens in gif_next_LZW (libobs/graphics/libnsgif/libnsgif.c), and the libnsgif is an open source project by NetSurf Browser (https://www.netsurf-browser.org/projects/libnsgif/). A further investigation shows that the OBS project ported libnsgif code in Jan 2016 but no one patches known security issues later on. As a result, the OBS is subject to CVE-2015-7505 and CVE-2015-7506 (OOB write and read in .bss section).

However, the OBS project also makes some changes to the libnsgif code. Instead of writing out-of-bounds or reading out-of-bounds in the .bss area, now the memory corruption happens in the heap:

typedef struct gif_animation {  // gif_animation is allocated from heap.
    ...
    // OBS developer decides to move these variables from .bss to heap.
    /*    General LZW values. They are NO LONGER shared for all GIFs being decoded BECAUSE
          THAT IS A TERRIBLE IDEA TO SAVE 10Kb or so per GIF.
    */
    unsigned char buf[4];
    unsigned char *direct;

    int table[2][(1 << GIF_MAX_LZW)];
    unsigned char stack[(1 << GIF_MAX_LZW) * 2];
    unsigned char *stack_pointer;  // Originally points to stack, but a malicious LZW compressed bytestream may cause a linear write OOB.
    int code_size, set_code_size;
    int max_code, max_code_size;
    int clear_code, end_code;
    int curbit, lastbit, last_byte;
    int firstcode, oldcode;
    bool zero_data_block;
    bool get_done;

Recommended fix: Apply the libnsgif fix commit to libobs: https://source.netsurf-browser.org/libnsgif.git/commit/?id=a268d2c15252ac58c19f1b19771822c66bcf73b2

Timeline

Date reported: 05/01/2024
Date fixed:
Date disclosed: 07/30/2024

Severity

High

CVE ID

No known CVE

Weaknesses

No CWEs

Credits