COMMAND
SSH LocalForward
SYSTEMS AFFECTED
Systems running ssh
PROBLEM
Aeneas bumped into a weird 'feature' of ssh 1.2.20. When you run:
ssh -L 80:remotehost:80 remotehost
as a normal user you should get the expected error:
Privileged ports can only be forwarded by root.
But if you put:
LocalForward 80 remotehost:80
in your ~/.ssh/config file and connect to the remote host you
don't get the error and port 80 is opened on the localhost (an
httpd was not running, the port must be available). When you
connect to it you get a normal redirection to remotehost:80 over
the secure channel. This means however that a non-root user is
able to open privileged ports on the localhost and redirect them.
This was checked on Linux and Solaris.
It seems that ssh rejects attempts to forward privileged ports for
non-root users while parsing the command line arguments - the
config file is read further down in the code, without performing a
similar test.
The implications are a bit scary -- on a machine where telnet or
rlogin is normally disabled an ordinary user could set up ssh
port redirection of the telnet or rlogin service to a machine
under their own control. A user with ordinary privileges could
"run" a Web server on a machine not currently running a server
bound to port 80 by redirecting port 80 to another host, etc.
SOLUTION
ssh only has this ability because it is normally installed setuid.
Turning off the setuid bit on the ssh client program doesn't
appear to impair the normal operation of ssh and scp, but it
definitely turns off the hole which allows privileged TCP/IP ports
to be forwarded. So, turn off the setuid bit
chmod u-s /usr/local/bin/ssh
until the posted code fix is installed and tested.
The immediate fix is chmod -s (which will get rid of potential
similar holes in ssh as well...) - the more reasonable method is
to move the check into add_local_forward():
--- readconf.c.orig Sun Aug 3 00:57:21 1997
+++ readconf.c Sun Aug 3 13:20:08 1997
@@ -204,6 +204,10 @@
Forward *fwd;
if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
+ if (port < 1024 && original_real_uid != UID_ROOT)
+ {
+ fatal("Privileged ports can only be forwarded by root.\n");
+ }
fwd = &options->local_forwards[options->num_local_forwards++];
fwd->port = port;
fwd->host = xstrdup(host);