HexBrain

Internet Bug Bounty · Report #262665

CVE-2017-5969: libxml2 when used in recover mode, allows remote attackers to cause a denial of service (NULL pointer dereference)

Validstatus
mediumseverity
3upvotes
4 Oct 2019disclosed

How it was found

I first reported this bug to the developers on 20 November 2015. A patch was finally committed on 7 June 2017 here. The caveat here is that this only happens in recover mode which the developers say no sane person should ever use in production and/or against untrusted inputs. A CVE was assigned in April 2017.

The original crash involved some memory corruption which lead to a null pointer dereference and subsequent segfault after running ./xmllint --recover against XML similar to <!DOCTYPE[<!ELEMENT l((|s)>.

test00.xml:1: parser error : xmlParseDocTypeDecl : no DOCTYPE name !
<!DOCTYPE[<?l?><!ELEMENT�(�,()>
         ^
test00.xml:1: parser error : Space required after 'ELEMENT'
<!DOCTYPE[<?l?><!ELEMENT�(�,()>
                        ^
test00.xml:1: parser error : Input is not proper UTF-8, indicate encoding !
Bytes: 0xDF 0x28 0xE2 0x2C
<!DOCTYPE[<?l?><!ELEMENT�(�,()>
                        ^
test00.xml:1: parser error : Space required after the element name
<!DOCTYPE[<?l?><!ELEMENT�(�,()>
                         ^
test00.xml:1: parser error : ContentDecl : Name or '(' expected
<!DOCTYPE[<?l?><!ELEMENT�(�,()>
                             ^
test00.xml:1: parser error : internal error: xmlParseInternalSubset: error detected in Markup declaration

<!DOCTYPE[<?l?><!ELEMENT�(�,()>
                               ^
test00.xml:1: parser error : DOCTYPE improperly terminated
<!DOCTYPE[<?l?><!ELEMENT�(�,()>
                               ^
==100630== Conditional jump or move depends on uninitialised value(s)
==100630==    at 0x452A72: xmlNextChar (parserInternals.c:535)
==100630==    by 0x4CF45F: xmlParseInternalSubset (parser.c:8460)
==100630==    by 0x4E655D: xmlParseDocument (parser.c:10852)
==100630==    by 0x50657F: xmlDoRead (parser.c:15340)
==100630==    by 0x50657F: xmlReadFile (parser.c:15402)
==100630==    by 0x41CD6F: parseAndPrintFile (xmllint.c:2401)
==100630==    by 0x410409: main (xmllint.c:3759)
==100630== 
==100630== Conditional jump or move depends on uninitialised value(s)
==100630==    at 0x452E0C: xmlNextChar (parserInternals.c:538)
==100630==    by 0x4CF45F: xmlParseInternalSubset (parser.c:8460)
==100630==    by 0x4E655D: xmlParseDocument (parser.c:10852)
==100630==    by 0x50657F: xmlDoRead (parser.c:15340)
==100630==    by 0x50657F: xmlReadFile (parser.c:15402)
==100630==    by 0x41CD6F: parseAndPrintFile (xmllint.c:2401)
==100630==    by 0x410409: main (xmllint.c:3759)
==100630== 
==100630== Conditional jump or move depends on uninitialised value(s)
==100630==    at 0x452EE3: xmlNextChar (parserInternals.c:540)
==100630==    by 0x4CF45F: xmlParseInternalSubset (parser.c:8460)
==100630==    by 0x4E655D: xmlParseDocument (parser.c:10852)
==100630==    by 0x50657F: xmlDoRead (parser.c:15340)
==100630==    by 0x50657F: xmlReadFile (parser.c:15402)
==100630==    by 0x41CD6F: parseAndPrintFile (xmllint.c:2401)
==100630==    by 0x410409: main (xmllint.c:3759)
==100630== 
==100630== Conditional jump or move depends on uninitialised value(s)
==100630==    at 0x4D39A7: xmlParseMisc (parser.c:10723)
==100630==    by 0x4E6197: xmlParseDocument (parser.c:10872)
==100630==    by 0x50657F: xmlDoRead (parser.c:15340)
==100630==    by 0x50657F: xmlReadFile (parser.c:15402)
==100630==    by 0x41CD6F: parseAndPrintFile (xmllint.c:2401)
==100630==    by 0x410409: main (xmllint.c:3759)
==100630== 
==100630== Conditional jump or move depends on uninitialised value(s)
==100630==    at 0x4D39FA: xmlParseMisc (parser.c:10726)
==100630==    by 0x4E6197: xmlParseDocument (parser.c:10872)
==100630==    by 0x50657F: xmlDoRead (parser.c:15340)
==100630==    by 0x50657F: xmlReadFile (parser.c:15402)
==100630==    by 0x41CD6F: parseAndPrintFile (xmllint.c:2401)
==100630==    by 0x410409: main (xmllint.c:3759)
==100630== 
==100630== Conditional jump or move depends on uninitialised value(s)
==100630==    at 0x4D3A3F: xmlParseMisc (parser.c:10726)
==100630==    by 0x4E6197: xmlParseDocument (parser.c:10872)
==100630==    by 0x50657F: xmlDoRead (parser.c:15340)
==100630==    by 0x50657F: xmlReadFile (parser.c:15402)
==100630==    by 0x41CD6F: parseAndPrintFile (xmllint.c:2401)
==100630==    by 0x410409: main (xmllint.c:3759)
==100630== 
test00.xml:1: parser error : internal error: Huge input lookup
==100630== Conditional jump or move depends on uninitialised value(s)
==100630==    at 0x445E2C: xmlParserPrintFileContextInternal (error.c:184)
==100630==    by 0x448B99: xmlReportError (error.c:404)
==100630==    by 0x44FB9C: __xmlRaiseError (error.c:631)
==100630==    by 0x474CA5: xmlFatalErr (parser.c:538)
==100630==    by 0x474CA5: xmlGROW (parser.c:2075)
==100630==    by 0x4E5CCF: xmlParseDocument (parser.c:10878)
==100630==    by 0x50657F: xmlDoRead (parser.c:15340)
==100630==    by 0x50657F: xmlReadFile (parser.c:15402)
==100630==    by 0x41CD6F: parseAndPrintFile (xmllint.c:2401)
==100630==    by 0x410409: main (xmllint.c:3759)
==100630== 
==100630== Conditional jump or move depends on uninitialised value(s)
==100630==    at 0x445E6C: xmlParserPrintFileContextInternal (error.c:184)
==100630==    by 0x448B99: xmlReportError (error.c:404)
==100630==    by 0x44FB9C: __xmlRaiseError (error.c:631)
==100630==    by 0x474CA5: xmlFatalErr (parser.c:538)
==100630==    by 0x474CA5: xmlGROW (parser.c:2075)
==100630==    by 0x4E5CCF: xmlParseDocument (parser.c:10878)
==100630==    by 0x50657F: xmlDoRead (parser.c:15340)
==100630==    by 0x50657F: xmlReadFile (parser.c:15402)
==100630==    by 0x41CD6F: parseAndPrintFile (xmllint.c:2401)
==100630==    by 0x410409: main (xmllint.c:3759)
==100630== 
<!DOCTYPE[<?l?><!ELEMENT�(�,()>
                               ^
==100630== Conditional jump or move depends on uninitialised value(s)
==100630==    at 0x4749A8: xmlGROW (parser.c:2079)
==100630==    by 0x4E5CCF: xmlParseDocument (parser.c:10878)
==100630==    by 0x50657F: xmlDoRead (parser.c:15340)
==100630==    by 0x50657F: xmlReadFile (parser.c:15402)
==100630==    by 0x41CD6F: parseAndPrintFile (xmllint.c:2401)
==100630==    by 0x410409: main (xmllint.c:3759)
==100630== 
==100630== Conditional jump or move depends on uninitialised value(s)
==100630==    at 0x4E55FC: xmlParseDocument (parser.c:10879)
==100630==    by 0x50657F: xmlDoRead (parser.c:15340)
==100630==    by 0x50657F: xmlReadFile (parser.c:15402)
==100630==    by 0x41CD6F: parseAndPrintFile (xmllint.c:2401)
==100630==    by 0x410409: main (xmllint.c:3759)
==100630== 
test00.xml:1: parser error : Start tag expected, '<' not found
==100630== Conditional jump or move depends on uninitialised value(s)
==100630==    at 0x445E2C: xmlParserPrintFileContextInternal (error.c:184)
==100630==    by 0x448B99: xmlReportError (error.c:404)
==100630==    by 0x44FB9C: __xmlRaiseError (error.c:631)
==100630==    by 0x4E5012: xmlFatalErrMsg (parser.c:565)
==100630==    by 0x4E5012: xmlParseDocument (parser.c:10880)
==100630==    by 0x50657F: xmlDoRead (parser.c:15340)
==100630==    by 0x50657F: xmlReadFile (parser.c:15402)
==100630==    by 0x41CD6F: parseAndPrintFile (xmllint.c:2401)
==100630==    by 0x410409: main (xmllint.c:3759)
==100630== 
==100630== Conditional jump or move depends on uninitialised value(s)
==100630==    at 0x445E6C: xmlParserPrintFileContextInternal (error.c:184)
==100630==    by 0x448B99: xmlReportError (error.c:404)
==100630==    by 0x44FB9C: __xmlRaiseError (error.c:631)
==100630==    by 0x4E5012: xmlFatalErrMsg (parser.c:565)
==100630==    by 0x4E5012: xmlParseDocument (parser.c:10880)
==100630==    by 0x50657F: xmlDoRead (parser.c:15340)
==100630==    by 0x50657F: xmlReadFile (parser.c:15402)
==100630==    by 0x41CD6F: parseAndPrintFile (xmllint.c:2401)
==100630==    by 0x410409: main (xmllint.c:3759)
==100630== 
<!DOCTYPE[<?l?><!ELEMENT�(�,()>
                               ^
==100630== Invalid read of size 4
==100630==    at 0x5BD149: xmlDumpElementContent (valid.c:1181)
==100630==    by 0x5CD871: xmlDumpElementDecl (valid.c:1706)
==100630==    by 0xA06A82: xmlBufDumpElementDecl (xmlsave.c:501)
==100630==    by 0xA06A82: xmlNodeDumpOutputInternal (xmlsave.c:939)
==100630==    by 0xA06A82: xmlNodeListDumpOutput (xmlsave.c:825)
==100630==    by 0xA06A82: xmlDtdDumpOutput (xmlsave.c:749)
==100630==    by 0xA032B2: xmlDocContentDumpOutput (xmlsave.c:1234)
==100630==    by 0xA032B2: xmlSaveDoc (xmlsave.c:1936)
==100630==    by 0x416BA6: parseAndPrintFile (xmllint.c:2705)
==100630==    by 0x410409: main (xmllint.c:3759)
==100630==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==100630== 
==100630== 
==100630== Process terminating with default action of signal 11 (SIGSEGV)
==100630==  Access not within mapped region at address 0x0
==100630==    at 0x5BD149: xmlDumpElementContent (valid.c:1181)
==100630==    by 0x5CD871: xmlDumpElementDecl (valid.c:1706)
==100630==    by 0xA06A82: xmlBufDumpElementDecl (xmlsave.c:501)
==100630==    by 0xA06A82: xmlNodeDumpOutputInternal (xmlsave.c:939)
==100630==    by 0xA06A82: xmlNodeListDumpOutput (xmlsave.c:825)
==100630==    by 0xA06A82: xmlDtdDumpOutput (xmlsave.c:749)
==100630==    by 0xA032B2: xmlDocContentDumpOutput (xmlsave.c:1234)
==100630==    by 0xA032B2: xmlSaveDoc (xmlsave.c:1936)
==100630==    by 0x416BA6: parseAndPrintFile (xmllint.c:2705)
==100630==    by 0x410409: main (xmllint.c:3759)
==100630==  If you believe this happened as a result of a stack
==100630==  overflow in your program's main thread (unlikely but
==100630==  possible), you can try to increase the size of the
==100630==  main thread stack using the --main-stacksize= flag.
==100630==  The main thread stack size used in this run was 8388608.
Segmentation fault

This report was disclosed publicly on HackerOne and belongs to its author and the program. See the original