Getting SSL23_GET_SERVER_HELLO:unknown protocol - ssl

This seems to be a popular question. I hope to differentiate my version from the others. Here's what I'm seeing when trying to connect to a Tomcat server, using the -debug option:
# openssl s_client -connect example.com:443 -debug
CONNECTED(00000003)
write to 0x694230 [0x694ef0] (187 bytes => 187 (0xBB))
[...]
read from 0x694230 [0x69a450] (7 bytes => 7 (0x7))
0000 - 15 03 03 00 02 02 28 ......(
15633:error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol:s23_clnt.c:610:

The first thing to note is that the response does not include visible characters, so I'm unlikely to be connecting to a non-SSL-enabled port. I'm not certain which SSL library my version of openssl is using, but looking at https://boringssl.googlesource.com/boringssl/+/2214/ssl/s23_clnt.c is helpful, even with the wrong line numbers. p[1] is 0x03, which is SSL3_VERSION_MAJOR, and p[2] is 0x03, which is TLS1_2_VERSION_MINOR. p[0] is 0x15 (21 decimal), which is SSL3_RT_ALERT, which means that p[3] and p[4] should be 0 and 2 (the code doesn't use symbolic names for these), which they are. p[5] is also 0x02, which is SSL3_AL_FATAL, which doesn't look good. I'm guessing the server didn't like my initial write. However, that should give me a different error, so I'm wondering if openssl really doesn't recognize an otherwise valid protocol. Checking the version:
# openssl version
OpenSSL 0.9.8j-fips 07 Jan 2009
Yes, that looks a bit old. I guess I need to find a more recent version.

Related

Play WS SSL acceptAnyCertificate=true issue

We are using Play WS SSL firsttime and play.ws.ssl.loose.acceptAnyCertificate: 'true' config which intends to be for disabling Hostname Verification.
But for some reason I see , it still does the host verification and I see the following warnings.
August 3rd 2017, 15:02:25.084 *** ClientKeyExchange, DH
August 3rd 2017, 15:02:25.083 *** Certificate chain
August 3rd 2017, 15:02:25.083 ***
August 3rd 2017, 15:02:25.083 Warning: no suitable certificate found - continuing without client authentication
August 3rd 2017, 15:02:25.083 0080: 72 70 72 69 73 65 43 41 30 31 rpriseCA01
August 3rd 2017, 15:02:25.083 [read] MD5 and SHA1 hashes: len = 4
August 3rd 2017, 15:02:25.083 0000: 0E 00 00 00 ....
August 3rd 2017, 15:02:25.083 <Empty>
August 3rd 2017, 15:02:25.083 *** ServerHelloDone
From my understanding,
play.ws.ssl.loose.acceptAnyCertificate: 'true' --> Strict validation
play.ws.ssl.loose.acceptAnyCertificate: 'false' --> Loose Validation
When we set the flag to false , it was able to identity server cert from keystore and does cert validation and other checks, also the handshake was happening as expected.
Where as when we set the loose config with flag true, it's NOT able to identify the server cert and throws no suitable certificate found warning and handshake fails.
For me it doesn't make any sense as it was working in the strict case but fails in the loose case which is strange behaviour.
I can say when the flag is set to true, play uses JDK's SSLEngine implementation but some other implementation in case the flag is false
Any ideas ?
Thanks
Suresh
play.ws.ssl.loose.acceptAnyCertificate: 'true' will disable certificate validation, and that is something you should not do unless you understand what are the implications (read Play Framework - Loose Options for more information).
To disable hostname verification, use this instead:
play.ws.ssl.loose.disableHostnameVerification=true

How does one specify a particular cipher suite for a nginx docker instance?

I am running a newly built discourse docker image on Google Compute Engine. I converted that to use https using letsencrypt following the walk through and I get an A+ rating from ssllabs. However the scripting agent I'm using doesn't support either of the two TLS 1.0 cipher suites enabled [TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA] and I'd like to add TLS-DHE-RSA-WITH-AES-256-CBC-SHA which is supported by the open source rebol3 fork ren-c.
I've modified my web.ssl.template.yml file from
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:\
ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:\
ECDHE-RSA-AES256-SHA;
to
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:\
ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:\
ECDHE-RSA-AES256-SHA:TLS-DHE-RSA-WITH-AES-256-CBC-SHA;
and rebuilt the app using
sudo ./launcher rebuild app
but this doesn't alter the cipher_suites available.
I'm now wondering if I have to alter the nginx.conf directly, wherever that is, instead of asking the discourse build script to do it ...
Changing the line in /var/discourse/templates/web.ssl.template.yml
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:\
ECDHE-RSA-AES128-SHA256$RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA;
to
ssl_ciphers 'HIGH:!aNULL:!MD5';
changes the supported TLS 1.0 suites to
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014) ECDH secp384r1 (eq. 7680 bits RSA) FS 256
TLS_RSA_WITH_AES_256_CBC_SHA (0x35) 256
TLS_RSA_WITH_CAMELLIA_256_CBC_SHA (0x84) 256
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (0xc013) ECDH secp384r1 (eq. 7680 bits RSA) FS 128
TLS_RSA_WITH_AES_128_CBC_SHA (0x2f) 128
TLS_RSA_WITH_CAMELLIA_128_CBC_SHA (0x41)
and still gives an A+ rating from ssllabs.
mkdir -p containers/templates
cp templates/web.ssl.template.yml containers/templates
fuss with the file
add containers/templates/web.ssl.template.yml to you app.yml file in the templates section
profit

Find SSL Version after Handshake in OpenSSL

I want to find out the protocols supported by a target but the problem is that their are quite a number websites which are not supporting a particular version but when i performed handshake it was successful becz target surpassed the version that i gave and perform handshake on the supported version
[ it happened on only 1 website]
example : i passed a version :TLSVersion.TLS_1_2 but the handshake is performed using TLSv1_0 becz it is not supporting TLSVersion.TLS_1_2
Because of the above issue i want to check the version on handshake and i dont want to use scapy.ssl_tls
version = [SSL.SSLv23_METHOD,
SSL.TLSv1_METHOD,
SSL.TLSv1_1_METHOD,
SSL.TLSv1_2_METHOD]
context = OpenSSL.SSL.Context(version)
soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
soc.settimeout(CONNECTION_TIMEOUT)
connection = OpenSSL.SSL.Connection(context,soc)
connection.connect((host,port))
connection.do_handshake()
#wants to check version here
i want to check the version on handshake
The relevant functions to check the version both client and server use for the remaining session in pyOpenSSL are get_protocol_version_name or get_protocol_version:
connection.do_handshake()
#wants to check version here
print(connection.get_protocol_version_name())
Note that these functions are only available since pyOpenSSL 0.16.0
Please not also that you cannot specify a list of TLS methods when creating the context but only a single method which essentially specifies the minimal TLS version supported by the client. Thus
context = OpenSSL.SSL.Context(SSL.TLSv1_METHOD)
allows the client to use TLS 1.0 and better. If you instead use SSL.TLSv1_2_METHOD the client would be restricted to TLS 1.2 and better and thus could not establish a SSL connection with a server supporting only TLS 1.0.
Find SSL Version after Handshake in OpenSSL...
If I am parsing what you want correctly... you want the protocol version like printed by openssl s_client:
$ openssl version
OpenSSL 1.1.0b 26 Sep 2016
$ openssl s_client -connect www.google.com:443 -servername www.google.com
CONNECTED(00000005)
depth=2 C = US, O = GeoTrust Inc., CN = GeoTrust Global CA
verify error:num=20:unable to get local issuer certificate
Server did acknowledge servername extension.
---
...
---
New, TLSv1.2, Cipher is ECDHE-RSA-CHACHA20-POLY1305
Server public key is 2048 bit
Secure Renegotiation IS supported
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.2
...
The first message of "New, TLSv1.2" tells you about the cipher. That is, when is ECDHE-RSA-CHACHA20-POLY1305 first arrived in TLS. In the case of ECDHE-RSA-CHACHA20-POLY1305, the cipher suite was first seen in TLS 1.2.
The source code for s_client is located at <openssl src>/apps/s_client.c. The code responsible in OpenSSL 1.0.2 is around line 2210:
/* line 2210 */
c = SSL_get_current_cipher(s);
BIO_printf(bio, "%s, Cipher is %s\n",
SSL_CIPHER_get_version(c), SSL_CIPHER_get_name(c));
...
The second message of "Protocol: TLSv1.2" tells you the protocol version used during key exchange and subsequent cipher selection and bulk transfer.
The code responsible in OpenSSL 1.0.2 is <openssl src>/ssl/ssl_txt.c around line 105:
/* line 105 */
int SSL_SESSION_print(BIO *bp, const SSL_SESSION *x)
{
unsigned int i;
const char *s;
if (x == NULL)
goto err;
if (BIO_puts(bp, "SSL-Session:\n") <= 0)
goto err;
if (x->ssl_version == SSL2_VERSION)
s = "SSLv2";
else if (x->ssl_version == SSL3_VERSION)
s = "SSLv3";
else if (x->ssl_version == TLS1_2_VERSION)
s = "TLSv1.2";
else if (x->ssl_version == TLS1_1_VERSION)
s = "TLSv1.1";
else if (x->ssl_version == TLS1_VERSION)
s = "TLSv1";
else if (x->ssl_version == DTLS1_VERSION)
s = "DTLSv1";
else if (x->ssl_version == DTLS1_2_VERSION)
s = "DTLSv1.2";
else if (x->ssl_version == DTLS1_BAD_VER)
s = "DTLSv1-bad";
else
s = "unknown";
if (BIO_printf(bp, " Protocol : %s\n", s) <= 0)
goto err;
...
}
I want to find out the protocols supported by a target but the problem is that their are quite a number websites which are not supporting a particular version but when i performed handshake ...
This is a different problem. You should look at the source code for sslscan at SSLScan - Fast SSL Scanner to see how it works. The Sourceforge one seems abandoned. It lacks SNI and other new features, like secure negotiation and ALPN.
You might try this sslscan from GitHub: rbsec/sslscan. The GitHub one is actively maintained and seems to be more up to date.
example : i passed a version :TLSVersion.TLS_1_2 but the handshake is performed using TLSv1_0 becz it is not supporting TLSVersion.TLS_1_2
This will not happen. TLS specifies one protocol version only. The idea is your try TLS 1.2. If it fails, then you fall back to TLS 1.1. If it fails, then you fall back to TLS 1.0. Ad infinitum.
The try-and-fallback approach is the reason for RFC 7504, TLS Fallback Signaling Cipher Suite Value (SCSV) for Preventing Protocol Downgrade Attacks. This was an awful band-aide from the Browser crowd. See, for example, Last Call: <draft-ietf-tls-downgrade-scsv-03.txt> (TLS Fallback Signaling Cipher Suite Value (SCSV) for Preventing Protocol Downgrade Attacks) to Proposed Standard.
TLS does not accept a range of protocol versions like many folks think. We have tried to get it changed a few times. See, for example, A new TLS version negotiation mechanism.

Not possible to accept only TLS 1.2 with boost::asio?

So I am trying to modify a third party (libtorrent) to only accept the TLS 1.2 protocol.
Part of the setup of the SSL context:
boost::shared_ptr<context> ctx = boost::make_shared<context>(boost::ref(m_ses.get_io_service()), context::tlsv12)
ctx->set_options(context::default_workarounds
| boost::asio::ssl::context::no_sslv2
| boost::asio::ssl::context::no_sslv3
| boost::asio::ssl::context::no_tlsv1
| boost::asio::ssl::context::no_tlsv1_1
| boost::asio::ssl::context::single_dh_use);
However when I am testing my connection with OpenSSL s_client it still seems to accept tls 1.0 and tls 1.1 connection.
Is there something I am doing wrong?
EDIT: Added "| boost::asio::ssl::context::no_tlsv1_1" to options. I realized I was referring to an old boost reference guide. It did however not change anything.
EDIT: I just realize that I have not mentioned that this connection is a two-way/mutual authentication connection. Not sure if that changes anything.
There is no constant for TLS1.2 in asio::ssl::context. But you can use native openssl API to do that:
#include <openssl/ssl.h>
long ssl_disallowed = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2;
ssl_disallowed &= ~SSL_OP_NO_TLSv1_2;
SSL_CTX_set_options(ctx.native_handle(), ssl_disallowed);
This is a total shot in the dark, but try this:
Try creating a string of ciphers specific to TLS 1.2 and then call
char* TLS_12_CIPHERS = "... list of ciphers specific to TLS 1.2";
SSL_CTX_set_cipher_list(ctx->native_handle(), TLS_12_CIPHERS);
Then set the option on the context (assuming it's a server context) that the server gets to choose what ciphers it wants use, not client.
SSL_CTX_set_options(ctx->native_handle(), SSL_OP_CIPHER_SERVER_PREFERENCE);
You'd think that boost::asio::ssl would take care of this stuff for you by specifying the no_X options but I can't be sure. Like I said this is a shot in the dark, but explicitly configuring context using the OpenSSL API in this way should enforce the conditions you're after. Even if somewhere, somehow, some conflicting option is being set to allow non TLS 1.2 connections, with these options, any non TLS 1.2 connection will fail with the error "no shared cipher".
As for why your server is even advertising that non 1.2 connections are acceptable is unknown, but one possible explanation is that there is a default context that is advertising this. This is why sehe made the point about "applying to all connections."
Here is a list of TLS 1.2 specific ciphers.

SSL_accept() fails with "SSL routines:SSL_GET_NEW_SESSION:ssl session id callback failed'

I am receiving the following error while trying to accept SSL connection from a client application. I am using openssl version 0.9.8 on HP-UX IA.
SSL_accept(40107e50) -1 err: 336285997 'error:140B512D:SSL routines:SSL_GET_NEW_SESSION:ssl session id callback failed'
I have checked for /dev/random and /dev/urandom. It exists and functioning properly.
ls -l /dev/random
cr--r--r-- 1 root sys 144 0x000000 Mar 10 2010 /dev/random
cr--r--r-- 1 root sys 144 0x000001 Mar 10 2010 /dev/urandom
Please help me in identifying the root cause of the problem.
Let me know if you need more information.
This can occur when OpenSSL's PRNG is not sufficiently seeded. Check on it with RAND_status(), and seed as necessary with RAND_add() or RAND_seed(). http://www.openssl.org/docs/crypto/RAND_add.html