-
Notifications
You must be signed in to change notification settings - Fork 161
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
Hostname verification should be required by default when OpenSSL::SSL::VERIFY_PEER is configured #8
Comments
One way to solve this without breaking backwards compatibility is to add a new type of verification mode, e.g. |
I believe this is fixed in ruby/ruby@61a3fff which made it's way here soon after. Can you please verify (no pun intended)? /cc @rhenium |
It only converted SSLSocket#initialize to C and doesn't fix this. I'm afraid adding a new verify mode confuses people because the existing modes are directly mapped to OpenSSL's SSL_* constants. How about adding SSLContext#verify_hostname=(true|false)? This injects OpenSSL::SSL.verify_certificate_identity into verify_callback so that the handshake fails. |
@rhenium yeah agreed re:
What I'd actually suggest now in 20/20 hindsight of all of this stuff is having hostname verification automatically performed when You could additionally add |
While I agree this is beneficial in most cases, this is our extension so I rather think this is something that should be enabled by explicitly calling SSLContext#set_params. |
I think this is severe enough to warrant a breaking change. The Rust hyper project just did a similar breaking change (or as one commenter described it, "bugfix"): I was very surprised to discover that setting I think security libraries should have good defaults, and hostname verification definitely seems like the sort of thing that should be on by default to me. Users who are not calling At the very least it should warn: |
It is a definitely natural and desirable behavior that HTTP libraries perform hostname verification by default, but openssl is basically a wrapper for OpenSSL. I think openssl should follow the default of OpenSSL unless the user requests to use "Ruby's recommended default" by calling SSLContext#set_params. There are already have some exceptions, for example we have a default DH parameter to enable a server to use DHE cipher suites by default (with a warning), though. |
As rhenium says, ext/openssl is basically a wrapper of OpenSSL. In the such wrapper area, Ruby shouldn't extend OpenSSL, because OpenSSL sometimes introduces incompatible changes... But ext/openssl has also some utility methods. They can be extended to be more useful and secure. Anyway as usual Ruby's development process, it needs to list up use cases and the extension is useful and secure in some use cases and not harmful for other use cases. The idea "if it sets hostname with |
Hostname verification is not a feature of OpenSSL itself, except in the unreleased 1.1.0 series. Yet it is a part of the Ruby OpenSSL extension (the current implementation is my code), so what you're saying isn't strictly true. How hostname verification should interact with OpenSSL requires thinking about it outside of a purely "wrapper" context. For me, at least, it was very unexpected that setting the hostname did not cause hostname verification to be performed by default. |
Sorry for my silence. I think you meant X509_VERIFY_PARAM_set1_host() (by the way it is already in 1.0.2), but it's unrelated to SNI. Combining SNI and the hostname verification is completely new. I'm all for having such feature as an option, but just I don't think it should be the default. I can add another reason: the hostname verification is useful for HTTP, but it is not necessarily for other application-layer protocols. Again I think SSLContext#set_params is the right place to enable it. This sets the system certificate store to In my quick grep '.set_params' against gems on rubygems.org (using akr/gem-codesearch), I didn't find a gem that will break if we add it to SSLContext#set_params. |
@rhenium hostname verification is an important part of the usage of SSL/TLS in virtually any protocol. I say this as someone who just added SSL/TLS support to This paper covers several cases where MitM attacks were possible in non-browser software because hostname verification wasn't performed: https://www.cs.utexas.edu/~shmat/shmat_ccs12.pdf |
@tarcieri It's true when the |
If a client sets this to true and enables SNI with SSLSocket#hostname=, the hostname verification on the server certificate is performed automatically during the handshake using OpenSSL::SSL.verify_certificate_identity(). Currently an user who wants to do the hostname verification needs to call SSLSocket#post_connection_check explicitly after the TLS connection is established. This commit also enables the option in SSLContext::DEFAULT_PARAMS. Applications using SSLContext#set_params may be affected by this. [GH ruby#8]
If a client sets this to true and enables SNI with SSLSocket#hostname=, the hostname verification on the server certificate is performed automatically during the handshake using OpenSSL::SSL.verify_certificate_identity(). Currently an user who wants to do the hostname verification needs to call SSLSocket#post_connection_check explicitly after the TLS connection is established. This commit also enables the option in SSLContext::DEFAULT_PARAMS. Applications using SSLContext#set_params may be affected by this. [GH ruby#8]
If a client sets this to true and enables SNI with SSLSocket#hostname=, the hostname verification on the server certificate is performed automatically during the handshake using OpenSSL::SSL.verify_certificate_identity(). Currently an user who wants to do the hostname verification needs to call SSLSocket#post_connection_check explicitly after the TLS connection is established. This commit also enables the option in SSLContext::DEFAULT_PARAMS. Applications using SSLContext#set_params may be affected by this. [GH ruby#8]
If a client sets this to true and enables SNI with SSLSocket#hostname=, the hostname verification on the server certificate is performed automatically during the handshake using OpenSSL::SSL.verify_certificate_identity(). Currently an user who wants to do the hostname verification needs to call SSLSocket#post_connection_check explicitly after the TLS connection is established. This commit also enables the option in SSLContext::DEFAULT_PARAMS. Applications using SSLContext#set_params may be affected by this. [GH ruby#8]
Add new ossl_pkey_read_raw() function to ossl_pkey.c. This decodes +data+ using password +pass+ from DER/PEM encoding, and return EVP_PKEY. The next commit will make use of this - it adds PKCS ruby#8 PrivateKeyInfo format support.
Fixed in #60 |
🎉 |
OpenSSL::PKey::PKey#private_to_der, #private_to_pem are added to the generic PKey class that serialize the private key to PKCS ruby#8 {Encrypted,}PrivateKeyInfo format, in DER- and PEM- encoding respectively. Also add #public_to_der and #public_to_pem for symmetry. They serializes the public key into X.509 SubjectPublicKeyInfo format. OpenSSL::PKey.read now reads DER-encoded PKCS ruby#8 keys. PEM-encoded keys have been already handled by PEM_read_bio_PrivateKey().
OpenSSL::PKey::PKey#private_to_der, #private_to_pem are added to the generic PKey class. They serialize the private key to PKCS ruby#8 {Encrypted,}PrivateKeyInfo format, in DER- and PEM- encoding, respectively. For symmetry, also add #public_to_der and #public_to_pem that serialize the public key into X.509 SubjectPublicKeyInfo format. OpenSSL::PKey.read now reads DER-encoded PKCS ruby#8 keys as well as the "raw" private keys. PEM-encoded PKCS ruby#8 keys have been already handled by PEM_read_bio_PrivateKey().
OpenSSL::PKey::PKey#private_to_der, #private_to_pem are added to the generic PKey class. They serialize the private key to PKCS ruby#8 {Encrypted,}PrivateKeyInfo format, in DER- and PEM- encoding, respectively. For symmetry, also add #public_to_der and #public_to_pem that serialize the public key into X.509 SubjectPublicKeyInfo format. OpenSSL::PKey.read now reads DER-encoded PKCS ruby#8 keys as well as the "raw" private keys. PEM-encoded PKCS ruby#8 keys have been already handled by PEM_read_bio_PrivateKey().
OpenSSL::PKey::PKey#private_to_der, #private_to_pem are added to the generic PKey class. They serialize the private key to PKCS ruby#8 {Encrypted,}PrivateKeyInfo format, in DER- and PEM- encoding, respectively. For symmetry, also add #public_to_der and #public_to_pem that serialize the public key into X.509 SubjectPublicKeyInfo format. OpenSSL::PKey.read now reads DER-encoded PKCS ruby#8 keys as well as the "raw" private keys. PEM-encoded PKCS ruby#8 keys have been already handled by PEM_read_bio_PrivateKey().
OpenSSL::PKey::PKey#private_to_der, #private_to_pem are added to the generic PKey class. They serialize the private key to PKCS #8 {Encrypted,}PrivateKeyInfo format, in DER- and PEM- encoding, respectively. For symmetry, also add #public_to_der and #public_to_pem that serialize the public key into X.509 SubjectPublicKeyInfo format. OpenSSL::PKey.read now reads DER-encoded PKCS #8 keys as well as the "raw" private keys. PEM-encoded PKCS #8 keys have been already handled by PEM_read_bio_PrivateKey().
Even if OpenSSL::SSL::VERIFY_PEER is configured, I/O is allowed with a remote server before the subject has been verified. VERIFY_PEER only checks the cert chain is rooted in the local truststore. It does not check if the subject is valid in and of itself.
My understanding is the
ssl_socket.post_connection_check(hostname)
method must be called to ensure the subject is correctly verified. However, communication is allowed to remote services without verifying the subject.I would suggest throwing an exception if VERIFY_PEER is configured and I/O is attempted without first calling
post_connection_check
It would also be nice if this all happened automatically simply by passing
hostname
into OpenSSL::SSL::SSLSocket (which AFAICT only affects SNI presently, and not subject verification)The text was updated successfully, but these errors were encountered: