Java security allows for safe excecution of code from an untrusted source, usually web applets. But java.net.(Http)URLConnection implementations could be tricked into irregular HTTP requests, bypassing Java network access policy that would otherwise apply. Only systems with a HTTP proxy configured could be vulnerable. One exploit is where a remote server, aided by a hostile applet, hijacks a browsers persistent HTTP connection to its configured HTTP proxy.
Sun Security Bulletin #00216
Microsoft Security Bulletin MS02-013
bugtraq id 4228
Vulnerability identifier CAN-2002-0058 (under review)
Secure Coding Antipatterns: Avoiding Vulnerabilities, TS-1238 (slide 25-30).
Shortly after I, more or less by coincidence, discovered the issue, I reported it to Sun on April 07, 2001. They communicated it to their Java licensees, and coordinated a synchronized response.
I audited both Kaffe and GNU Classpath class libraries, and to the best of my knowledge, they are not vulnerable to this issue.
I supplied Sun with my PoC-exploit, and they passed it on to other vendors. No further distribution is expected.
I did not release details of the vulnerability before a three month grace period expired after the issue was announced (and when it expired, it took me another three months to actually get to it).
There are a couple of variants, none of which works for every vulnerable Java runtime. All variants have in common that they trick (Http)URLConnection into sending a HTTP request it would otherwise not be willing to send. A configured HTTP proxy is required for all exploits that I am aware of.
Consider the following code snippets.
// Sun Java urlConnection.setRequestProperty( "Accept", "*.*\r\n\r\n[insert custom HTTP request here]" ); // Netscape Java urlConnection.setRequestProperty( "Content-length: 9\r\n\r\n", "23456789[insert custom HTTP request here]" ); // Microsoft Java urlConnection.setRequestProperty("Content-length","9"); (...) payload.write("123456789".getBytes()); payload.write("[insert custom HTTP request here]".getBytes());
Note the inserted HTTP requests will be pipelined. While these three examples are simple enough, to make things fit and actually work, will often be more complicated.
The fourth variant exploits a race condition by writing the custom HTTP request continuously to urlConnection.getOutputStream() in one thread, and call urlConnection.getInputStream() in another. As a result the content-length value will not add up. I discovered this one long after my initial report, and by that time Sun was already aware of it.
The apparent implication is, that Java security network access policy is not applied to irregular HTTP requests, including HTTP CONNECT, that is otherwise not a valid HTTP request method for HttpURLConnection.
Consider the following code snippet.
urlConnection.setRequestProperty( "Accept", "*.*\r\n\r\nCONNECT [host]:[port] HTTP/1.0\r\n\r\n"
The proxy would connect to the requested server and continue as a plain relay thereafter. Subsequent legitimate HTTP requests would then end up as-is at that server, that could respond to them like a regular HTTP proxy would, if and for as long as a persistent HTTP connection would be maintained. If the Java runtime used the browsers HTTP stack, like Microsoft and Netscape Java do, this would also be true for HTTP requests not originating from Java. Sun Java plugins use their own HTTP stack however, IMHO leaving proxy hijacking rather theoretical with those, to say the least.
|Sun, Blackdown Java runtimes||1.1.7/8, 1.2.2, 1.3.0/1 1.4.0||linux, win32|
Thanks to the vendors for addressing the issue. Special thanks to Sun, in particular Chok Poh, for coordinating.
This comes with ABSOLUTELY NO WARRANTY! Copying in whole and quoting parts permitted.
|October 16, 2006||1.4||Added and changed a link.|
|October 02, 2006||1.3||Removed superfluous sections. Fixed broken links. HTML format.|
|September 08, 2002||1.2||Detailed problem description.|
|March 16, 2002||1.1||Bugtraq id.|
|March 05, 2002||1.0||First release.|