OpenSSL connection: alert internal error - ssl

I have 100 HTTPS services running on a single server using SNI. (Actually, I don't have access to them. It's an assignment. All I know are their domain names N.xxx.yy where N is in range from 00 to 99.) The goal of the assignment is to evaluate security of every single connection to each of these servers. So some of the servers contain expired certificates, certificates with wrong CN, etc.
My problem is that I cannot get past the handshake on some of the servers. I have written my own application in C++ using OpenSSL, but I've also tried it with openssl s_client. This is how I connect to the server:
openssl s_client -host N.xxx.yy -port 443 -verify 1 -servername N.xxx.yy -CAfile assignment-ca.pem
And this is what I get:
139625941858168:error:14094438:SSL routines:ssl3_read_bytes:tlsv1 alert internal error:s3_pkt.c:1493:SSL alert number 80
139625941858168:error:140790E5:SSL routines:ssl23_write:ssl handshake failure:s23_lib.c:177:
In Wireshark, I see that client sent ClientHello, server responded with ServerHello (choosing TLSv1.2 and ECDHE-RSA-AES256-GCM-SHA384) followed by Certificate and then it sent me Alert message containing Internal Error (80).
After trying different thing I have found out that if I run s_client with -tls1 or -tls1_1 I can successfully get past the handshake. -tls1_2 does not work. What is even stranger is that connection through Chrome/Firefox/any other browser succeeds even if TLSv1.2 is negotiated. From what I see, Chrome is sending a different cipher list than me or s_client but even after modifying the cipher list to match the one in Chrome (and making sure that server chooses ECDHE-RSA-AES128-GCM-SHA256), it does not work either. Chrome is sending these TLS extensions, which I don't but most of them seem empty:
Unknown 47802
renegotiation_info
Extended Master Secret
signed_certificate_timestamp
status_request
Application Layer Protocol Negotiation
channel_id
Unknown 6682
Can anybody explain me what is happening here? Unfortunately, I have no way to debug it on the server side so this is all I know.
UPDATE:
After playing around with forged ClientHello messages I managed to track it down to signature_algorithms extension. My app and s_client provide SHA384 + {RSA,DSA,ECDSA} but if I remove these and keep just SHA256 + {RSA,DSA,ECDSA}, as Chrome does, it works and I receive Server Key Exchange message successfully. Could it be that server somehow does not support it, but instead of providing meaningful error message, it just ends unexpectedly and gives me this internal error?
UPDATE 2:
I found answer to why it works with TLS versions prior to 1.2 in RFC5246. Question from the previous UPDATE still holds.
Note: this extension is not meaningful for TLS versions prior to 1.2.
Clients MUST NOT offer it if they are offering prior versions.
However, even if clients do offer it, the rules specified in [TLSEXT]
require servers to ignore extensions they do not understand.

Since you wrote that -tls1_2 does not work I assume either you and/or the server uses an older openssl library. The current version while writing this is 1.1.0e
There were quite some fixes since 0.9.8, which could often be seen on older systems.
For Version 1.0.1 there was this fix, which sounds like your problem:
`Some servers which support TLS 1.0 can choke if we initially indicate
support for TLS 1.2 and later renegotiate using TLS 1.0 in the RSA
encrypted premaster secret. As a workaround use the maximum permitted
client version in client hello, this should keep such servers happy
and still work with previous versions of OpenSSL.`
Maybe also notable:
Don't allow TLS 1.2 SHA-256 ciphersuites in TLS 1.0, 1.1 connections.
So I would suggest to update your openssl-Version and in case of the servers out of your control I would stick to the settings you already found.

Related

CL+SSL SSL Error: Unsafe legacy renegotiation disabled. How to bypass or resolve?

I'm trying to hit an https endpoint to pull back some data using common-lisp(sbcl). For a while this worked without issue. Then one day I started receiving the following error
SSL error queue:
error:0A000152:SSL routines::unsafe legacy renegotiation disabled
[Condition of type CL+SSL::SSL-ERROR-SSL]
I've tried using both drakma and dexador, but see the same error from both. I've confirmed through openssl that the server I'm trying to connect to does not support renegotiation.
From openssl s_client -connect
New, TLSv1/SSLv3, Cipher is AES256-GCM-SHA384
Server public key is 2048 bit
Secure Renegotiation IS NOT supported
I'm on OSX and my open ssl version is LibreSSL 2.8.3.
So to my understanding my client is trying to initiate renegotiation, but the server is rejecting it. I don't really know where to go from here and at this point I'm not even sure what level the problem is truly at, openSSL, CL+SSL, or the http client libraries built on top of CL+SSL. Is there some way to disable renegotiation, or force a new connection? Is there some setting I'm missing?
In Openssl 1.1.1, the SSL_OP_LEGACY_SERVER_CONNECT flag was turned on by default, but
It is turned off by default as of Openssl 3.0.0.
check the article below
SSL_CTX_set_options(ssl_ctx, SSL_OP_LEGACY_SERVER_CONNECT);
https://www.openssl.org/docs/man3.0/man3/SSL_clear_options.html

openSSL 1.1.1 API Doubts

I want to set up and run SSL client and server with TLS 1.2 using openSSL 1.1.1 for my project.
I have a few doubts and/or requirements with openSSL:
what is the right way to select TLS 1.2 as version? Currently I am using TLS_client_method(). the other methods seem to be deprecated. Is there a specific API for choosing particular version?
I need to run an SSL clinet with following handshake extensions.
ec_point_formats with "uncompressed" as value
supported_groups with list of "secp521r","secp384r1","secp256r1","secp224r1","secp192r1","secp160r1","ffdhe2048"
encrypt_then_mac with value 0
server_name
extended_master_secret without any value and length set to 0
I need to run an SSL server with following handshake extensions
encrypt_then_mac with value 0
extended_master_secret without any value and length set to 0
Apart from above header extension fields I want to disable everything else. How to accomplish that?
From client I want to provide only "TLS_PSK_WITH_AES_128_CBC_SHA256" cipher suite as option.
Is client certificate and key files (pem) necessary for successful connection establishment and communication when PSK cipher is used?
Is there any example or open source client-server implementation with PSK authentication?
what is the right way to select TLS 1.2 as version? Currently I am using TLS_client_method(). the other methods seem to be deprecated. Is there a specific API for choosing particular version?
TLS_client_method() is the correct method to use. To specify that no version below TLSv1.2 is used you should do this:
SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
Where ctx is your SSL_CTX object.
If you also want to prevent anything higher than TLSv1.2 from being used then do this:
SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION);
See this page for information on these calls:
https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_min_proto_version.html
I need to run an SSL clinet with following handshake extensions.
ec_point_formats with "uncompressed" as value
supported_groups with list of "secp521r","secp384r1","secp256r1","secp224r1","secp192r1","secp160r1","ffdhe2048"
These extensions aren't used if you specify the PSK ciphersuite that you've selected so OpenSSL won't send them (assuming you've restricted the max TLS protocol version as described above, and have configured only that ciphersuite). Doing so would be pointless. Even if it did, OpenSSL 1.1.1 does not support "ffdhe2048". It does support all the others.
encrypt_then_mac with value 0
Not sure what you mean by "with value 0" since this extension is always empty and has no value. I assume you mean with length 0. This extension is sent by default so you don't need to do anything.
server_name
You should call:
SSL_set_tlsext_host_name(ssl, "hostname of the server");
Where ssl is your SSL object, and replacing "hostname of the server" with the server's real hostname.
See this page for information on this call:
https://www.openssl.org/docs/man1.1.1/man3/SSL_set_tlsext_host_name.html
extended_master_secret without any value and length set to 0
This extension is sent by default so you don't need to do anything.
I need to run an SSL server with following handshake extensions
encrypt_then_mac with value 0
extended_master_secret without any value and length set to 0
If the client sent them, then the server will echo them back by default. You don't need to do anything.
Apart from above header extension fields I want to disable everything else. How to accomplish that?
An OpenSSL client will additionally send the session_ticket extension. Its harmless, but if you really want to disable it you can do this:
SSL_CTX_set_options(ctx, SSL_OP_NO_TICKET);
See this page for further information:
https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_options.html
An OpenSSL server will additionally send the "renegotiate" extension. You must not disable this (in fact you cannot). Ignore it. Its harmless.
From client I want to provide only "TLS_PSK_WITH_AES_128_CBC_SHA256" cipher suite as option.
That is the official IANA name for the ciphersuite. OpenSSL knows it as "PSK-AES128-CBC-SHA256".
Configure it on both the client and the server like this:
SSL_CTX_set_cipher_list(ctx, "PSK-AES128-CBC-SHA256");
See this page for further information:
https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_cipher_list.html
In addition you will need to provide PSK callbacks to tell OpenSSL what the PSK is that you want to use.
On the client you need to call SSL_CTX_set_psk_client_callback(). On the server you must call SSL_CTX_set_psk_server_callback().
See these pages for further information:
https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_psk_client_callback.html
https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_psk_server_callback.html
TLSv1.3 ciphersuites will still automatically be sent unless you have additionally restricted the max TLS protocol version to TLSv1.2 as described above. Finally you will also see a ciphersuite called "TLS_EMPTY_RENEGOTIATION_INFO_SCSV" being sent. This isn't actually a real ciphersuite at all. It is always sent and cannot be suppressed. It will never be negotiated and is harmless. Ignore it.
Is client certificate and key files (pem) necessary for successful connection establishment and communication when PSK cipher is used?
No.
Is there any example or open source client-server implementation with PSK authentication?
You can look at how s_client and s_server do it:
https://github.com/openssl/openssl/blob/OpenSSL_1_1_1-stable/apps/s_client.c
https://github.com/openssl/openssl/blob/OpenSSL_1_1_1-stable/apps/s_server.c

NiFi ListenHTTP processor: Uses an unsupported protocol

I have configured a ListenHTTP 1.7.0 processor in NiFi 1.7.0-RC1. It is listening on a custom port behind a reverse proxy. I have configured a StandardRestrictedSSLContextService with a JKS keystore and have added the keystore password. We have not configured the truststore as we don't expect to need mutual TLS. The certificate is signed by an internal enterprise CA and is (or should be!) trusted by the client.
When I test this with Chrome I receive the following:
This site can’t provide a secure connection
my.server uses an unsupported protocol.
ERR_SSL_VERSION_OR_CIPHER_MISMATCH
Unsupported protocol
The client and server don't support a common SSL protocol version or cipher suite.
Troubleshooting:
We have tried both TLS and TLSv1.2 in the ListenHTTP processor.
We have treid using curl (Linux) and Invoke-WebRequest (Windows) but have received variations on the bad cipher/SSL version message above.
I don't see anything in the release notes suggesting that the ListenHTTP processor changed much since 1.7.0, so I'm assuming that I don't need to upgrade NiFi.
Can anyone suggest what to try next or explain why we see this error?
I have read the following:
https://www.simonellistonball.com/technology/nifi-ssl-listenhttp/
https://cwiki.apache.org/confluence/display/NIFI/Release+Notes
Nifi: how to make ListenHTTP work with SSL
What version of Java are you running on? Java 11 provides TLSv1.3, which is the default offering if you have generic TLS selected, but NiFi 1.7.0 doesn't support TLSv1.3 (and doesn't run on Java 11). So assuming you are running on Java 8, recent updates have introduced TLSv1.3 but should still provide for TLSv1.2. This can also indicate that the certificate you have provided is invalid or incompatible with the cipher suite list provided by the client. You can use $ openssl s_client -connect <host:port> -debug -state -CAfile <path_to_your_CA_cert.pem> to try diagnosing the available cipher suites & protocol versions. Adding -tls1_2 or -tls1_3, etc. will restrict the connection attempt to the specified protocol version as well.
You should definitely upgrade from NiFi 1.7.0 -- it was released over 2 years ago, has known issues, and there have been close to 2000 bug fixes and features added since, including numerous security issues. NiFi 1.12.1 is the latest released version.

How to set up SSL protocols priority in OpenSSL

I am implementing an SSL Client using OpenSSL which
(1) only "speaks" TLS 1.2, TLS 1.1 and TLS 1.0,
(2) set exactly this priority: TLS 1.2. If communication is not possible, use TLS 1.1. If not, TLS 1.0. If not, refuse connection.
I achieve (1) by using
SSL_CTX_set_options(m_ssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
But I don't know any way to achieve (2). Is there any "elegant" way to do this in OpenSSL or do I have to attempt several connections checking if communication was possible and, if not, attempt a lower protocol version?
Thanks.
There is no protocol priority setting. The client will announce the best version it can do to the server and the server will pick this or a lower version. If the version picked by the server is not supported by the client then the handshake will fail. This is not specific to OpenSSL but this is how SSL/TLS works.
Don't confuse this handshake between client and server with the TLS downgrading mechanism most browsers use. In this case browsers retry the SSL handshake on a new TCP connection with a lower version if the handshake with the better version failed. This behavior is to work around broken SSL/TLS implementations. These downgrades are mostly restricted to browsers, simpler TLS stacks are less tolerant and fail permanently if the first handshake failed.

handshake failure(40) and TLS_EMPTY_RENEGOTIATION_INFO_SCSV

A client installed on jBOSS is trying to access a secured website configured on DataPower xi50v6.0.0.2 appliance. The connection is getting failed at SSL handshake.
I have taken a packet capture at DataPower and observed that SSL Handshake is failing with the Description:Handshake failure(40).
However, at the Client Hello step, I have observed that, only one Cipher Suite is specified which is : TLS_EMPTY_RENEGOTIATION_INFO_SCSV.
The TLS protocol used ( as per packet capture) is TLS1.1. Can this Cipher Suite be a problem?
In the DataPower system logs I can see below error:
Request processing failed: Connection terminated before request headers read because of the connection error occurs
Update:
The client application is running on jBOSS7.I have asked our jBOSS administrator to check the configuration at jBOSS end. I somehow got the access to server where jBOSS instance is installed and checked domain.xml where the ssl is configured. Where exactly in domain.xml, ths configuration related to cipher suites can be found?
I have observed that, only one Cipher Suite is specified which is : TLS_EMPTY_RENEGOTIATION_INFO_SCSV
This is no real cipher. If no other ciphers are specified then the client does not offer any ciphers at all which means that no shared ciphers can be found and thus the handshake will fail. It looks like the client is buggy. Reason might be a failed attempt to fight POODLE attack by disabling all SSL3.0 ciphers, which in effect disables all ciphers for TLS1 1.0 and TLS 1.1.