3

Can malicious JavaScript defeat source-port randomization in browsers?

I am reading a research paper which seems to claim that the answer is yes:

many browsers seem to always assign a random local port number for different web pages which makes [source] port prediction very difficult. To overcome the challenge, we design a simple strategy to intentionally occupy as many local ports as possible so that the next port used is selected from a much smaller pool.

Specifically, the malicious website can instruct the client to open many connections to the malicious site (or any other server) to consume a large number of local ports. In addition, the occupied port numbers tend to be contiguous according to our experiment likely due to the origination from the same JavaScript. One challenge is that the OS may limit the total number of ports that an application can occupy, thus preventing the attacker from opening too many concurrent connections. Nevertheless, we found such limit can be bypassed if the established connections are immediately closed (which no longer counts towards the limit). The local port numbers are still not released since the closed connections enter the TCP TIME WAIT state for a duration of 1–2 minutes. If an attacker can manage to open enough connections, he can easily use brute force [to guess the source port of the next request].

Conceptually, the attack seems to go like this. Suppose the victim visits a malicious web page, evil.com, controlled by the attacker. evil.com serves up some JavaScript that opens many connections to evil.com, in an attempt to exhaust the pool of local source ports. Then, the JavaScript redirects the browser to www.amazon.com (or opens an iframe to www.amazon.com). The claim is that their method enables them to predict the TCP source port number that will be used in that connection to www.amazon.com.

Is this right? Does this attack work?

If the attack works, I have some questions about how/why the attack works:

  • Do browsers manage a pool of local ports themselves, or do they ask the OS to allocate a local port for them? What pool is getting exhausted here?

  • If the OS is allocating the source port, isn't the source port specific to the destination server? (I can open many connections to evil.com and exhaust all available local ports to evil.com, but I'd expect that a new connection to www.amazon.com could use any source port, even one that is currently being used with www.evil.com or has recently been used with www.evil.com. Am I misunderstanding something?)

  • Or is the browser somehow manually managing a pool of local ports it is prepared to use for connections? If so, what strategy does it use? Is this browser-dependent?

  • How does the attacker predict what the source port number will be used for the connection to www.amazon.com?

I was hoping someone might be able to help me understand what's going on here, and fill in the missing details.

1 Answer 1

2

As far as I know, the kernel will allocate a new local port for each outgoing connection (unless the application enforced a specific port value with bind() -- this can be done even for a TCP client) and will not allow two outgoing connections to use the same local port simultaneously. Indeed, if you try to force two client connections to use the same local port number, with explicit bind() calls, the second bind() should fail.

A Linux will allocate local ports in the 32768-61000 range (see this page). This is system-wide.

I doubt Web browsers select specific local ports. I do not see what this would buy them, and, moreover, this will be lost when traversing a router which does some NAT -- a very common thing, both for home users and enterprises.

Guessing the local port in advance does not give an advantage per se to the attacker -- it can be part of a larger attack which also guesses TCP sequence numbers (which seems harder).

Edit: actually Linux will allow a port to be reused for another connection while the first one is still active, but this does not happen often. Linux randomizes ephemeral ports (see RFC 6056) so, generally, a new port will be used. When the application does an explicit pre-connect bind(), a new port is necessarily allocated, since at that time, the kernel does not know the target address yet. For a bind-less connect(), another algorithm is used, which tends to prefer using a new port but may reuse an older. See this blog post for an analysis.

2
  • Fascinating! A simple experiment confirms your description of kernel behavior (at least on Linux). Do you know why the kernel requires the local port to be unique, even across two connections to two different servers? It seems like it would be perfectly fine to re-use the same local port number, as long as the 4-tuple (localaddr,localport,serveraddr,serverport) is different for each connection. Do you know why OS's refuse to reuse the same local port number for two different connections to two different servers?
    – D.W.
    Sep 27, 2012 at 21:53
  • 1
    @D.W.: apparently this is a matter of circumventing the BSD API (bind() before connect()) and a side-effect of port randomization, and the usual evil, performance (it is faster to do a port-only lookup than taking addresses into account). Sep 27, 2012 at 22:53

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .