Attacking the Tor Control Port with Java

Java Vulnerabilities

On 3 October 2007, Sun announced several critical security updates for the Java Runtime Environment on their security blog. In particular, this notification describes how network access restrictions can be circumvented to connect to arbitrary hosts by utilizing DNS rebinding.

The background (and additional references) for these issues are described in detail at http://crypto.stanford.edu/dns/ and http://seclists.org/fulldisclosure/2007/Jul/0159.html. The Stanford DNS rebinding paper describes the past and present of DNS rebinding vulnerabilities and attacks and then suggests some possible mitigation strategies.

Impact on Tor Control Port

The Tor download page specifically warns about the impact on anonymity of browser plugins and offers several suggested workarounds if active content is required (e.g., Java, JavaScript, Flash, etc.). Although these suggestions may address some anonymity concerns, they do not provide protection against client-side attacks that target the control port.

If the control port is exposed when Tor is running, attacks can originate from either requests performed through Tor or from outside out it. In other words, you may still be a risk if you always leave Tor running while retrieving active content without using the Tor network. For example, if one uses the suggestion to use two browsers (one for "unsafe" browsing and one for Tor), the control port can still be attacked through the unsafe browser if the port is accessible on the local machine.

Beginning with the 0.1.2.16 release of Tor, the control port will disconnect after a single failed authentication command. This prevents simple form submission attacks from working if the NULL authentication method is used. When the HTML form is submitted, the HTTP request sequence will cause an immediate authentication failure and the session will be disconnected. Prior versions allowed repeated attempts until a valid AUTHENTICATE command was received.

Java exposes a programmatic sockets interface that allows for arbitrary reading and writing of data once a socket connection has been established. Consequently, a malicious applet can construct properly formed control port commands without triggering a disconnect. If the control port is enabled with the NULL authentication and accessible to the web browser, the malicious applet can authenticate and send arbitrary commands.

Tor users with the following conditions may be at risk:

Use of proxy switching browser add-ons (e.g., Torbutton, FoxyProxy) may increase this risk if the Java Virtual Machine can perform arbitrary DNS resolution through the native operating system resolver. Since the JVM is going to attempt its own name resolutions, the browser's configuration with respect to name look-ups over SOCKS is important. A malicious site can use that the fact that multiple resolvers are being used (one proxying through Tor, the other from the operating system) to return different DNS responses in order to facilitate rebinding attacks. If the JVM is completely prevented from resolving host names, it should not be able to connect to the specified host (although some past Java versions are rumored to allow this).

Workarounds

Demonstration

A simple demonstration has been developed and tested with the following:

It is doubtful that the demo will work with other browsers but may work with older Java versions. If you don't have Tor installed, you can still test the demonstration by using this simple fake-control-port.pl Perl script to emulate the control port. It echos the request and assumes everything always succeeds.

The demonstration has been developed utilizing LiveConnect. It uses the document.domain exception to the same origin policy to set the document domain to localhost.pseudo-flaw.net; this is a suffix of the original domain. By design, localhost.pseudo-flaw.net resolves to 127.0.0.1. As a result, the browser's same-origin policy rules are met and the Java Virtual machine resolves the address as a reference to the local host.

The demonstration is available here.

Java Runtime Environment (JRE) 6 Update 3

The updated JRE 6u3 is currently available to download. After applying the update, the demonstration stopped working.

It appears that the JVM has been updated to use the Host Name Authorization technique discussed in the Protecting Browsers from DNS Rebinding Attacks paper. Examining the traffic when attempting the demonstration, it is apparent that requests are being made for the 'auth' names:

23:32:41.677095 IP 192.168.65.129.32769 > 192.168.65.2.53:  57241+ A? localhost.pseudo-flaw.net. (43)
23:32:41.693732 IP 192.168.65.2.53 > 192.168.65.129.32769:  57241 1/13/13 A 127.0.0.1 (500)
23:32:41.695493 IP 192.168.65.129.32769 > 192.168.65.2.53:  56063+ A? localhost.pseudo-flaw.net.auth.1.0.0.127.in-addr.arpa. (71)
23:32:41.709082 IP 192.168.65.2.53 > 192.168.65.129.32769:  56063 NXDomain* 0/1/0 (127)
23:32:41.709380 IP 192.168.65.129.32769 > 192.168.65.2.53:  56770+ A? localhost.pseudo-flaw.net.auth.1.0.0.127.in-addr.arpa.localdomain. (83)
23:32:41.754285 IP 192.168.65.2.53 > 192.168.65.129.32769:  56770 NXDomain 0/1/0 (158)

In this case, the demonstration fails to work because the JVM cannot resolve the 'localhost.pseudo-flaw.net.auth.1.0.0.127.in-addr.arpa.' name and prevents the socket connection from occurring.

Unfortunately, I'm not entirely sure that this was implemented correctly. According to the DNS rebinding paper, a request should be first made for 'auth.1.0.0.127.in-addr.arpa.' to maintain backwards compatibility, but I never see this. The first look-up is supposed to determine if the site is policy-enabled or not. If the site isn't policy enabled, then the subsequent auth requests are not supposed to be made.

So, I'm not sure if this initial 'auth' request is being intercepted by the operating system resolver or not. But based on my experimentation, it appears that normal sites that do not have a mapping between A and PTR records no longer have the ability to create Java sockets. Only by providing the full auth policy record can the socket be created. I believe RSnake was right about the Hostname Authorization can of worms.

But in any case, if a malicious user can either poison the DNS cache or return a bad IP address for the full auth DNS query, the traffic pattern changes to:

23:37:36.792466 IP 192.168.65.129.32769 > 192.168.65.2.53:  53308+ A? localhost.pseudo-flaw.net. (43)
23:37:36.828790 IP 192.168.65.2.53 > 192.168.65.129.32769:  53308 1/2/2 A 127.0.0.1 (139)
23:37:36.830362 IP 192.168.65.129.32769 > 192.168.65.2.53:  18524+ A? localhost.pseudo-flaw.net.auth.1.0.0.127.in-addr.arpa. (71)
23:37:36.831309 IP 192.168.65.2.53 > 192.168.65.129.32769:  18524* 1/0/0 A 127.0.0.1 (87)

And the demonstration succeeds! So moral of the story: if you don't trust the person who is resolving your DNS requests, you may want to re-evaluate your exposure.

Future Research

Some versions of Flash support sockets and don't require a crossdomain.xml file for ports >1024. If DNS rebinding to localhost is possible with the Flash plugin, then the control port could be vulnerable to attack.