[ 
https://issues.apache.org/jira/browse/CASSANDRA-13325?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17205879#comment-17205879
 ] 

Jon Meredith commented on CASSANDRA-13325:
------------------------------------------

I've been investigating restricting the TLS protocols to prevent use of TLSv1 & 
TLSv1.1 for secure internode messaging and streaming connections and think the 
current implementation needs improvement before the final 4.0 release, so I'd 
like to pick this up again.

The Apache Cassandra documentation page on security 
https://cassandra.apache.org/doc/latest/operating/security.html mentions

"...  the JVM defaults for supported protocols and cipher suites are used when 
encryption is enabled. These can be overidden using the settings in 
cassandra.yaml, but this is not recommended unless there are policies in place 
which dictate certain settings or a need to disable vulnerable ciphers or 
protocols in cases where the JVM cannot be updated."

The implication to me there is that the preferred mechanism is to configure the 
JSSE subsystem. Trawling through documentation, the operator can disable older 
TLS protocol at the JVM level by creating new security properties file

{code}
$ cat conf/cassandra-security.properties
jdk.tls.disabledAlgorithms=SSLv3, RC4, DES, MD5withRSA, DH keySize < 1024, \
    EC keySize < 224, 3DES_EDE_CBC, anon, NULL, TLSv1, TLSv1.1
{code}

And appending to the current security properties using

{code}
  -Djava.security.properties=conf/cassandra-security.properties
{code}

This works fine pre-4.0, however the introduction of Netty tcnative which uses 
OpenSSL under the hood, does not use the {{java.security.properties}} to 
restrict anything. Neither does it implement the calls for supporting the 
OpenSSL configuration file. It only seems possible to restrict the protocol & 
ciphers through the Netty SSLContext API. It is possible to disable OpenSSL by 
setting the Java system property {{cassandra.disable_tcactive_openssl=true}}, 
but it seems undesirable to lose the performance benefit there.

Looking in {{cassandra.yaml}}, under 'More advanced defaults' there is a 
{{protocol}} setting, which an operator might expect restricts which TLS 
protocols are accepted.

{code}
    # More advanced defaults:
    # protocol: TLS
{code}

However, setting that to {{TLSv1.2}} had no effect on the protocols the server 
accepted. Running {{openssl}} will connect without issue and negotiate a 
TLSv1.0 session.

{code}
openssl s_client -tlsv1 -connect 127.0.0.1:7000
{code}

I found two previous tickets that addressed TLS protocols, first explicitly 
hard-coding the accepted TLS protocols to disable SSLv3 (due to POODLE) in 
CASSANDRA-8265 / b93f48a5db321bf7c9fb55a800ed6ab2d6f6b102, and then rely back 
on Java8 defaults in CASSANDRA-10508 / e4a0a4bf65a87c3aabae4ee0cc35009879e2d455 
once the defaults were fixed.

CASSANDRA-10508 mentions the ‘protocol' field as a mechanism for specifying the 
protocol, however according to Java docs, that only verifies the protocol is to 
the SSL engine supported, and does not restrict negotiation to using it, as the 
openssl s_client test demonstrates.

>From a quick search of the internet, a couple of blog posts recommend setting 
>the cipher suite to only {{TLSv1.2}} valid ciphers and I can confirm that does 
>work, leading to this being logged (at ERROR).

{code}
ERROR [Messaging-EventLoop-3-2] 2020-09-19T16:17:48,023 : - Failed to properly 
handshake with peer /127.0.0.1:33826. Closing the channel. 
io.netty.handler.codec.DecoderException:
javax.net.ssl.SSLHandshakeException: Client requested protocol TLSv1.1 is not 
enabled or supported in server context
Caused by: javax.net.ssl.SSLHandshakeException: Client requested protocol 
TLSv1.1 is not enabled or supported in server context
{code}

While it does work to restrict the protocol, if we start logging the accepted 
protocols the log will show that the server will negotiate TLS1/TLS1.1 which 
may get flagged by anybody validating the operators configuration/logs.

The current state of the code and documentation is unsatisfactory to me.  We 
should at least improve the documentation to give clear guidance to operators 
on how they can secure their systems under 4.0/tcnative, however I think we 
should go further and make the encryption_option.protocol field behave as 
intended.

Here's my proposal:

1) Interpret the current protocol string as a comma separated list of protocols 
that are accepted. Replace the default
{{EncryptionOptions.protocol}} of {{"TLS"}} with null.
2) If protocol is non-null, call {{SslContextBuilder.protocols()}} with the 
configured protocols in 
{{org.apache.cassandra.security.SSLFactory#createNettySslContext}}
3) Special case the protocol configuration {{"TLS"}} to mean {{["TLSv1", 
"TLSv1.1", "TLSv1.2”]}} for users that have uncommented the default value. 
Passing {{“TLS”}} is invalid in the {{protocols()}} call.
4) Hard-code {{org.apache.cassandra.security.SSLFactory#createSSLContext}} to 
pass {{"TLS"}} and then restrict to the protocols specified if non-null. It 
still looks used by the JavaDriverClient and BulkLoader.
5) Make sure the protocol and cipher are propagated to the Clients table.

With those changes, operators should be able to restrict both the protocols and 
ciphers as well as audit the configuration and past behavior of their system.

> Bring back the accepted encryption protocols list as configurable option
> ------------------------------------------------------------------------
>
>                 Key: CASSANDRA-13325
>                 URL: https://issues.apache.org/jira/browse/CASSANDRA-13325
>             Project: Cassandra
>          Issue Type: Improvement
>          Components: Local/Config
>            Reporter: Nachiket Patil
>            Assignee: Nachiket Patil
>            Priority: Low
>             Fix For: 4.x
>
>         Attachments: trunk.diff
>
>
> With CASSANDRA-10508, the hard coded list of accepted encryption protocols 
> was eliminated. For some use cases, it is necessary to restrict the 
> encryption protocols used for communication between client and server. 
> Default JVM way of negotiations allows the best encryption protocol that 
> client can use. 
> e.g. I have set Cassandra to use encryption. Ideally client and server 
> negotiate to use best protocol (TLSv1.2). But a malicious client might force 
> TLSv1.0 which is susceptible to POODLE attacks.
> At the moment only way to restrict the encryption protocol is using the 
> {{jdk.tls.client.protocols}} systems property. If I dont have enough access 
> to modify this property, I dont have any way of restricting the encryption 
> protocols.
> I am proposing bring back the accepted_protocols property but make it 
> configurable. If not specified, let the JVM take care of the TLS negotiations.



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@cassandra.apache.org
For additional commands, e-mail: commits-h...@cassandra.apache.org

Reply via email to