Last Call Review of draft-ietf-tsvwg-port-randomization-
I am reviewing this document as part of the security directorate's ongoing effort to review all IETF documents being processed by the IESG. These comments were written primarily for the benefit of the security area directors. Document editors and WG chairs should treat these comments just like any other last call comments. Feel free to forward to any appropriate forum.
This document (targeting BCP status) describes an obscure but important practice regarding the selection of ephemeral port IDs when creating TCP connections. If an attacker can guess the ephemeral port used by a TCP connection between some pair of nodes, it greatly increases the chances he can corrupt the data being passed over that connection or cause the connection to break. To make such an attack harder, the originators of TCP connections should pick the ephemeral port number randomly (or at least unpredictably) from a large set of available ports.
For some arcane reasons, picking ports strictly randomly is not the best you can do, because some choices don't work out. If you pick a port number that has used for a recently closed TCP connection to the same IP address, the other end might become confused, think that the old connection is continuing, and generally mess things up. (Most applications will eventually sort themselves out after some timeouts and retries, but it is not guaranteed). Another possible problem is that if someone starts listening on the port you selected and the timing is "just wrong", you connection could become confused with one of his.
These problems can be almost certainly avoided by picking ports from a particular narrow range and picking them in sequence so that no port number is reused until all have been used once. Unfortunately, doing that increases the chance that an attacker can predict the port some new connection will choose.
This document describes how various implementations trade-off these two conflicting goals, and makes recommendations as to how a new implementation might pick an algorithm.
Unfortunately, this algorithm is a cryptographers dream with lots of opportunities to make micro-optimizations. I could not resist the temptation to do so myself when reading the document, but I *can* resist the temptation to tell anyone about the resulting algorithm. There are only 64K ports, so nothing anyone can do is going to make a cryptographically significant improvement over the proposals made here, and spending time debating whether my algorithm beats your algorithm is a waste of everyone's time.
Detailed security-relevant comments:
p13 para 2: says random must return integers in the range 0 - (2^n-1) where n>15. Larger values of n (e.g. n=31) are preferred, since otherwise distribution when reduced mod num_ephemeral will not be uniform.
p16 para 2: suggests use of MD5, which is fine from the point of view of documenting current practice, and in fact is cryptographically just fine in this context. Nevertheless, crypto weenies the world over will pounce on you if it looks like you're suggesting that people use it. It's probably better to just suggest "some cryptographic hash function", or if you have to suggest something specific, perhaps SHA-256. The appendix at the end should specify the hash algorithm used by existing implementations.
Your sample code in many cases, but in particular on page 17 figure 5 ignores the possibility of integer overflow when incrementing things (e.g. table[index]++). The results of modular arithmetic when one of the operands is negative is language dependent, and in ANSI C is not defined, so this code could corrupt memory (unless the values being incremented are unsigned).
p20 para 2: suggests use of a 32 bit key, which has exploitable security problems even though MD5 is fine. 64 bits is a bare minimum, and since bits are cheap someone should really use 128.
p20 last 2 lines: use of pseudo-random data is never harmful and might help, so "should not be done" seems a little strong.
p24 para 3: Since the local offset function is a cryptographic hash reduced to a small number of bits, there will be identical offsets for different inputs and they are generally harmless. If they occurred at greater frequency than would be expected by chance, the port-offset mechanism proposed in this document would have a reduced effect.
p24 para 4: Similarly, seeding the random number generator with a good source of randomness will make an implementation more secure, but "must" is a bit strong.
Detailed non-security relevant comments:
The document is titled "Transport Protocol Port Randomization Recommendations", but it doesn't really make recommendations. It enumerates current practice and calls out the pros and cons, but it doesn't really recommend what an implementer should do. That's probably OK, but it seemed a bit odd.
p6 last para section 1: Given that this document never uses SHOULD, MUST, ... outside of this paragraph, does it really need this paragraph and the reference to RFC 2119?
p7 end of section 2.1 says ports in the range 49152-65535 are meant for the selection of ephemeral ports
p12 1st para says: "ephemeral port selection algorithms should use the whole range 1024-49151". Is this saying you should use port numbers not intended for this use? Do you mean should use the whole range 1024-65535?
p12 line 2: "is not affected is not affected" -> "is not affected"
p13 para 2 line 2: "interger" -> "integer"
p16 para 3: "chosen as random as possible" -> "chosen to be as random as possible"
p20 para 3: "reasonable" -> "reasonably"