JDK-6226610 : HTTP tunnel connections send user headers to proxy
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.net
  • Affected Version: solaris_10,1.4.2,5.0,5.0u6
  • Priority: P2
  • Status: Resolved
  • Resolution: Fixed
  • OS: solaris,windows_xp
  • CPU: generic,x86
  • Submitted: 2005-02-08
  • Updated: 2011-02-16
  • Resolved: 2005-09-02
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availabitlity Release.

To download the current JDK release, click here.
Other JDK 6
1.4.2_13Fixed 6 betaFixed
Related Reports
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Relates :  
java version "1.5.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-b64)
Java HotSpot(TM) Client VM (build 1.5.0-b64, mixed mode)

Microsoft Windows XP [Version 5.1.2600]

When making an HTTP(S) request that tunnels through an HTTP proxy (using the CONNECT method) any headers set on the HttpURLConnection are sent to the proxy server as well as to the destination host (through the tunnel).  This can cause sensitive data (e.g. Authorization headers) to travel across the network plain-text, even though the program believes it is connecting to the server using HTTPS.

The problem I am describing is not an issue with base64 encoding the
username:password pair in the Authorization header.  Our code takes care
of it and properly authenticates with the end server.  The problem I am
seeing is more general.

The expectation is that when making a connection to an HTTPS URL, both
the request headers and the request body will be sent to the server
protected by SSL/TLS encryption as negotiated in the SSL handshake.

If the connection is made through a proxy server, Java makes a CONNECT
request to open a channel to the destination server.  In this case, any
request headers set with setRequestProperty are sent to the proxy server
even though the programmers intent is to send these headers to the final
destination server.  This can result in exposing sensitive information
unencrypted on the network.

The behavior can be examined using a packet analyzer and the test code I
provided with the original bug report.  The expectation is that the
X-Test-Header is only sent to the destination server once the SSL
handshake has been completed through the tunneled connection established
by the HTTP CONNECT request.

Note that in order to see the behavior I describe the destination URL
must be an HTTPS URL.

Compile and run the included program giving the name and port number of a proxy server as the first two arguments and the url of the destination server as the third argument.  Use a packet analyzer to view the packets sent by the program.

The X-TestHeader should not be sent to the proxy server.
The X-TestHeader was sent to the proxy server.

This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.net.*;
import java.io.*;

public class ProxyBad {

  public static void main(String args[]) throws Exception {
    System.setProperty("https.proxyHost", args[0]);
    System.setProperty("https.proxyPort", args[1]);
    URL u = new URL(args[2]);
    URLConnection c = u.openConnection();
    /* I want this header to go to the destination server only, protected
     * by SSL; but it gets sent to the proxy as well in plaintext. */
    c.setRequestProperty("X-TestHeader", "value");
    BufferedReader br = new BufferedReader(new InputStreamReader(c.getInputStream()));


---------- END SOURCE ----------

If possible, clear the https proxy properties or set the http noproxy property before making the connection so that a proxy will not be used.  This, of course, will not work if it is actually necessary to use a proxy server.
###@###.### 2005-2-08 13:12:51 GMT

SUGGESTED FIX http://oldsunweb.ireland/~ch122065/j2se/jsn/archive/6226610webrev/ *** src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java *** 1314,1323 **** --- 1314,1328 ---- String statusLine = ""; int respCode = 0; AuthenticationInfo proxyAuthentication = null; String proxyHost = null; int proxyPort = -1; + + // save current requests so that they can be restored after tunnel is setup + MessageHeader savedRequests = requests; + requests = new MessageHeader(); + try { do { if (!checkReuseConnection()) { proxiedConnect(url, proxyHost, proxyPort, false); } *** 1386,1400 **** } finally { if (respCode == HTTP_PROXY_AUTH && proxyAuthentication != null) { proxyAuthentication.endAuthRequest(); } } - // remove tunneling related requests - int i; - if ((i = requests.getKey("Proxy-Authorization")) >= 0) - requests.set(i, null, null); // reset responses responses.reset(); } /** --- 1391,1404 ---- } finally { if (respCode == HTTP_PROXY_AUTH && proxyAuthentication != null) { proxyAuthentication.endAuthRequest(); } } + // restore original request headers + requests = savedRequests; + // reset responses responses.reset(); } /**

EVALUATION This wasn't actually fixed by 6216082. The fix is to save the current MessageHeaders before sending the connect and then restore them if the connect was successful. sendCONNECTRequest() sets a minimal set of headers that can be used during the CONNECT request.

EVALUATION Will fix for mustang ###@###.### 2005-2-10 17:16:31 GMT A quick look shows the fix available for CR 6216082 should fix this one, too. ###@###.### 2005-2-16 09:33:38 GMT