Talos Vulnerability Report

TALOS-2023-1846

stb stb_vorbis.c comment heap-based buffer overflow vulnerability

May 1, 2024
CVE Number

CVE-2023-47212

SUMMARY

A heap-based buffer overflow vulnerability exists in the comment functionality of stb _vorbis.c v1.22. A specially crafted .ogg file can lead to an out-of-bounds write. An attacker can provide a malicious file to trigger this vulnerability.

CONFIRMED VULNERABLE VERSIONS

The versions below were either tested or verified to be vulnerable by Talos or confirmed to be vulnerable by the vendor.

stb _vorbis.c v1.22

PRODUCT URLS

stb_vorbis.c - https://github.com/nothings/stb

CVSSv3 SCORE

9.8 - CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

CWE

CWE-190 - Integer Overflow or Wraparound

DETAILS

stb_vorbis.c is a single-header file library for decoding Ogg Vorbis non-proprietary audio files.

The stb_vorbis.c allows parsing of Ogg Vorbis files. Comments can be store in this file format. Following the relevant code that parses the comments in the stb_vorbis.c file:

    static int start_decoder(vorb *f)
    {
       [...]
   [1] f->comment_list_length = get32_packet(f);
       f->comment_list = NULL;
       if (f->comment_list_length > 0)
       {
   [2]    f->comment_list = (char**) setup_malloc(f, sizeof(char*) * (f->comment_list_length));
          if (f->comment_list == NULL)                  return error(f, VORBIS_outofmem);
       }

       for(i=0; i < f->comment_list_length; ++i) {
          len = get32_packet(f);
   [3]    f->comment_list[i] = (char*)setup_malloc(f, sizeof(char) * (len+1));
          if (f->comment_list[i] == NULL)               return error(f, VORBIS_outofmem);

          for(j=0; j < len; ++j) {
             f->comment_list[i][j] = get8_packet(f);
          }
          f->comment_list[i][len] = (char)'\0';
       }
       [...]
    }

The comment list starts with 4 bytes for the comment_list_length field, which specifies the number of comment entries that follow this field. Each entry is composed of two fields: the size of the comment and the comment itself. The encoding looks like this:

<32bit comment_list_length> (<32bit comment_length> <comment[comment_length]>)[comment_list_length]

At [1] the comment_list_length is parsed and later used at [2] for allocating an array of char*. The array is filled up iterating the code at [3] that allocates the size of the current comment.

At [2] the size used for allocating the array is calculated through sizeof(char*) * (f->comment_list_length). This calculation could cause an integer overflow, which would lead to allocation of less space than required for the comment pointers. Because the integer overflow occurs only during the calculation of the space required, this will not impact the f->comment_list_length value itself, leading to allocation of more comment pointers than there is space. This leads to an out-of-bounds write at [3]. With enough heap grooming an attacker would be able to use this vulnerability to achieve arbitrary code execution.

Crash Information

=================================================================
==1926744==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000038 at pc 0x0000004d693f bp 0x7ffcf6b3e3d0 sp 0x7ffcf6b3e3c8
WRITE of size 8 at 0x602000000038 thread T0
    #0 0x4d693e in start_decoder(stb_vorbis*) /home/vagrant/stb/stb_vorbis.c:3670:26
    #1 0x4ed9f8 in stb_vorbis_open_memory /home/vagrant/stb/stb_vorbis.c:5112:8
    #2 0x4f09b6 in stb_vorbis_decode_memory /home/vagrant/stb/stb_vorbis.c:5390:20
    #3 0x4cd050 in LLVMFuzzerTestOneInput /home/vagrant/stb/./debug_crash.cc:107:5
    #4 0x525a53 in HonggfuzzMain (/home/vagrant/stb/debug_crash+0x525a53)
    #5 0x7f6206187d09 in __libc_start_main csu/../csu/libc-start.c:308:16
    #6 0x4208e9 in _start (/home/vagrant/stb/debug_crash+0x4208e9)

0x602000000038 is located 0 bytes to the right of 8-byte region [0x602000000030,0x602000000038)
allocated by thread T0 here:
    #0 0x49a95d in malloc (/home/vagrant/stb/debug_crash+0x49a95d)
    #1 0x513af2 in setup_malloc(stb_vorbis*, int) /home/vagrant/stb/stb_vorbis.c:960:16
    #2 0x4d6703 in start_decoder(stb_vorbis*) /home/vagrant/stb/stb_vorbis.c:3664:34
    #3 0x4ed9f8 in stb_vorbis_open_memory /home/vagrant/stb/stb_vorbis.c:5112:8
    #4 0x4f09b6 in stb_vorbis_decode_memory /home/vagrant/stb/stb_vorbis.c:5390:20
    #5 0x4cd050 in LLVMFuzzerTestOneInput /home/vagrant/stb/./debug_crash.cc:107:5
    #6 0x525a53 in HonggfuzzMain (/home/vagrant/stb/debug_crash+0x525a53)

SUMMARY: AddressSanitizer: heap-buffer-overflow /home/vagrant/stb/stb_vorbis.c:3670:26 in start_decoder(stb_vorbis*)
Shadow bytes around the buggy address:
  0x0c047fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c047fff8000: fa fa 00 07 fa fa 00[fa]fa fa 00 fa fa fa 00 fa
  0x0c047fff8010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==1926744==ABORTING
VENDOR RESPONSE

No maintainer reachable, no patch available

TIMELINE

2023-11-15 - Initial Vendor Contact
2023-11-20 - Initial Vendor Contact
2023-11-28 - Initial Vendor Contact
2023-11-30 - Initial Vendor Contact
2023-12-22 - Vendor Disclosure
2024-03-06 - Status update request / Publication date announced
2024-05-01 - Public Release

Credit

Discovered by Francesco Benvenuto of Cisco Talos.