COMMAND
bind()
SYSTEMS AFFECTED
Linux, SunOS, FreeBSD, BSDI, Ultrix, probably others.
PROBLEM
Credit fot this goes to *Hobbit*, bitblt and Aleph One. On most
systems, a combination of setting the SO_REUSEADDR socket option,
and a call to bind() allows any process to bind to a port to
which a previous process has bound width INADDR_ANY. This allows
a user to bind to the specific address of a server bound to
INADDR_ANY on an unprivileged port, and steal its udp packets/tcp
connection.
Exploit should go as follows. Download and compile netcat from
some site that has it (search engine will solve problems for you).
Make sure an nfs server is running:
w00p% netstat -a | grep 2049
udp 0 0 *.2049 *.* LISTEN
Run netcat:
w00p% nc -v -v -u -s 192.88.209.5 -p 2049
listening on [192.88.209.5] 2049 ...
Wait for packets to arrive.
SOLUTION
Linux: A patch was been sent to Linux and Alan Cox. It should be
included with 1.3.60. Aleph One's original patch (included
bellow) allows for binds from the same uid, as some virtual
hosting software like modified httpds, and ftpds, may break
otherwise.
Alan didnt like this, so all bind to the same port will not be
allowed in newer kernels. You should be able to easily adapt this
patch or Alan's patch to 1.2.13 without much trouble. Others:
Pray to your vendor, but since this is older bug by now, you
should have patch or at least something.
--- begin patch ---
diff -u --recursive --new-file linux-1.3.57/net/ipv4/af_inet.c linux/net/ipv4/af_inet.c
--- linux-1.3.57/net/ipv4/af_inet.c Mon Dec 25 20:03:01 1995
+++ linux/net/ipv4/af_inet.c Tue Jan 16 19:46:28 1996
@@ -46,6 +46,8 @@
* Germano Caronni : Assorted small races.
* Alan Cox : sendmsg/recvmsg basic support.
* Alan Cox : Only sendmsg/recvmsg now supported.
+ * Aleph One : Rogue processes could steal packets
+ * from processes bound to INADDR_ANY.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -899,6 +901,12 @@
if (sk2->num != snum)
continue; /* more than one */
+ if ((sk2->rcv_saddr == 0 || sk->rcv_saddr == 0) &&
+ current->euid != sk2->socket->inode->i_uid)
+ {
+ sti();
+ return(-EADDRINUSE);
+ }
if (sk2->rcv_saddr != sk->rcv_saddr)
continue; /* socket per slot ! -FB */
if (!sk2->reuse || sk2->state==TCP_LISTEN)