Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SSL/TLS certificate verification disabled #352

Closed
harbulot opened this issue Jul 29, 2013 · 10 comments
Closed

SSL/TLS certificate verification disabled #352

harbulot opened this issue Jul 29, 2013 · 10 comments
Assignees
Milestone

Comments

@harbulot
Copy link

The SSL/TLS certificate verification is disabled. This is a security issue (which makes connections vulnerable to MITM attacks).

Here is a quick test that can be tested with a server that has a self-signed certificate or issued by a CA that's not in the default truststore. URLConnection will fail as expected (sun.security.validator.ValidatorException: PKIX path building failed), whereas SimpleAsyncHttpClient will work just fine.

String hostname = "https://somehost/";

try {
    URLConnection connection = new URL(hostname).openConnection();
    connection.connect();
} catch (Exception e) {
    e.printStackTrace();
}

SimpleAsyncHttpClient client = new SimpleAsyncHttpClient.Builder()
        .setUrl(hostname).build();
client.get(new BodyConsumer() {
    @Override
    public void consume(ByteBuffer buffer) throws IOException {
        System.out.print(new String(buffer.array(), "UTF-8"));
    }

    @Override
    public void close() throws IOException {
    }
});

Please remove anything that has to do with the TrustingSSLSocketFactory in com.ning.http.client.providers.apache.TrustingSSLSocketFactory.

@slandelle
Copy link
Contributor

@harbulot
Copy link
Author

The fact that AHC works out of the box with self-signed certificates isn't a feature, it's a security bug.

People who want their self-signed certificates to work should add them to their trust store (either programmatically, which I'm not sure is possible with AHC, or via -Djavax.net.ssl.truststore=..., which will affect the default SSLContext for that application).

There's a discussion on this problem here: http://security.stackexchange.com/questions/22965/what-is-the-potential-impact-of-these-ssl-certificate-validation-vulnerabilities

Many developers using libraries like this assume that it has sensible security defaults. Unfortunately, it seems that AHC doesn't. This impacts a number of projects that uses this library. (To be honest, I don't use AHC myself, but I have noticed that an application I've used was able to connect to an URL that uses a certificate that wouldn't normally have been validated with my trust store.)

@harbulot
Copy link
Author

I've just had a quick look at the fragment of code affected by the patch in issue #351.

I think the expected default settings don't quite make sense.

SSLConfig config = new SSLConfig();
if (config.keyStoreLocation == null
    || config.trustStoreLocation == null) {
     context = getLooseSSLContext();
} else {
     context = getStrictSSLContext(config);
}

Firstly, not specifying a keystore location is actually quite common, since, from a client point of view, the keystore is only used when using client certificates. There isn't even a default value for the keystore in the default JSSE settings (see JSSE Customization section). Assuming that when no client certificates are used, no server certificate validation should take places is a bid odd.

Secondly, of course, assuming that, when no truststore location is specified, no server certificate validation should take place either (not even with the default JRE truststore/trustmanager) is certainly a default that will catch many library users by surprise. In addition, it's not always possible to find what the default trust manager uses (see: http://stackoverflow.com/questions/13657299/how-to-find-current-truststore-on-disk-programatically/13660336#13660336).

@slandelle
Copy link
Contributor

Are you willing to contribute? I personally won't be able to work on this before several weeks at least.

@vmalladi
Copy link

Hi AHC team,
@rlubke @jfarcand @slandelle @oleksiys
Can you comment if this security issue is with all AHC providers or specific to say default provider (netty/grizzly/JDK)?

Thanks.

@wsargent
Copy link
Contributor

wsargent commented Apr 2, 2014

I think the logic behind SSLUtils in creating only a single static SSLContext is incorrect, because it means that the system properties that were in effect at the time of creation are static. In reality, system properties can be changed after a program runs.

In addition, getStrictSSLContext replicates exactly the logic that would be executed by the default JSSE SSLContextImpl in any case -- if you called sslContext.init(null, null, null) then it would look like the strict version. As such, it's repeating the functionality without any new benefit.

Not only that, but SSLUtil relies on static methods for functionality. Even if the goal were to use a singleton, there's no way to reinitialize the method or override a static method without using reflection or Unsafe.

Finally, getLooseSSLContext should not exist, at all. If people need to pass in a loose SSL context, they should do that by hand.

@slandelle
Copy link
Contributor

I mostly agree, except regarding getLooseSSLContext that can perfectly sit there as a public helper. It's the one I'd use for Gatling, I don't really care about security there, I need raw performance.

Do you think you could handle this? My hands are pretty full at the moment...

@wsargent
Copy link
Contributor

wsargent commented Apr 2, 2014

Poking at it right now.

@wsargent
Copy link
Contributor

wsargent commented Apr 3, 2014

@slandelle if you're using getLooseSSLContext for Gatling, then you're probably getting inaccurate numbers for your load tests, as adding / removing certificate verification is going to alter the CPU / memory times. I think it's much better to remove it -- the real pain isn't in TLS certificate verification, it's that creating certificates and sharing them is not something people know how to do.

JEP 166 should let users set up multiple keystores like this:
http://cr.openjdk.java.net/~vinnie/8007755/webrev.00/raw_files/new/test/sun/security/provider/KeyStore/domains.cfg

@wsargent
Copy link
Contributor

wsargent commented Apr 8, 2014

@slandelle PR submitted.

@slandelle slandelle added this to the 2.0.0.Alpha1 milestone Jun 13, 2014
@slandelle slandelle self-assigned this Jun 13, 2014
@slandelle slandelle modified the milestones: 1.9.0, 2.0.0.Alpha1 Jul 10, 2014
cs-workco pushed a commit to cs-workco/async-http-client that referenced this issue Apr 13, 2023
Motivation:

Users of the HTTPClientResponseDelegate expect that the event loop
futures returned from didReceiveHead and didReceiveBodyPart can be used
to exert backpressure. To be fair to them, they somewhat can. However,
the TaskHandler has a bit of a misunderstanding about how NIO
backpressure works, and does not correctly manage the buffer of inbound
data.

The result of this misunderstanding is that multiple calls to
didReceiveBodyPart and didReceiveHead can be outstanding at once. This
would likely lead to severe bugs in most delegates, as they do not
expect it.

We should make things work the way delegate implementers believe it
works.

Modifications:

- Added a buffer to the TaskHandler to avoid delivering data that the
   delegate is not ready for.
- Added a new "pending close" state that keeps track of a state where
   the TaskHandler has received .end but not yet delivered it to the
   delegate. This allows better error management.
- Added some more tests.
- Documented our backpressure commitments.

Result:

Better respect for backpressure.

Resolves AsyncHttpClient#348
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants