---------- Forwarded message ----------
From: Greg Smethells <gsmethe...@medstrat.com>
To: xmlrpc-a...@ws.apache.org
Date: Thu, 18 Mar 2010 10:22:21 -0500
Subject: Connection re-use bug in XML-RPC 3.1.3

XML-RPC Developers,

There is a security hole in the re-use of server connections when
basic authentication is involved.

Context:
We have an XML-RPC client that connects to a server over HTTPS and
requires basic authentication. Initially, the app starts up using a
1st username/password and our java.net.Authenticator does a
setDefault() to our own WebServerAuthenticator class. It's
getPasswordAuthentication() is called by HttpURLConnection and the
connection succeeds on the server. I cannot tell if it is ever used,
but the XmlRpcClientConfigImpl also has its setBasicUserName and
setBasicPassword set on the xmlrpcClient instance. Everything looks
good at that point.
Then, we have an administration dialog we use to configure the server
side, which is where the issue starts to come up. The
username/password at this point is different than when the app first
signed into the server. A new WebServerAuthenticator class is
setDefault()-ed with this admin (2nd) username/password and a new
XmlRpcClientConfigImpl is instantiated and set to the admin's (2nd)
user/pass and a new xmlrpcClient is also instantiated and set to the
new client config. On the server side, I can see the client try to log
in as the admin (2nd); however, if I provide a bogus password, I can
see the basic auth fail on the server side AND THEN the original
(1st) username/password (not the admin (2nd) credentials) are used to
sign in and the RPC returns successfully (no exception thrown for
password mismatch!). Unbeknownst to the app the xmlrpcClient has used
credentials that were not asked to be used!

Source Code:
This is called during construction of the client-side server proxy ...
                        // Assign an Authenticator to pass username
and password data during HTTPS requests
                        // Required for getting past Apache
authentication (.htaccess)
                        Authenticator.setDefault(new
WebServerAuthenticator(username, password));
                        // Create the XML-RPC client
XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl();
// Set-up the URL to the XML-RPC server
config.setServerURL(new URL("https://"; + ipAddress + "/" + cgiScript));
// Set-up the log-in credentials that provide our actual security
config.setBasicUserName(username);
config.setBasicPassword(password);
config.setEnabledForExtensions(true);
// WARNING: must be as high enough to allow all timeouts given to call()
config.setConnectionTimeout(30 * 1000);        // Timeout for connecting
config.setReplyTimeout(MAX_TIMEOUT * 1000);    // Timeout for XML-RPC
replies
xmlrpcClient = new XmlRpcClient();
xmlrpcClient.setConfig(config);
// Timeout after "timeout" seconds ("timeout" seconds x 1000 milliseconds)
TimingOutCallback callback = new TimingOutCallback(15 * 1000);
// Fault tolerant connect
try {
Object[] result;
Object[] params = new Object[] {};
if( testRPC.length() > 0 ) {
// Asynchronous remote procedure call
xmlrpcClient.executeAsync(testRPC, getParams(params), callback);
result = (Object[]) callback.waitForResponse();

// If we did not throw an exception and got here, then we are connected
  state = CONNECTED;
// Finish any internal state set-up
setupState(result);
Console.print("Connection opened to " + toString());
}
else {
// Assume we are "connected"
state = CONNECTED;
Console.print("Proxy created for " + toString());
}
}
catch(TimeoutException e) {
setState(e.getMessage(), ADDRESS_UNREACHABLE);
}
catch(XmlRpcException xrex) {
parseState(xrex.getMessage());
}
catch(Exception ex) {
parseState(ex.getMessage());
}
catch(Throwable t) {
parseState(t.toString());
}
}
else {
state = CONNECTION_NOT_ALLOWED;
}
Thanks,
Greg

Software Architect
Medstrat, Inc.




--
Germanys national anthem is the most boring in the world - how telling!

Reply via email to