Open MaxTownley opened 7 months ago
I am just trying to work out if on the latest versions of openssl loading in the DEFAULT_PARAMS even makes the system anymore secure by default - as currently in my tests with "OpenSSL 1.1.1k FIPS 25 Mar 2021" it would seem that the list of ciphers with insecure false are weaker than with it set to true.....
@MaxTownley Thanks for reporting this in detail!
It seems the if statement here should also have an else that will explicitly set the verify_mode to VERIFY_NONE.
In my first impression, this looks reasonable.
It seems that the current implementation fails to take into account that the default mode is VERIFY_PEER
.
If you know anything about the version of the package that causes this problem, please let us know. (I'm wondering if this behavior has been this way for a long time, or if the behavior has changed with recent packages.)
@MaxTownley Thanks for reporting this in detail!
It seems the if statement here should also have an else that will explicitly set the verify_mode to VERIFY_NONE.
In my first impression, this looks reasonable. It seems that the current implementation fails to take into account that the default mode is
VERIFY_PEER
.If you know anything about the version of the package that causes this problem, please let us know. (I'm wondering if this behavior has been this way for a long time, or if the behavior has changed with recent packages.)
I think it has been this way for a very long time. I am just using the latest package (fluentd 1.16.5) but if we take a look a git blame it been this way for 6 years (https://github.com/fluent/fluentd/commit/d20d68657943e7a0b5179a5612234afbb8738176)
You wouldn't notice if you just don't present a certificate at all as the verify cert code is just not called and it doesn't set VERIFY_FAIL_IF_NO_PEER_CERT by default. So it only tried to verify the client cert if one is provided but some clients might connect to many syslog servers some requiring a cert and some not. I believe the correct behavior here should be to ignore to ignore the client certificate if client_cert_auth is false.
There seems to be a more troubling problem here to in further tests I have conducted. It seems the original intention of using open ssl DEFAULT_PARAMS is to stop using weak ciphers. It would appear if you are using a newer version of openssl the insecure false
is actually using weaker ciphers than the ones openssl sets by default.
I am using OpenSSL 1.1.1k FIPS 25 Mar 2021
with insecure false
set and scanning the port used for the TLS syslog source these are the cipher available for use
Supported Server Cipher(s):
Preferred TLSv1.3 128 bits TLS_AES_128_GCM_SHA256 Curve 25519 DHE 253
Accepted TLSv1.3 256 bits TLS_AES_256_GCM_SHA384 Curve 25519 DHE 253
Accepted TLSv1.3 256 bits TLS_CHACHA20_POLY1305_SHA256 Curve 25519 DHE 253
Accepted TLSv1.3 128 bits TLS_AES_128_CCM_SHA256 Curve 25519 DHE 253
Preferred TLSv1.2 256 bits ECDHE-RSA-AES256-GCM-SHA384 Curve 25519 DHE 253
Accepted TLSv1.2 256 bits DHE-RSA-AES256-GCM-SHA384 DHE 2048 bits
Accepted TLSv1.2 256 bits ECDHE-RSA-CHACHA20-POLY1305 Curve 25519 DHE 253
Accepted TLSv1.2 256 bits DHE-RSA-CHACHA20-POLY1305 DHE 2048 bits
Accepted TLSv1.2 256 bits DHE-RSA-AES256-CCM DHE 2048 bits
Accepted TLSv1.2 256 bits ECDHE-ARIA256-GCM-SHA384 Curve 25519 DHE 253
Accepted TLSv1.2 256 bits DHE-RSA-ARIA256-GCM-SHA384 DHE 2048 bits
Accepted TLSv1.2 128 bits ECDHE-RSA-AES128-GCM-SHA256 Curve 25519 DHE 253
Accepted TLSv1.2 128 bits DHE-RSA-AES128-GCM-SHA256 DHE 2048 bits
Accepted TLSv1.2 128 bits DHE-RSA-AES128-CCM DHE 2048 bits
Accepted TLSv1.2 128 bits ECDHE-ARIA128-GCM-SHA256 Curve 25519 DHE 253
Accepted TLSv1.2 128 bits DHE-RSA-ARIA128-GCM-SHA256 DHE 2048 bits
Accepted TLSv1.2 64 bits DHE-RSA-AES256-CCM8 DHE 2048 bits
Accepted TLSv1.2 64 bits DHE-RSA-AES128-CCM8 DHE 2048 bits
Accepted TLSv1.2 256 bits ECDHE-RSA-AES256-SHA384 Curve 25519 DHE 253
Accepted TLSv1.2 256 bits DHE-RSA-AES256-SHA256 DHE 2048 bits
Accepted TLSv1.2 256 bits ECDHE-RSA-CAMELLIA256-SHA384 Curve 25519 DHE 253
Accepted TLSv1.2 256 bits DHE-RSA-CAMELLIA256-SHA256 DHE 2048 bits
Accepted TLSv1.2 128 bits ECDHE-RSA-AES128-SHA256 Curve 25519 DHE 253
Accepted TLSv1.2 128 bits DHE-RSA-AES128-SHA256 DHE 2048 bits
Accepted TLSv1.2 128 bits ECDHE-RSA-CAMELLIA128-SHA256 Curve 25519 DHE 253
Accepted TLSv1.2 128 bits DHE-RSA-CAMELLIA128-SHA256 DHE 2048 bits
Accepted TLSv1.2 256 bits ECDHE-RSA-AES256-SHA Curve 25519 DHE 253
Accepted TLSv1.2 256 bits DHE-RSA-AES256-SHA DHE 2048 bits
Accepted TLSv1.2 256 bits DHE-RSA-CAMELLIA256-SHA DHE 2048 bits
Accepted TLSv1.2 128 bits ECDHE-RSA-AES128-SHA Curve 25519 DHE 253
Accepted TLSv1.2 128 bits DHE-RSA-AES128-SHA DHE 2048 bits
Accepted TLSv1.2 128 bits DHE-RSA-CAMELLIA128-SHA DHE 2048 bits
Accepted TLSv1.2 256 bits AES256-GCM-SHA384
Accepted TLSv1.2 256 bits AES256-CCM
Accepted TLSv1.2 256 bits ARIA256-GCM-SHA384
Accepted TLSv1.2 128 bits AES128-GCM-SHA256
Accepted TLSv1.2 128 bits AES128-CCM
Accepted TLSv1.2 128 bits ARIA128-GCM-SHA256
Accepted TLSv1.2 64 bits AES256-CCM8
Accepted TLSv1.2 64 bits AES128-CCM8
Accepted TLSv1.2 256 bits AES256-SHA256
Accepted TLSv1.2 256 bits CAMELLIA256-SHA256
Accepted TLSv1.2 128 bits AES128-SHA256
Accepted TLSv1.2 128 bits CAMELLIA128-SHA256
Accepted TLSv1.2 256 bits AES256-SHA
Accepted TLSv1.2 256 bits CAMELLIA256-SHA
Accepted TLSv1.2 128 bits AES128-SHA
Accepted TLSv1.2 128 bits CAMELLIA128-SHA
Accepted TLSv1.2 112 bits TLS_RSA_WITH_3DES_EDE_CBC_SHA
Accepted TLSv1.2 112 bits TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
Accepted TLSv1.2 ?? bits TLS_RSA_WITH_SEED_CBC_SHA
Accepted TLSv1.2 ?? bits TLS_DHE_RSA_WITH_SEED_CBC_SHA
Accepted TLSv1.2 112 bits TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SH
With insecure true
I see the following list
Supported Server Cipher(s):
Preferred TLSv1.3 128 bits TLS_AES_128_GCM_SHA256 Curve 25519 DHE 253
Accepted TLSv1.3 256 bits TLS_AES_256_GCM_SHA384 Curve 25519 DHE 253
Accepted TLSv1.3 256 bits TLS_CHACHA20_POLY1305_SHA256 Curve 25519 DHE 253
Accepted TLSv1.3 128 bits TLS_AES_128_CCM_SHA256 Curve 25519 DHE 253
Preferred TLSv1.2 256 bits ECDHE-RSA-AES256-GCM-SHA384 Curve 25519 DHE 253
Accepted TLSv1.2 256 bits DHE-RSA-AES256-GCM-SHA384 DHE 2048 bits
Accepted TLSv1.2 256 bits ECDHE-RSA-CHACHA20-POLY1305 Curve 25519 DHE 253
Accepted TLSv1.2 256 bits DHE-RSA-CHACHA20-POLY1305 DHE 2048 bits
Accepted TLSv1.2 256 bits DHE-RSA-AES256-CCM DHE 2048 bits
Accepted TLSv1.2 128 bits ECDHE-RSA-AES128-GCM-SHA256 Curve 25519 DHE 253
Accepted TLSv1.2 128 bits DHE-RSA-AES128-GCM-SHA256 DHE 2048 bits
Accepted TLSv1.2 128 bits DHE-RSA-AES128-CCM DHE 2048 bits
Accepted TLSv1.2 256 bits DHE-RSA-AES256-SHA256 DHE 2048 bits
Accepted TLSv1.2 128 bits ECDHE-RSA-AES128-SHA256 Curve 25519 DHE 253
Accepted TLSv1.2 128 bits DHE-RSA-AES128-SHA256 DHE 2048 bits
Accepted TLSv1.2 256 bits ECDHE-RSA-AES256-SHA Curve 25519 DHE 253
Accepted TLSv1.2 256 bits DHE-RSA-AES256-SHA DHE 2048 bits
Accepted TLSv1.2 128 bits ECDHE-RSA-AES128-SHA Curve 25519 DHE 253
Accepted TLSv1.2 128 bits DHE-RSA-AES128-SHA DHE 2048 bits
Accepted TLSv1.2 256 bits AES256-GCM-SHA384
Accepted TLSv1.2 256 bits AES256-CCM
Accepted TLSv1.2 128 bits AES128-GCM-SHA256
Accepted TLSv1.2 128 bits AES128-CCM
Accepted TLSv1.2 256 bits AES256-SHA256
Accepted TLSv1.2 128 bits AES128-SHA256
Accepted TLSv1.2 256 bits AES256-SHA
Accepted TLSv1.2 128 bits AES128-SHA
The list with insecure true is actually a list of stronger cipher suites.
I do have the min_version set to tls 1.2 and the max set to tls 1.3
But I guess this is a separate issue to one I have opened this for.......
Sorry for my late response. We will check and fix this.
This code prevents from selecting insecure TLS version.
However, looks like it makes verify_mode
VERIFY_PEER
unintendedly.
if conf.client_cert_auth ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT else ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE end
It looks good, we should just apply this.
If you know anything about the version of the package that causes this problem, please let us know. (I'm wondering if this behavior has been this way for a long time, or if the behavior has changed with recent packages.)
Why we overlooked it long time is that it's only affected only when clients send its certificate.
(In most cases, client certification isn't used.)
When a client doesn't send it, just ignored because VERIFY_FAIL_IF_NO_PEER_CERT
isn't set by default:
DEFAULT_PARAMS = { # :nodoc:
:verify_mode => OpenSSL::SSL::VERIFY_PEER,
:verify_hostname => true,
:options => -> {
opts = OpenSSL::SSL::OP_ALL
opts &= ~OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS
opts |= OpenSSL::SSL::OP_NO_COMPRESSION
opts
}.call
}
In this case, verification won't performed.
https://docs.openssl.org/3.3/man3/SSL_CTX_set_verify/#notes
SSL_VERIFY_PEER
Server mode: the server sends a client certificate request to the client.
The certificate returned (if any) is checked.
...
SSL_VERIFY_FAIL_IF_NO_PEER_CERT
Server mode: if the client did not return a certificate, the TLS/SSL handshake is immediately terminated
with a "handshake failure" alert. This flag must be used together with SSL_VERIFY_PEER.
if any
is the what we should focus on.
Describe the bug
When creating a source to receive syslog messages using the TLS transport method the
client_cert_auth false
setting is not applied/ So when a client cert is provided it will still attempt to validate the certificate.This is because if the insecure setting is set to false the SSLContext:DEFAULT_PARAMS are set. This sets the verify_mode to VERIFY_PEER https://github.com/ruby/openssl/blob/master/lib/openssl/ssl.rb#L25
The verify_mode is only changed in
cert_option_create_context
if conf.client_cert_auth is set to true.It seems the if statement here should also have an else that will explicitly set the verify_mode to VERIFY_NONE.
https://github.com/fluent/fluentd/blob/284bf4064a9831f5262330a94e3505e09ef6a068/lib/fluent/plugin_helper/cert_option.rb#L34-L36
To Reproduce
Client config
Expected behavior
The server will ignore the certificate and allow you to proceed without validation.
Your Environment
Your Configuration
Your Error Log
Additional context
If you specify insecure this will work as the DEFAULT_PARAMS are not loaded in and the verify_mode will be set to none which is the default. This doesn't seem like the intention behind the insecure setting though it seems the actual intention is to stop weak ciphers from being used.