On Mon, Nov 9, 2009 at 10:47 AM, Costin Manolache <cos...@gmail.com> wrote:
> > > On Mon, Nov 9, 2009 at 8:04 AM, Konstantin Kolinko <knst.koli...@gmail.com > > wrote: > >> 2009/11/9 Mark Thomas <ma...@apache.org>: >> > Summarising the information gathered so far from various channels >> > (thanks to Bill B., Bill W. & Rainer who have done most of the actual >> > work to find the info below). >> > >> > BIO/NIO connectors using JSSE. >> > Vulnerable when renegotiation is triggered by the client or server. >> > We could prevent server initiated renegotiation (and probably break the >> > majority of configurations using CLIENT-CERT). >> > We can't do anything to prevent client initiated renegotiation. >> > >> > APR/native connector using OpenSSL >> > It is vulnerable when renegotiation is triggered by the client or by the >> > server. >> > Client triggered negotiation is supported. >> > Server triggered negotiation will be supported from 1.1.17 onwards. >> > >> > OpenSSL 0.9.8l disables negotiation by default >> > >> > >> > In terms of what this means for users: >> > >> > BIO/NIO >> > - There isn't anything we can do in Tomcat to stop client >> > initiated renegotiation so it is a case of waiting for the JVM >> > vendors to respond. >> > >> > APR/native >> > - Re-building their current version with 0.9.8l will protect >> > users at the risk of breaking any configurations that >> > require renegotiation. >> > - We can release 1.1.17 with the binaries built with 0.9.8l. This >> > will also protect users at the risk of breaking any >> > configurations that require renegotiation. Mladen is doing this >> > now. >> > - Supporting renegotiation whilst avoiding the vulnerability will >> > require a protocol fix. In the meantime, we could port port >> > r833582 from httpd which would disable client triggered >> > renegotiation for OpenSSL < 0.9.8l (which may help some users >> > who can't easily change their OpenSSl version and release 1.1.18 >> > with this fix >> > - Once the protocol is fixed, release 1.1.next bundled with the >> > appropriate version of OpenSSL >> > >> > >> > Have I got my facts right above? If so, any objections to posting the >> > above to the users@ and announce@ lists along with adding something to >> > the security pages? >> > >> > Mark >> > >> >> +1 >> >> s/negotiation/renegotiation/ >> s/port port/port/ >> >> A question: >> My understanding of renegotiation is that it changes SSL session. Is >> it possible to observe changes in the value of SSL sessionId? I doubt >> so, but may be? >> > > AFAIK you can reuse the session ID across negotiations ( it's a nice > optimization BTW, too > bad we're not using, it can speed up SSL connections a lot ), I'm not sure > if it changes > within a renegotation, but AFAIK when you start any negotiation you can > specify you want > to reuse the old session id. But if I understand the exploit correctly - > they would want a different > cypher, and if you reuse the session you reuse the old one. > > > Maybe we can modify JSSESupport.Listener to break the connection if > handshakeCompleted is > called > once in a connection ? That is besides disabling server-initiated > handshakes. > > BTW - confirmed that JSSESupport.Listener is called when client does re-negotiate, but it is not called on the first negotiation ( it's added too late ). However it's pretty easy to add a listener earlier, patch attached - it should break all client re-negotiations, so we don't need to wait for a JDK fix. I wrote a small unit test - but I'm can't seem to get jsse client to re-negotiate for the test, can only do it using command line openssl. The patch seems to work - but you need so system properties or flags if we want to let people disable this ( "allowManInTheMiddle" is a good name for a flag ). Also the test needs a bit of work. If anyone has more time, my 20% is getting low .... Costin > Costin > > > >> We read that value once and provide it to our users as >> "javax.servlet.request.ssl_session" request attribute. >> >> Regarding valves (as mentioned in issue 48157): >> I understand, that that is not sufficient, but if anyone wants to >> check against malformed headers, they can do so. >> >> Best regards, >> Konstantin Kolinko >> >> --------------------------------------------------------------------- >> To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org >> For additional commands, e-mail: dev-h...@tomcat.apache.org >> >> >
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.catalina.startup; import java.io.BufferedInputStream; import java.io.File; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import javax.net.ssl.HandshakeCompletedEvent; import javax.net.ssl.HandshakeCompletedListener; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import org.apache.tomcat.util.buf.ByteChunk; /** * Requires: * keytool -genkey -alias tomcat -keyalg RSA * pass: changeit * CN: localhost ( for hostname validation ) */ public class TestTomcatSSL extends TomcatBaseTest { static TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) { } public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) { } } }; static { // Install the all-trusting trust manager try { SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, trustAllCerts, new java.security.SecureRandom()); javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory( sc.getSocketFactory()); } catch (Exception e) { e.printStackTrace(); } } public void testHandshake() throws Exception { Tomcat tomcat = getTomcatInstance(); File appDir = new File("output/build/webapps/examples"); // app dir is relative to server home tomcat.addWebapp(null, "/examples", appDir.getAbsolutePath()); tomcat.getConnector().setSecure(true); tomcat.getConnector().setProperty("SSLEnabled", "true"); tomcat.getConnector().setProperty("sslProtocol", "tls"); tomcat.start(); ByteChunk res = getUrl("https://localhost:" + getPort() + "/examples/servlets/servlet/HelloWorldExample"); assertTrue(res.toString().indexOf("<h1>Hello World!</h1>") > 0); } public void testReHandshake() throws Exception { Tomcat tomcat = getTomcatInstance(); File appDir = new File("output/build/webapps/examples"); // app dir is relative to server home tomcat.addWebapp(null, "/examples", appDir.getAbsolutePath()); tomcat.getConnector().setSecure(true); tomcat.getConnector().setProperty("SSLEnabled", "true"); tomcat.getConnector().setProperty("sslProtocol", "tls"); tomcat.start(); SSLContext sslCtx = SSLContext.getInstance("TLS"); sslCtx.init(null, trustAllCerts, new java.security.SecureRandom()); SSLSocketFactory socketFactory = sslCtx.getSocketFactory(); SSLSocket socket = (SSLSocket) socketFactory.createSocket("localhost", getPort()); socket.addHandshakeCompletedListener(new HandshakeCompletedListener() { @Override public void handshakeCompleted(HandshakeCompletedEvent event) { System.err.println("Handshake done"); } }); OutputStream os = socket.getOutputStream(); os.write("GET /examples/servlets/servlet/HelloWorldExample HTTP/1.0\n".getBytes()); socket.getSession().invalidate(); socket.startHandshake(); os.write("Host: localhost\n\n".getBytes()); InputStream is = socket.getInputStream(); ByteChunk out = new ByteChunk(); BufferedInputStream bis = new BufferedInputStream(is); byte[] buf = new byte[2048]; int rd = 0; while((rd = bis.read(buf)) > 0) { out.append(buf, 0, rd); } assertTrue(out.toString().indexOf("<h1>Hello World!</h1>") > 0); } }
--------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org