Why you can't mix wildcard IP port binding with other bindings

July 18, 2006

A while back I wrote, about TCP port binding:

Unfortunately, you can't bind a port to the generic wildcard address if anyone is using the port on a specific IP address, hence the Apache restart problem. (Why this port binding limitation is a sensible is beyond the scope of this margin, but it is, however annoying it periodically is.)

Today I feel like explaining why. The core problem is deciding who gets handed a new connection (or for UDP, a new packet); if you allow multiple binding, all of the possible answers create security issues.

Imagine that a hypothetical system allowed two different programs to listen for connections on port 3000, one with a wildcard address (aka INADDR_ANY) and one specifically with the local address 127.0.0.1. There are generally three useful answers for who gets the connection when someone connects to port 3000 on 127.0.0.1:

  1. the program that bound the port with the 127.0.0.1 address.
  2. the program that bound the port with the wildcard address.
  3. something different for each connection (a random choice, the first program to call accept(), strict alternation, etc).

All of these let a malicious program steal incoming connections from a legitimate program and do nasty things with them. The first two are mirrors of each other and each can hose you in the right circumstances, and the third just means that the malicious program steals only some of the connections instead of all of them.

The one limited way out that I can see is to make binding the second port succeed only if the process doing so is privileged, and have it forcefully close the first port. (If you don't force-close the first port, you open daemons up to subtle connection stealing attacks when they're restarted or started after boot.)

But, really, the simplest way out is to prevent the whole situation coming up in the first place, which is exactly what Unix does. (I suspect Windows does likewise, but I don't know for sure.)

(PS: the title of this entry illustrates how I sometimes can't write good titles.)


Comments on this page:

From 128.100.8.31 at 2006-07-18 14:32:51:

But, really, the simplest way out is to prevent the whole situation coming up in the first place, which is exactly what Unix does.

Not all Unix, necessarily. At least as late as Solaris 8 FCS, it was quite possible for an unprivileged user to bind to a port >1023 on a specific IP address and steal connections from a daemon listening on the wildcard.

Sun introduced the (non-public) TCP_EXCLBIND and UDP_EXCLBIND socket options to try to deal with this problem, and supposedly it's now the default for RPC services which bind using TLI, but it can't be made the general socket default for stupid standards compliance reasons.

Various other flavours of Unix probably have their own issues.

--Dan Astoorian

By cks at 2006-07-18 15:24:46:

Solaris 9 seems to have changed that; a quick set of Python test programs gets EADDRINUSE for such overlapping bindings (and truss says that they aren't using any funny socket options). Which is good, because allowing it is an augh thing to do; I wonder what specification Solaris 8 was following that was so braindead.

Written on 18 July 2006.
« Thesis: SMP is a failure for most Internet servers
Link: 'Document Centric' »

Page tools: View Source, View Normal, Add Comment.
Search:
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Tue Jul 18 03:12:32 2006
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.