LG MRA58K – Missing Bounds-Checking in AVI Stream Parsing

  • 作者: Google Security Research
    日期: 2017-06-13
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/42170/
  • 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 00000002r1 00000012r2 ffffffd0r3 f6b572f0
    AM write failed: Broken pipe
    r4 f6b572e8r5 41414141r6 f5fb6000r7 41400000
    r8 f155c748r9 f6b4a594sl 00000001fp f000081c
    ip 41400048sp f00005f8lr f6b2c7a7pc f6b29826cpsr 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