Hi: another CVE appeared, CVE-2017-8787 (see also
https://bugs.debian.org/861738)

According to a private email from the OP this is already
fixed/unreproducible in trunk, so it would only need $somebody to find
the fixing commit.

Forwarding here as a FYI.


----- Forwarded message from Xiaobo Xiang <xiangxb2...@gmail.com> -----

Date: Wed, 3 May 2017 18:55:49 +0800
From: Xiaobo Xiang <xiangxb2...@gmail.com>
To: sub...@bugs.debian.org
Subject: Bug#861738: [bug report][libpodofo]heap based overflow in 
ReadXRefStreamEntry
Message-ID: <cahhvycq9zsft5x68gwdbf13_w17iq5g4luvor3gz4p33113...@mail.gmail.com>

Package: libpodofo
Version: 0.9.5

[summary]
I've found a heap based buffer overflow in libpodofo using libFuzzer.
PdfXRefStreamParserObject::ReadXRefStreamEntry(src/base/PdfXRefStreamParserObject.cpp:224)

[details]
in function PdfXRefStreamParserObject::ReadXRefTable(), the program get
nW[] array from file data, and does no check on it.

    void PdfXRefStreamParserObject::ReadXRefTable()
    {
        pdf_int64  lSize   = this->GetDictionary().GetKeyAsLong(
PdfName::KeySize, 0 );
        PdfVariant vWArray = *(this->GetDictionary().GetKey( "W" ));

        // The pdf reference states that W is always an array with 3 entries
        // all of them have to be integers
        if( !vWArray.IsArray() || vWArray.GetArray().size() != 3 )
        {
            PODOFO_RAISE_ERROR( ePdfError_NoXRef );
        }

        pdf_int64 nW[W_ARRAY_SIZE] = { 0, 0, 0 };
        for( int i=0;i<W_ARRAY_SIZE;i++ )
        {
            if( !vWArray.GetArray()[i].IsNumber() )
            {
                PODOFO_RAISE_ERROR( ePdfError_NoXRef );
            }

            nW[i] =
static_cast<pdf_int64>(vWArray.GetArray()[i].GetNumber());    // get from
file data, without check.
        }

        std::vector<pdf_int64> vecIndeces;
        GetIndeces( vecIndeces, static_cast<pdf_int64>(lSize) );

        ParseStream( nW, vecIndeces );  // pass the array to ParseStream
    }

the nW array will be passed to ParseStream Function, they are used to
calculate entryLen using add.

    const size_t entryLen  = static_cast<size_t>(nW[0] + nW[1] + nW[2]);

Followed are two while loop, in the second loop, program calls
ReadXRefStreamEntry:

    void PdfXRefStreamParserObject::ParseStream( const pdf_int64
nW[W_ARRAY_SIZE], const std::vector<pdf_int64> & rvecIndeces )
    {
        char*        pBuffer;
        pdf_long     lBufferLen;
        const size_t entryLen  = static_cast<size_t>(nW[0] + nW[1] +
nW[2]); // may be 0xffffffff

        std::vector<pdf_int64>::const_iterator it = rvecIndeces.begin();
        char* const pStart = pBuffer;
        while( it != rvecIndeces.end() )
        {
            //.......
            while( nCount > 0 )
            {
                if( (pBuffer - pStart) >= lBufferLen )
                {
                    PODOFO_RAISE_ERROR_INFO( ePdfError_NoXRef, "Invalid
count in XRef stream" );
                }

                //printf("nCount=%i ", static_cast<int>(nCount));
                //printf("pBuffer=%li ", (long)(pBuffer - pStart));
                //printf("pEnd=%li ", lBufferLen);
                if ( nFirstObj >= 0 && nFirstObj <
static_cast<pdf_int64>(m_pOffsets->size())
                     && !
(*m_pOffsets)[static_cast<int>(nFirstObj)].bParsed)
                {
                ReadXRefStreamEntry( pBuffer, lBufferLen, nW,
static_cast<int>(nFirstObj) );     // calling ReadXRefStreamEntry
                }

                nFirstObj++ ;
                pBuffer += entryLen;    // heap out of bound read
                --nCount;
            }
            //......
        }
        podofo_free( pStart );
    }

in ReadXRefStreamEntry function,there are two loops, in the second loop,
program fetches data from pBuffer pointer and assigns it to nData[i], this
could result in out of bound read in the heap. Because pBuffer was modified
in ParseStream by "pBuffer += entryLen;" .

in my case, the nW[]=[1 -4 2] , entryLen=1-4+2=0xffffffff

I've recorded the value before the assignment sentence. the value of
pBuffer pointer is as follows:

    pBuffer=0x621000019100
    pBuffer=0x621000019101
    pBuffer=0x621000019102
    pBuffer=0x6210000190ff

after calling pBuffer+=entryLen for several times, the pBuffer will get
under overflow, when it returned to ReadXRefStreamEntry again, heap
overflow.

[crash log]
Below is my crash log:
 ./podofopdfinfo ./heap-overflow-ReadXRefStreamEntry
=================================================================
==23234==ERROR: AddressSanitizer: heap-buffer-overflow on address
0x6210000190ff at pc 0x0000005bd7a4 bp 0x7fff686b0350 sp 0x7fff686b0340
READ of size 1 at 0x6210000190ff thread T0
    #0 0x5bd7a3 in
PoDoFo::PdfXRefStreamParserObject::ReadXRefStreamEntry(char*, long, long
const*, int) podofo-0.9.5/src/base/PdfXRefStreamParserObject.cpp:224
    #1 0x5bcf41 in PoDoFo::PdfXRefStreamParserObject::ParseStream(long
const*, std::vector<long, std::allocator<long> > const&)
podofo-0.9.5/src/base/PdfXRefStreamParserObject.cpp:156
    #2 0x5bc9b0 in PoDoFo::PdfXRefStreamParserObject::ReadXRefTable()
podofo-0.9.5/src/base/PdfXRefStreamParserObject.cpp:118
    #3 0x598894 in PoDoFo::PdfParser::ReadXRefStreamContents(long, bool)
podofo-0.9.5/src/base/PdfParser.cpp:858
    #4 0x597720 in PoDoFo::PdfParser::ReadXRefContents(long, bool)
podofo-0.9.5/src/base/PdfParser.cpp:682
    #5 0x594106 in PoDoFo::PdfParser::ReadDocumentStructure()
podofo-0.9.5/src/base/PdfParser.cpp:337
    #6 0x593734 in
PoDoFo::PdfParser::ParseFile(PoDoFo::PdfRefCountedInputDevice const&, bool)
podofo-0.9.5/src/base/PdfParser.cpp:220
    #7 0x59331e in PoDoFo::PdfParser::ParseFile(char const*, bool)
podofo-0.9.5/src/base/PdfParser.cpp:164
    #8 0x540f4f in PoDoFo::PdfMemDocument::Load(char const*, bool)
podofo-0.9.5/src/doc/PdfMemDocument.cpp:256
    #9 0x53fde9 in PoDoFo::PdfMemDocument::PdfMemDocument(char const*,
bool) podofo-0.9.5/src/doc/PdfMemDocument.cpp:102
    #10 0x4b8021 in PdfInfo::PdfInfo(std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> > const&)
podofo-0.9.5/tools/podofopdfinfo/pdfinfo.cpp:25
    #11 0x4bee20 in main
podofo-0.9.5/tools/podofopdfinfo/podofopdfinfo.cpp:110
    #12 0x7fe5111a882f in __libc_start_main
(/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
    #13 0x4b7ee8 in _start (podofopdfinfo+0x4b7ee8)

0x6210000190ff is located 1 bytes to the left of 4096-byte region
[0x621000019100,0x62100001a100)
allocated by thread T0 here:
    #0 0x7fe512a0779a in __interceptor_calloc
(/usr/lib/x86_64-linux-gnu/libasan.so.2+0x9879a)
    #1 0x591652 in PoDoFo::podofo_calloc(unsigned long, unsigned long)
podofo-0.9.5/src/base/PdfMemoryManagement.cpp:136
    #2 0x591aa6 in
PoDoFo::PdfMemoryOutputStream::PdfMemoryOutputStream(long)
podofo-0.9.5/src/base/PdfOutputStream.cpp:77
    #3 0x4db667 in PoDoFo::PdfStream::GetFilteredCopy(char**, long*) const
podofo-0.9.5/src/base/PdfStream.cpp:91
    #4 0x5bccb1 in PoDoFo::PdfXRefStreamParserObject::ParseStream(long
const*, std::vector<long, std::allocator<long> > const&)
podofo-0.9.5/src/base/PdfXRefStreamParserObject.cpp:127
    #5 0x5bc9b0 in PoDoFo::PdfXRefStreamParserObject::ReadXRefTable()
podofo-0.9.5/src/base/PdfXRefStreamParserObject.cpp:118
    #6 0x598894 in PoDoFo::PdfParser::ReadXRefStreamContents(long, bool)
podofo-0.9.5/src/base/PdfParser.cpp:858
    #7 0x597720 in PoDoFo::PdfParser::ReadXRefContents(long, bool)
podofo-0.9.5/src/base/PdfParser.cpp:682
    #8 0x594106 in PoDoFo::PdfParser::ReadDocumentStructure()
podofo-0.9.5/src/base/PdfParser.cpp:337
    #9 0x593734 in
PoDoFo::PdfParser::ParseFile(PoDoFo::PdfRefCountedInputDevice const&, bool)
podofo-0.9.5/src/base/PdfParser.cpp:220
    #10 0x59331e in PoDoFo::PdfParser::ParseFile(char const*, bool)
podofo-0.9.5/src/base/PdfParser.cpp:164
    #11 0x540f4f in PoDoFo::PdfMemDocument::Load(char const*, bool)
podofo-0.9.5/src/doc/PdfMemDocument.cpp:256
    #12 0x53fde9 in PoDoFo::PdfMemDocument::PdfMemDocument(char const*,
bool) podofo-0.9.5/src/doc/PdfMemDocument.cpp:102
    #13 0x4b8021 in PdfInfo::PdfInfo(std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> > const&)
podofo-0.9.5/tools/podofopdfinfo/pdfinfo.cpp:25
    #14 0x4bee20 in main
podofo-0.9.5/tools/podofopdfinfo/podofopdfinfo.cpp:110
    #15 0x7fe5111a882f in __libc_start_main
(/lib/x86_64-linux-gnu/libc.so.6+0x2082f)

SUMMARY: AddressSanitizer: heap-buffer-overflow
podofo-0.9.5/src/base/PdfXRefStreamParserObject.cpp:224
PoDoFo::PdfXRefStreamParserObject::ReadXRefStreamEntry(char*, long, long
const*, int)
Shadow bytes around the buggy address:
  0x0c427fffb1c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c427fffb1d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c427fffb1e0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c427fffb1f0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c427fffb200: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c427fffb210: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa[fa]
  0x0c427fffb220: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c427fffb230: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c427fffb240: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c427fffb250: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c427fffb260: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
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
  Heap right redzone:      fb
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack partial redzone:   f4
  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
==23234==ABORTING

[how to reproduce]
compile the podofo project with address sanitizer, and run the following
command
 ./podofopdfinfo ./heap-overflow-ReadXRefStreamEntry

[how to fix]
I think checking the value of the nW array to ensure they are positive will
work.

Please feel free to ask me if you have further question about this report.

Best Regards,
Xiang Xiaobo of VARAS@IIE



----- End forwarded message -----

-- 
regards,
                        Mattia Rizzolo

GPG Key: 66AE 2B4A FCCF 3F52 DA18  4D18 4B04 3FCD B944 4540      .''`.
more about me:  https://mapreri.org                             : :'  :
Launchpad user: https://launchpad.net/~mapreri                  `. `'`
Debian QA page: https://qa.debian.org/developer.php?login=mattia  `-

Attachment: signature.asc
Description: PGP signature

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Podofo-users mailing list
Podofo-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/podofo-users

Reply via email to