Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    863108587

Contributors to this blog

  • HireHackking 16114

About this blog

Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.

Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1206

Missing bounds-checking in AVI stream parsing

When parsing AVI files, CAVIFileParser uses the stream count from the AVI header 
to allocate backing storage for storing metadata about the streams (member 
variable m_aStream). However, the number of stream headers we parse is never 
validated against this allocation size during parsing, so we can write further 
metadata past the end of this buffer by constructing a file which contains more
stream headers than expected.

The allocation happens here:

int CAVIFileParser::ParseChunkAviHdr(int a2, unsigned int chunk_size)
{
  struct AviHeader *avih;
  int result;

  // snip some sanity checking (have we already found an 'avih' chunk, is this
  // chunk large enough to contain an avi header.)

  result = AVISourceReader::AVI_fread(this->source, avih, sizeof(struct AviHeader), 1);
  if ( result <= 0 )
  {
    // snip...
  }
  else
  {
    stream_count = avih->dwStreams; // <-- this is an attacker-controlled count
    this->m_aStreamCount = stream_count;
    this->m_aStream = malloc(stream_count * sizeof(struct AviStream));
    this->m_aStreamIndex = -1;

    // snip...
  }

  return 1;
}

There doesn't appear to be any integer overflow checking in the multiplication
either; so if the current issue is directly fixed there could still be a 
vulnerability if stream_count * sizeof(struct AviStream) overflows.

this->m_aStreamIndex is incremented without checking in 
CAVIFileParser::ParseChild and used as an index into m_aStream in several places
without checking, including in CAVIFileParser::ParseChunkStrHdr and
CAVIFileParser::ParseChunkStrFmt.

Several of the values that we can get written out of bounds are pointers to 
controlled data, which is an interesting exploitation primitive. I've attached
a PoC file and script to generate it which results in overlapping a SRIFFNode* 
with the contents of a 'strf' chunk, resulting in a free of an attacker 
controlled pointer - in this case, 0x41414141. Since the structure sizes are 
dependent on the version of the library, this may not work on different builds, 
but it will hopefully cause a crash regardless.

Build fingerprint: 'lge/p1_global_com/p1:6.0/MRA58K/1624210305d45:user/release-keys'
Revision: '11'
ABI: 'arm'
pid: 19481, tid: 19585, name: Binder_2  >>> /system/bin/mediaserver <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x4140007c
    r0 00000002  r1 00000012  r2 ffffffd0  r3 f6b572f0
AM write failed: Broken pipe
    r4 f6b572e8  r5 41414141  r6 f5fb6000  r7 41400000
    r8 f155c748  r9 f6b4a594  sl 00000001  fp f000081c
    ip 41400048  sp f00005f8  lr f6b2c7a7  pc f6b29826  cpsr 200f0030

backtrace:
    #00 pc 00055826  /system/lib/libc.so (ifree+49)
    #01 pc 000587a3  /system/lib/libc.so (je_free+374)
    #02 pc 000058f3  /system/lib/liblg_parser_avi.so (_ZN14CAVIFileParser15DeleteSRIFFNodeEP9SRIFFNode+54)
    #03 pc 00005915  /system/lib/liblg_parser_avi.so (_ZN14CAVIFileParser7DestroyEv+12)
    #04 pc 00005a33  /system/lib/liblg_parser_avi.so (_ZN14CAVIFileParserD1Ev+14)
    #05 pc 00005a45  /system/lib/liblg_parser_avi.so (_ZN14CAVIFileParserD0Ev+4)
    #06 pc 0000442f  /system/lib/liblg_parser_avi.so (_ZN9AVIParser5CloseEv+12)
    #07 pc 00025baf  /system/lib/libLGParserOSAL.so (_ZN7android14LGAVIExtractorD1Ev+26)


Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/42170.zip