Subject: Re: [Tsvwg] I-D Action:draft-ietf-tsvwg-port-randomization-02.txt

From: Joe Touch <[email-masked]>
Date: Tue, 02 Sep 2008 14:53:01 -0700

> 	Title           : Port Randomization
> 	Author(s)       : M. Larsen, F. Gont
> 	Filename        : draft-ietf-tsvwg-port-randomization-02.txt
> 	Pages           : 28
> 	Date            : 2008-08-31
Hi, Fernando,

A few comments, the latter mostly by Ananth's draft:

- - it might be useful to simplify the abstract
	some of the context can be moved to the intro,
	i.e., the abstract can just refer to being
	'inspired by recent attacks' as RFC1948 does

- - it might be useful to refer to RFC1948 earlier, e.g.,
in the intro
	this doc very closely parallels RFC1948, so
	raising that point earlier might be useful to
	the reader

- - I'm not clear on the utility of the bit array to avoid reserved ports
	if the source port is selected on CONNECT, the TCB
	will be correctly associated with the issuing process,
	not any other process listening on that port

	the only value is in debugging - i.e., assuming that
	port=service, but that doesn't always mean anything
	specific anyway, since kernel's don't prohibit use of
	allocated ports anyway (i.e., no reason this mechanism
	needs to do more than a kernel would in preventing a user
	from setting a specific source port at the app layer)

Joe

---

From: Fernando Gont <[email-masked]>
Date: Tue, 02 Sep 2008 20:08:25 -0300

Hello, Joe,

Comments inline....

>         'inspired by recent attacks' as RFC1948 does

Ok. Will do.

>         raising that point earlier might be useful to

The "problem" here here is that the current draft does not propose 
any particular algorithm for doing port randomization. In the first 
few versions of the document, we were pushing algorithms #3 and 
algorithm #4. But now that the document does not push any particular 
algorithm, mentioning RFC1948 like that would be misleading. However, 
I guess the intro might introduce the algorithms with something like 
"This algorithm describes four different algorithms for selecting 
ephemeral port numbers. Two of them are based on the randomization 
function already available in most systems, while the others paralell 
RFC 1948 to produce a linear sequence from a random starting point". 
Please let me know what you think.

>         not any other process listening on that port

I guess the problem here is that some systems (FreeBSD, IIRC) are not 
able to reuse port numbers if they are already in use for some other 
connection.

That said (and thinking out loud), maybe one should check whether, at 
least for those ports in the bit array, there's a socket in the 
LISTENING state. If there is, then that port number should not be 
used for outgoing connections, as an attacker could send a SYN at the 
same time a incoming SYN is received for the same four-tuple, thus 
*accepting* an incomming conenction (simultaneous open).

Thanks for your feedback, Joe!

Kind regards,

--
Fernando Gont
e-mail: [email-masked] || [email-masked]
PGP Fingerprint: 7809 84F5 322E 45C7 F1C9 3945 96EE A9EF D076 FFF1

---

From: Joe Touch <[email-masked]>
Date: Tue, 02 Sep 2008 16:46:50 -0700

Hi, Fernando,

> Hello, Joe,
...
> The "problem" here here is that the current draft does not propose any
> particular algorithm for doing port randomization. In the first few
> versions of the document, we were pushing algorithms #3 and algorithm
> #4. But now that the document does not push any particular algorithm,
> mentioning RFC1948 like that would be misleading. However, I guess the
> intro might introduce the algorithms with something like "This algorithm
> describes four different algorithms for selecting ephemeral port
> numbers. Two of them are based on the randomization function already
> available in most systems, while the others paralell RFC 1948 to produce
> a linear sequence from a random starting point". Please let me know what
> you think.

The broader point is that the whole document parallels RFC 1948, which
is why I would expect it to be referred to in the first few sentences.

The fact that 1948 specifies a particular algorithm is a secondary issue.

> able to reuse port numbers if they are already in use for some other

Reuse if in-use is one thing - in that case, your array is just a cached
version of the TCB states (more efficient to check, but needs to be
maintained in parallel with the TCBs). That's fine, though just an
implementation issue.

> LISTENING state. If there is, then that port number should not be used
> for outgoing connections, as an attacker could send a SYN at the same
> time a incoming SYN is received for the same four-tuple, thus

That matters only if you match ISNs; otherwise, you'd just clobber both
connections.

- ---

I thought your array was more of "don't use 25, 80, 443, 110, etc.
because they're assigned". That's the one I was thinking wasn't
necessary at all...

Joe

---

From: Fernando Gont <[email-masked]>
Date: Tue, 02 Sep 2008 20:59:01 -0300

Hello, Joe,

>The fact that 1948 specifies a particular algorithm is a secondary issue.

mmm... not sure what you mean. i.e., Why do you think e.g., algorithm 
#1 and algorithm #2 have to do with RFC1948?

>maintained in parallel with the TCBs). That's fine, though just an

Say you use 6667 as an ephemeral port. If at some point you want to 
ran an IRC server, you won't be able to. (samething for a web proxy 
in port 8080, etc.)

That's the reason why you avoid using those ports from starters.

Am I missing something?

>That matters only if you match ISNs; otherwise, you'd just clobber both

Why wouldn't the ISN's match? If the two SYNs cross each other on the 
wire, then both SYNs will be retransmitetd, with matching sequence numbers.

>because they're assigned". That's the one I was thinking wasn't

FWIW, I had submitted a patch for FreeBSD to use the port range 
1025-65535 for the ephemeral ports. But was asked to change it to 
10000-65535, as there were a number of services (e.g., the X server) 
that used ports in that range.

Thanks!

Kind regards,

---

From: Joe Touch <[email-masked]>
Date: Tue, 02 Sep 2008 23:24:31 -0700

Hi, Fernando,

Fernando Gont wrote:
> mmm... not sure what you mean. i.e., Why do you think e.g., algorithm #1
> and algorithm #2 have to do with RFC1948?

Neither algorithm is related to RFC1948. Randomizing the source port to
protect a connection is very similar to randomizing the ISN to protect
the SYN exchange - that's the similarity I'm referring to.

> Say you use 6667 as an ephemeral port. If at some point you want to ran
> an IRC server, you won't be able to. (samething for a web proxy in port
> 8080, etc.)
> 

I think we're talking past each other.

Let's say I use 6667 as the source port of a connection. That has
nothing to do with then issuing a listen on port 6667; that listen
should affect only subsequent connections that are issued - and only
inbound ones. E.g., even after I issue a listen on port 6668, I should
still be able to connect using an explicit source port of 6668.

> wire, then both SYNs will be retransmitetd, with matching sequence numbers.

Actually, if the SYNs cross, as you note, there would be a simultaneous
open (no retransmission, just SYN-ACKs). However, that can happen for
any connection anyway. It doesn't matter if the source port is
privileged; that matters only for incoming connections anyway - for
outgoing connections, the process issuing the CONNECT is the one that
owns the TCB, regardless of which other processes are LISTENing to any
ports.

I.e., this isn't a new attack or a new vulnerability - outgoing
connections can always be spoofed into simultaneous opens, and only the
process of the outgoing call is vulnerable.
> that used ports in that range.

That seems like it only makes sense for debugging, where people *assume*
(incorrectly) that the port number defines the process when it's
well-known. That's true only for incoming connections, and it seems like
the OS could flag such TCBs anyway (i.e., based on how they were opened,
at open-time).

Joe

---

From: Fernando Gont <[email-masked]>
Date: Wed, 03 Sep 2008 03:32:57 -0300

>the SYN exchange - that's the similarity I'm referring to.

Ok. Now I see your point. Will do.

>still be able to connect using an explicit source port of 6668.

That does not happen in practice. Servers usually set the 
SO_REUSE_ADDR option for this to allow re-bind()ing the same port (in 
case you want to kill and restart a daemon). But as clients do not 
set this option, if some port is in use for an outgoing connection, 
then no server will be able to bind() it and listen on it.

>process of the outgoing call is vulnerable.

My take is that if you currently cannot use a port as an ephemeral 
port if there's a service listen()ing on that port, and we change 
that behavior to allow that, that would be a new vulnerability. That 
would open the door for an attacker to steal incoming connections if 
he can "fake" a simultaneous open for an incoming connection.

>the OS could flag such TCBs anyway (i.e., based on how they were opened,

Their argument was the same argument I made above: if those ports 
were used as ephemeral ports, at some point later a server would not 
be able to bind() them, and would fail.

Thanks!

Kind regards,

---

From: Joe Touch <[email-masked]>
Date: Tue, 02 Sep 2008 23:56:14 -0700

Fernando Gont wrote:
...
> That does not happen in practice. Servers usually set the SO_REUSE_ADDR
> option for this to allow re-bind()ing the same port (in case you want to
> kill and restart a daemon). But as clients do not set this option, if
> some port is in use for an outgoing connection, then no server will be
> able to bind() it and listen on it.

A client that doesn't set SO_REUSEADDR only means that the server can't
open a connection matching the whole 5-tuple until the TIME-WAIT
expires. A server should still be able to listen on a more general
(localport=6667, remoteport=any) even if there's a client open (not just
even in TIME-WAIT) on a more specific (localport=6667,
remoteport=10001). I don't recall less-specific binding code checking to
make sure there were NO connections on that port...

> My take is that if you currently cannot use a port as an ephemeral port
> if there's a service listen()ing on that port, and we change that
> behavior to allow that, that would be a new vulnerability. That would
> open the door for an attacker to steal incoming connections if he can
> "fake" a simultaneous open for an incoming connection.

Attackers can already fake those simultaneous opens. The open affects
only the service being connected at that time. If you listen on SMTP
(25), then issue a connect with local port 25 from a new-app, the
simultaneous open could hijack the new-app process, but not SMTP.

I.e., the incoming SYN goes to SMTP only for TCBs in the (virtual)
'closed' state. An incoming SYN for a connection in the SYN-SENT state
goes to that TCB; that TCB is bound to new-app in the above case, at the
time of the CONNECT call.

Joe

---

From: Fernando Gont <[email-masked]>
Date: Wed, 03 Sep 2008 04:31:46 -0300

>make sure there were NO connections on that port...

I agree with your point, but that doesn't happen in practice. The 
reason for which servers set SO_REUSEADDR is that, if they don't, you 
cannot restart a server if there's any active connection. (in any 
state) You might call this a bug, but....

>time of the CONNECT call.

If you (legitimately) listen on *:25, or even, say, IPaddress:25, but 
an attacker binds IPaddress:25 and sends a request to targetIP:target 
port, he will hijack a conenction, as his socket pair is more 
specific than that of the (legitimate) server. I think we agree on this one.

(In the case of any port < 1024, that wouldn't be much of a problem, 
as unix systems have traditionally required superuser privileges to 
bind those ports, though)

Kind regards,

---

From: Joe Touch <[email-masked]>
Date: Wed, 03 Sep 2008 06:40:22 -0700

Fernando Gont wrote:
> I agree with your point, but that doesn't happen in practice. The reason
> for which servers set SO_REUSEADDR is that, if they don't, you cannot
> restart a server if there's any active connection. (in any state) You
> might call this a bug, but....

I'll look at the source code. This sounds like a bug.

> If you (legitimately) listen on *:25, or even, say, IPaddress:25, but an
> attacker binds IPaddress:25 and sends a request to targetIP:target port,
> he will hijack a conenction, as his socket pair is more specific than
> that of the (legitimate) server. I think we agree on this one.

If I listen on *.25, and the attacker binds to IPaddress:25, that
binding is more specific only if both processes are on the same host.
That's an OS issue to resolve - i.e., determining whether the attacker
should be able to bind to a more specific address if there's a 'hit' on
an existing listen.

AFAICT, the test of a 'hit' on a listen is all that should happen; it
doesn't matter if there is a 'hit' on an existing, active connection.
The hit on the listen should happen in the OS; it shouldn't need to be
described in the protocol doc.

> (In the case of any port < 1024, that wouldn't be much of a problem, as
> unix systems have traditionally required superuser privileges to bind
> those ports, though)

That's an OS issue as well; the meaning of those ports as privileged
seems like it should go away as well (IMO).

Joe

---

From: Fernando Gont <[email-masked]>
Date: Wed, 03 Sep 2008 11:21:00 -0300

>I'll look at the source code. This sounds like a bug.

I'll look, too. BTW, I recall that Stevens TCP book describes it, 
even with some test code (TCP/IP Illustrated, Volume 1, and probably 
in UNPv1, too).

>described in the protocol doc.

To some extent, there's some talk about that in RFC793 itself. I'm 
not saying that we should state what should be the result if there's 
such a hit. But clearly, that issue is something we should keep in 
mind if we want our proposal to be implement from the RFC.

>seems like it should go away as well (IMO).

I agree. Particularly in an era of personal computers, where in many 
cases there's a single user on the system, and thus anybody can be 
running a service on ports < 1024, without this fact implying that 
they are "administrators".

That said, I don't think that meaning will go away in the UNIX circles....

Kind regards,

---

From: Joe Touch <[email-masked]>
Date: Wed, 03 Sep 2008 07:41:37 -0700

Hi, Fernando (et al.),

Overall, regarding the issue of port reuse, it seems like it would be
useful to note, essentially:

1. port reuse on the local end is a local matter, and already is/should
be handled there

2. port reuse on the remote end may be amplified by randomization,
largely due to the (incorrect) assumption that rollover of sequential
port assignment would take more than 2*MSL (and thus avoid TIME-WAITs on
the remote end)

You already focus on #2 in section 2.3. I agree that Ananth's document
doesn't really add to what you already present there.

IMO, algorithms to solve either of these two are local decisions.

Finally, neither #1 nor #2 is really an issue if you assume that port
spaces already wrap around, which they do on fast servers, and could
easily even on a client these days. Picking ports from the emphemeral
range only helps, but doesn't completely solve the problem, because both
ends can be picked from this range, e.g., for dynamically-negotiated
connections.

I think at this point it's worth pointing to RFC1948, which notes that
the only definitive way to solve this is to use TIME-WAIT on both sides
after a CLOSE, and just say that if chosen, the solution is
implementation-dependent.

Joe