Hyper: Does not do any TLS hostname verification by default

Created on 23 Apr 2015  Â·  25Comments  Â·  Source: hyperium/hyper

Currently, hyper does not provide any hostname verification when working with TLS. Ideally, Hyper would use a library similar to https://github.com/pyca/service_identity to prevent MITM attacks from happening.

A-client

All 25 comments

The issue here is that hyper needs to pick something by default.

It's already possible to do it yourself with Client.set_ssl_verifier().

For what it's worth, I just implemented RFC 6125-compliant hostname verification for Ruby's OpenSSL extension (a.k.a. CVE-2015-1855):

https://github.com/ruby/openssl/pull/12/files

I'd be happy to do a Rust implementation.

Worth noting this is also an issue in Servo: https://github.com/servo/servo/issues/4954

I just started an RFC6125 hostname verification library for Rust:

https://github.com/tarcieri/pkixnames

One thing I'm curious about... what type is used for representing presented identifiers? I think I'd like the internal implementation of this library to be done completely as Vec<u8>s

Hyper doesn't seem to do _any_ TLS verification right now with the default client settings. Any untrusted certificate goes.

@tarcieri I don't know what presented identifiers means in this context.

@seanmonstar the subjectAlternativeNames (SANs) or Common Names (CNs) in X.509 certificates

Ah, I have no idea. That would be in the openssl lib, no?

On Sun, Apr 26, 2015, 2:21 PM Tony Arcieri [email protected] wrote:

@seanmonstar https://github.com/seanmonstar the subjectAlternativeNames
(SANs) or Common Names (CNs) in certificates

—
Reply to this email directly or view it on GitHub
https://github.com/hyperium/hyper/issues/472#issuecomment-96436564.

It's beginning to seem like rust-openssl is probably where I should be asking about this :wink:

Since it hasn't been explicitly stated in here, here's a relevant project: https://github.com/briansmith/webpki

@frewsxcv +1 for that

What is a good API for disabling TLS verification when the user desires it?

Environment variable? Argument to the connection object?

Disabling security based on environment variables sounds dangerous.

What is a good API for disabling TLS verification when the user desires it?

Hopefully, this will not be possible.

@zmanian @frewsxcv
There are use-cases where skipping TLS verification is necessary.

In libcurl, the options CURLOPT_SSL_VERIFYPEER and CURLOPT_SSL_VERIFYHOST are available and you can set them to 0.

The curl tool has the option -k,--insecure which relies on the library options mentioned above.

An easy approach would be to make your own implementation of SslClient that avoids the check.

Although it should go without saying that disabling certificate verification is a terrible thing to do, there will be developers who will want to disable it and will find a way to do so whether or not Hyper provides an API for it. Rather than leaving developers to their own devices, I think Hyper should provide an API to disable verification for two reasons:

  1. It will be easier to spot in code audits. Searching for the API call that disables verification is easier than spotting and analyzing a custom SslClient implementation. It would even be possible to search GitHub and file bug reports against projects that are disabling verification.
  2. Developers are likely to search the Web for the invalid certificate error message and find a blog post or Stack Overflow answer that contains an example SslClient to disable verification. This example might come without a sufficient disclaimer that it's doing something very bad. In contrast, if there's an "official" way to disable verification, it can come with a big warning and be named in such a way that may cause at least some developers to think twice before using it. For example, in Go's TLS library, the property to disable verification is named InsecureSkipVerify.

I'm -1 on an option to disable verification. Rebuttal to AGWA's two points above: 1) An entire type that does nothing but circumvent verification has a bigger footprint than an environment variable. I don't think making it easy to grep for is a good thing to optimize for. 2) The kind of developer that would do what you're describing will _still_ just copy/paste whatever they read on Stack Overflow, regardless of whether or not the the flag has "insecure" in the name.

I have a bunch of use cases where disabling certificate validation is needed, mainly related to use on machines not connected to internet (the case at my company):

  • self signed certificates are used on most of the machines
  • the CA files are not up to date (e.g. machines are using older OSs)

More than that, it should also be possible to enable old, insecure ciphers in a relatively easy way mainly to be able to talk to clients/servers not supporting TLS1.2 (everything using Java 1.7 or older).

Hyper should be flexible enough to support these use cases. Defaults can be to enable most secure options but give the user the possibility to configure hyper according to his/her needs.

I have opened https://github.com/hyperium/hyper/issues/811 for this.

Edit: fix a typo

@maximih Hyper already allows all of the configuration you asked for by manually configuring the Openssl object: http://hyper.rs/hyper/v0.9.6/hyper/net/struct.Openssl.html

Note that running an X.509 PKI that broken only offers the illusion of security.

Re: TLS 1.2 and Java 1.7, it's supported out-of-the-box by the Sun JSSE provider.

mainly related to use on machines not connected to internet

Just noticed this, it seems like in this case it may be a waste to use TLS at all. If talking over a local network that you own and control, you can get performance improvements by not encrypting everything. Unless there are others on your local network that you want to protect yourself from, I guess?

Hyper should be flexible enough to support these use cases. Defaults can be to enable most secure options but give the user the possibility to configure hyper according to his/her needs.

This is exactly the current case. Default is to be secure. If one wants to alter away from the defaults, you can utilize the Client::with_connector(HttpsConnector::new(some_configured_openssl)). You can pick all the ciphers, protocol versions, and validation you want or don't want.

Just noticed this, it seems like in this case it may be a waste to use TLS at all.

Not necessarily. There are other local use cases that benefit from skipping verification. For example:

  • Testing server performance with and without TLS.
  • (Easily) isolating potential server TLS issues.

Using curl/libcurl for those use-cases is trivial and just works.

@MoSal I buy @AGWA's argument that having a standard notation that's easy to grep for is desirable.

That said, while I'm glad you think curl makes it super easy to shut off the security, I'm not sure that's actually a desirable property. I think the world would be a better place if there were no -k option to curl, and people needed to explicitly type --insecure, for example.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

seanmonstar picture seanmonstar  Â·  29Comments

cactorium picture cactorium  Â·  26Comments

timonv picture timonv  Â·  24Comments

sfackler picture sfackler  Â·  23Comments

jswrenn picture jswrenn  Â·  44Comments