Re: [Fwd: Truth about ssh 1.2.27 vulnerabiltiy]

From: Jeff Long (longat_private)
Date: Thu Sep 30 1999 - 15:28:38 PDT

  • Next message: Eric Griffis: "Re: [Fwd: Truth about ssh 1.2.27 vulnerabiltiy]"

    This is a multi-part message in MIME format.
    --------------AD6746A5F112E9AFFCB93E5F
    Content-Type: text/plain; charset=us-ascii
    Content-Transfer-Encoding: 7bit
    
    Oh crud, this wasn't tested on Digital Unix 4.0D.  It was tested before
    and after on Compaq Tru64 5.0.
    
    Jeff Long
    
    Jeff Long wrote:
    >
    > Dan Astoorian wrote:
    > >
    > > On Wed, 29 Sep 1999 16:59:48 EDT, Sylvain Robitaille writes:
    > > > I don't promise the most impressive code, but it has been tested (on
    > > > Digital Unix) and I believe it works correctly. Comments are of course
    > > > welcome...
    > >
    > > I have a couple of serious concerns about this patch.
    > >
    > > 1) It leaves behind a race condition; a symlink created between the
    > >    lstat() and the bind() will still get happily followed.  The race
    > >    condition could be minimized by moving the lstat() and the bind()
    > >    closer together, but it can't be eliminated this way.  This is why
    > >    it's important for the check to be made in the kernel, where it can
    > >    be done atomically.
    > <snip>
    > > The race condition is a hard problem; if bind() follows symlinks, it is
    > > *impossible* to safely use it in a directory writable by anyone other
    > > than geteuid().
    > >
    > > I haven't looked into what would be involved in creating a proper patch,
    > > but appropriate ways to fix the problem *might* include:
    > >
    > > - changing the process's effective userid/groupid/credentials to match
    > >   the target user before doing the bind(), so that directories not
    > >   writable by the user are also not writable by the code doing the
    > >   bind(); or
    > <snip>
    >
    > Seeing the race problems with the previous two patches I thought I would
    > take a shot at one.  It changes the effective uid/gid to the user
    > logging in before doing the bind() (and then resets them after) which
    > seems to take care of the problem.  It also chown's the
    > /tmp/ssh-<username> directory before doing the bind in the case that it
    > did not already exist so that the user owns it before performing the
    > bind.  On Digital Unix 4.0D this seems to take care of the problem.  The
    > bind() will fail if a symlink exists to a file that the user would
    > normally not be able to write to (such as /etc/nologin).  The only other
    > difference after logging in is that the socket will now be owned by the
    > user instead of root but I can't think of a reason why this would be
    > bad.
    >
    > If anyone sees problems in this patch please let me know.
    >
    > Jeff Long
    --------------AD6746A5F112E9AFFCB93E5F
    Content-Type: text/plain; charset=us-ascii;
     name="newchannels.c.patch"
    Content-Transfer-Encoding: 7bit
    Content-Disposition: inline;
     filename="newchannels.c.patch"
    
    *** newchannels.c.original	Thu Sep 30 16:58:22 1999
    --- newchannels.c	Thu Sep 30 17:13:24 1999
    ***************
    *** 2262,2267 ****
    --- 2262,2269 ----
        struct stat st, st2, parent_st;
        mode_t old_umask;
        char *last_dir;
    +   uid_t saved_euid = 0;
    +   gid_t saved_egid = 0;
    
        if (auth_get_socket_name() != NULL)
          fatal("Protocol error: authentication forwarding requested twice.");
    ***************
    *** 2411,2427 ****
           creating unix-domain sockets, you might not be able to use
           ssh-agent connections on your system */
        old_umask = umask(S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
    !
    !   if (bind(sock, (struct sockaddr *)&sunaddr, AF_UNIX_SIZE(sunaddr)) < 0)
    !     packet_disconnect("Agent socket bind failed: %.100s", strerror(errno));
    !
    !   umask(old_umask);
    !
        if (directory_created)
          if (chown(".", pw->pw_uid, pw->pw_gid) < 0)
            packet_disconnect("Agent socket directory chown failed: %.100s",
                              strerror(errno));
    
        /* Start listening on the socket. */
        if (listen(sock, 5) < 0)
          packet_disconnect("Agent socket listen failed: %.100s", strerror(errno));
    --- 2413,2442 ----
           creating unix-domain sockets, you might not be able to use
           ssh-agent connections on your system */
        old_umask = umask(S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
    !
        if (directory_created)
          if (chown(".", pw->pw_uid, pw->pw_gid) < 0)
            packet_disconnect("Agent socket directory chown failed: %.100s",
                              strerror(errno));
    
    +   saved_euid = geteuid();
    +   saved_egid = getegid();
    +
    +   if (setegid(pw->pw_gid) < 0)
    +       packet_disconnect("Agent socket setegid failed: %.100s", strerror(errno));
    +   if (seteuid(pw->pw_uid) < 0)
    +       packet_disconnect("Agent socket seteuid failed: %.100s", strerror(errno));
    +
    +   if (bind(sock, (struct sockaddr *)&sunaddr, AF_UNIX_SIZE(sunaddr)) < 0)
    +     packet_disconnect("Agent socket bind failed: %.100s", strerror(errno));
    +
    +   if (seteuid(saved_euid) < 0)
    +       packet_disconnect("Agent socket re-seteuid failed: %.100s", strerror(errno));
    +   if (setegid(saved_egid) < 0)
    +       packet_disconnect("Agent socket re-setegid failed: %.100s", strerror(errno));
    +
    +   umask(old_umask);
    +
        /* Start listening on the socket. */
        if (listen(sock, 5) < 0)
          packet_disconnect("Agent socket listen failed: %.100s", strerror(errno));
    
    --------------AD6746A5F112E9AFFCB93E5F--
    



    This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 15:06:18 PDT