Test SSL protocols availability using openssl s_client

3 min read | by Jordi Prats

To make sure we don't publish an SSL service with vulnerable protocols enabled we can check which protocols the server has enabled using openssl s_client

Depending on the OpenSSL version we have we will have different procotols available. For example, if we are using OpenSSL 1.0.2j we will have the following options for s_client:

 -ssl2         - just use SSLv2
 -ssl3         - just use SSLv3
 -tls1_2       - just use TLSv1.2
 -tls1_1       - just use TLSv1.1
 -tls1         - just use TLSv1
 -dtls1        - just use DTLSv1

On the other hand, if we are using OpenSSL 1.1.1f we will only have:

 -tls1                      Just use TLSv1
 -tls1_1                    Just use TLSv1.1
 -tls1_2                    Just use TLSv1.2
 -tls1_3                    Just use TLSv1.3

To be able to test a connection for a specific protocol we just need to look at it's output:

$ echo | openssl s_client -connect pet2cattle.com:443 -tls1_1
CONNECTED(00000003)
140063618889024:error:141E70BF:SSL routines:tls_construct_client_hello:no protocols available:../ssl/statem/statem_clnt.c:1112:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 0 bytes and written 7 bytes
Verification: OK
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)
---

If we are receiving the server's certificate means that the protocol is enabled

$ echo | openssl s_client -connect pet2cattle.com:443 -tls1_2
CONNECTED(00000003)
depth=2 C = US, O = Internet Security Research Group, CN = ISRG Root X1
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = R3
verify return:1
depth=0 CN = pet2cattle.com
verify return:1
---
Certificate chain
 0 s:CN = pet2cattle.com
   i:C = US, O = Let's Encrypt, CN = R3
 1 s:C = US, O = Let's Encrypt, CN = R3
   i:C = US, O = Internet Security Research Group, CN = ISRG Root X1
 2 s:C = US, O = Internet Security Research Group, CN = ISRG Root X1
   i:O = Digital Signature Trust Co., CN = DST Root CA X3
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIFTDCCBDSgAwIBAgISAwXD7VJX4nuT0D36AAaBjuTBMA0GCSqGSIb3DQEBCwUA
MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD
EwJSMzAeFw0yMTA2MTIxNzQyNDRaFw0yMTA5MTAxNzQyNDNaMBkxFzAVBgNVBAMT
DnBldDJjYXR0bGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
(...)

So, we can check for the s_clients output looking for the Server certificate string to tell if the protocol is enabled. We can even make a small oneliner to list all status of the available protocols:

$ for i in $(openssl s_client  --help 2>&1 | grep -i "just use" | awk '{ print $1 }' | grep -v dtls); do echo | openssl s_client -connect pet2cattle.com:443 $i 2>&1 | grep "Server certificate" > /dev/null; if [ $? -eq 0 ]; then echo $i ENABLED; else echo $i DISABLED; fi; done
-tls1 DISABLED
-tls1_1 DISABLED
-tls1_2 ENABLED
-tls1_3 DISABLED

Just by changing the -connect string we can test any server we like:

$ for i in $(openssl s_client  --help 2>&1 | grep -i "just use" | awk '{ print $1 }' | grep -v dtls); do echo | openssl s_client -connect google.com:443 $i 2>&1 | grep "Server certificate" > /dev/null; if [ $? -eq 0 ]; then echo $i ENABLED; else echo $i DISABLED; fi; done
-tls1 DISABLED
-tls1_1 DISABLED
-tls1_2 ENABLED
-tls1_3 ENABLED

Posted on 06/07/2021