Linux inetd port theft vulnerability

Summary
Description:Inetd clos()es its sockets sometimes which (if they are unpriviliged) allows a user to just swipe them to put up a trojan service or whatever. Note that users can generally cause inetd to close the port by connecting over and over rapidly to make inetd think there is a loop.
Author:Marc Slemko (marcs@znep.com) posted this, it might have originally been discovered by someone else and I don't have the original post.
Compromise:Steal unpriviliged services from INETD
Vulnerable Systems:Linux, possibly others
Date:28 March 1997
Details

Exploit:
Date: Fri, 28 Mar 1997 02:25:53 -0700 (MST)
From: Marc Slemko 
Reply-To: best-of-security@suburbia.net
To: best-of-security@suburbia.net
Cc: freebsd-security@freebsd.org
Subject: BoS:  Re: Privileged ports...
Resent-Date: Sat, 29 Mar 1997 00:02:35 +1100 (EST)
Resent-From: best-of-security@suburbia.net

On Thu, 27 Mar 1997, Thomas H. Ptacek wrote:

> > I agree completely with you.  It is a very bad thing.  Start with the 
fact
> > that, by default, inetd limits services to being called 256 times a 
minute
> > and then shuts them off and then move on to more devious ways you could
> 
> inetd doesn't release the socket address when it shuts the port off, so I
> doubt you'd be able to bind over something inetd's handling. You do have a

Yes it does.  It close()es the socket.  Try it.  If it didn't, it would
have no nice way of refusing connections other than accepting and 
rejecting them.

$ nc -vv -l -p 1025
retrying local 0.0.0.0:1025 : Address already in use
retrying local 0.0.0.0:1025 : Address already in use
retrying local 0.0.0.0:1025 : Address already in use
retrying local 0.0.0.0:1025 : Address already in use
Can't grab 0.0.0.0:1025 with bind
$ while true; do nc -z localhost 1025
Mar 28 02:18:45 host inetd[190]: blackjack/tcp server failing (looping), 
service terminated
^C
$ nc -vv -l -p 1025
listening on [any] 1025 ...

> potential problem with specific binds (over inetd's INADDR_ANY) in this
> configuration, though.
Yes.  I had thought that this was fixed up, but I guess I was
perhaps thinking of Linux.  Not sure what solution is in place
there, don't follow Linux networking any more.  I know I have an
archived message from Aleph One around here on the subject from
one of the mailing lists around the start of '96.  It was discussed
on several FreeBSD lists at the time, but I'm not sure anything
came of it.

If inetd did not set SO_REUSEADDR, it wouldn't be a problem because anyone
else would be prevented from binding.  However, I don't think that
inetd really has much choice.

OpenBSD has the following in netinet/in_pcb.c: 

        if (so->so_uid) {
                t = in_pcblookup(table, zeroin_addr, 0,
                    sin->sin_addr, lport, INPLOOKUP_WILDCARD);
                if (t && (so->so_uid != t->inp_socket->so_uid))
                        return (EADDRINUSE);
        }

...which prevents a process running as a different user from
binding to the same port.  The other option is to simply disallow
multiple processes from binding to the same port entirely, but that
is a bit extreme and over restrictive.

To emphasize; right now, anyone can steal any connections going
to an unprivileged port that inetd listens on, unless you use something
like the -a option to inetd.  That is bad.  I think something 
resembling the above OpenBSD change is a good idea.  Anyone?

It is a minor waste to add another in_pcblookup call, but a quick
glance shows that it appears to be necessary.

> The real problem, as I see it, is that if reserved ports are enough of a
> security concern for you that you'd dramatically complicate your inetd
> configuration to handle them, you're going to have a real security concern
> if inetd dies. I think it's bad to assume that an unprivileged user can't
> cause a daemon to die.

Yup.  All the issues above are simply examples; fixing them would not
make it worthwhile setting up inetd to prevent other processes 
from binding to the port.

> 
> > are set to a particular default but still allow them to be changed) that
> > handles setting it then add a few lines of code to the kernel to allow 
you
> > to set the uid who can bind to each priv'd port.  There are 1764 other
> > things that it would be useful to be able to set in a similar way,
> 
> Why do you want a UID per reserved port? What is this getting you?

It lets me run my mailer on port 25 as "mail".  It lets me run my
web server on port 80 as "www".  It lets me run my print spooler
on port 515 as "print".  It lets me run my cybercash (whatever 
that is...) on port 551 as "cash".

If someone compromises my www user, my web service is compromised
but my ever-important cybercash service on port 551 is not.  For
many of these programs there are legit reasons why it needs root
for other things and it is normally not as easy as just allowing
a non-root uid to bind to the port, but you have to start somewhere.


More Exploits!

The master index of all exploits is available here (Very large file)
Or you can pick your favorite operating system:
All OS's Linux Solaris/SunOS Micro$oft
*BSD Macintosh AIX IRIX
ULTRIX/Digital UNIX HP/UX SCO Remote exploits

This page is part of Fyodor's exploit world. For a free program to automate scanning your network for vulnerable hosts and services, check out my network mapping tool, nmap. Or try these Insecure.Org resources: