Saturday, May 12, 2018

End-to-End Security―How to Debug SSL/TLS Issues

SSL (Secure Socket Layer) or its successor TLS (Transport Layer Security) are protocols to facilitate end-to-end security. These protocols are used when accessing web sites (https), delivering or retrieving email, and in lots of other use cases. In the following documentation we will refer to both SSL and TLS as simply 'SSL'.

When you debug SSL issues, you can use Linux curl command to test.  In this article, we will cover the following topics:
  • Curl and its backend OpenSSL
  • Which CA certificate was used
  • Unknown SSL protocol error 
  • Useful Tools for SSL Debugging

Curl and Its Backend OpenSSL


Depending on which working SSL library that your curl was built with, curl command may sometimes fail to negotiate SSL handshake because of older version of OpenSSL.  So, the first thing to check is which OpenSSL your curl command is built with by typing:

$ curl --version
curl 7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.51.0 OpenSSL/1.0.2j zlib/1.2.3
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp
Features: AsynchDNS IPv6 Largefile NTLM SSL libz

In this curl, it is built with OpenSSL 1.0.2j.

Specify CA Certificate with --cacert  Option


You can specify which CA certificate to verify peer against by using
 --cacert  
$ curl -v --cacert /u01/data/secure_artifacts/ssl/certs/cert-8b3a107e0d914aed91828f4414ad69f0_USPSRDEVCERTSIGN.pem https://10.240.81.24:3651
* Rebuilt URL to: https://10.240.81.24:3651/
* Trying 10.240.81.24...
* TCP_NODELAY set
* Connected to 10.240.81.24 (10.240.81.24) port 3651 (#0)
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
* CAfile: /u01/data/secure_artifacts/ssl/certs/cert-8b3a107e0d914aed91828f4414ad69f0_USPSRDEVCERTSIGN.pem
CApath: none
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* Unknown SSL protocol error in connection to 10.240.81.24:3651
* Curl_http_done: called premature == 1
* Closing connection 0

Default Certificate


 If you don't specify a CA certificate, the default certificate is used.  Notice that the default certificate used below is:
/etc/pki/tls/certs/ca-bundle.crt
$ curl -v  https://10.240.81.24:3651
* Rebuilt URL to: https://10.240.81.24:3651/
* Trying 10.240.81.24...
* TCP_NODELAY set
* Connected to 10.240.81.24 (10.240.81.24) port 3651 (#0)
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
* CAfile: /etc/pki/tls/certs/ca-bundle.crt
CApath: none
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* Unknown SSL protocol error in connection to 10.240.81.24:3651
* Curl_http_done: called premature == 1
* Closing connection 0

Unknown SSL protocol


From both curl commands' output, we have found the following error:
* Unknown SSL protocol error in connection to 10.240.81.24:3651
* Curl_http_done: called premature == 1
The reason turns out to be that listen port 3651 on server 10.240.81.24 is non-SSL.

Useful Tools for SSL Debugging


Often an error message alone is not sufficient to solve the problem. In this case the following tools can be of help:[2]
  • SSLLabs can be used to check problems with public accessible HTTPS servers. It shows problems about certificate verification and also about potential problems with specific SSL clients.
  • In case it is not https or the server is not public accessible analyze.pl from my SSL tools can help. It can be used to debug SSL problems with plain SSL or explicit SSL on SMTP, IMAP, POP3 and FTPS and with HTTP proxies.
  • openssl helps with debugging too, especially with the s_client, s_server and x509 commands.
  • And wireshark can be used to analyse packet captures done by tcpdump or wireshark. It is able to show lots of details about the SSL handshake.
For example, below outputs are from analyze.pl:

D:\Todo>perl analyze-ssl.pl  --all-ciphers -v3 10.240.24.81:3651
+ checking host=10.240.24.81(10.240.24.81) port=3651
* version SSLv23, no verification, ciphers= -> FAIL! SSL wants a read first
* version SSLv23, no verification, ciphers=HIGH:ALL -> FAIL! SSL wants a read first
* version TLSv1_2, no verification, ciphers= -> FAIL! SSL wants a read first
* version TLSv1_2, no verification, ciphers=HIGH:ALL -> FAIL! SSL wants a read first
* version TLSv1_1, no verification, ciphers= -> FAIL! SSL wants a read first
* version TLSv1_1, no verification, ciphers=HIGH:ALL -> FAIL! SSL wants a read first
* version TLSv1, no verification, ciphers= -> FAIL! SSL wants a read first
* version TLSv1, no verification, ciphers=HIGH:ALL -> FAIL! SSL wants a read first
* version SSLv3, no verification, ciphers= -> FAIL! SSL wants a read first
* version SSLv3, no verification, ciphers=HIGH:ALL -> FAIL! SSL wants a read first
10.240.24.81 failed basic SSL connect: SSL wants a read first

Note that the SSL_ERROR_WANT_READ means SSL handshake between client and server didn't complete.  In our case, this is because listen port 3651 is non-SSL.

No comments: