TLS Verification and Testing

HOW TLS WORKS

TLS version negotiation is typically performed as part of the SSL/TLS handshake process.

When a client initiates a TLS connection, it sends a “ClientHello” message which includes the highest version of TLS it supports. The server responds with a “ServerHello” message, which includes the version of TLS that will be used for the connection.

The server should select the highest version that both the client and server support. If the client supports up to TLS 1.2, and the server supports up to TLS 1.1, then TLS 1.1 would be used. If the client supports up to TLS 1.1, and the server supports up to TLS 1.2, then TLS 1.1 would be used.

However, if the client supports up to TLS 1.2 and the server also supports up to TLS 1.2, then TLS 1.2 will be used for the connection.

Now, if the server only supports TLSv1.2 and the client only supports up to TLSv1.1, the handshake process will fail because there isn’t a common version of TLS protocol that both the client and server can agree upon.

In such a case, the client will typically see an error message indicating that the SSL/TLS handshake failed, and the connection will not be established. The exact error message will depend on the software being used by the client, but it usually indicates some kind of protocol version mismatch or unsupported protocol version.

This kind of situation is one of the reasons why it’s important to keep software up-to-date. More recent versions of software are more likely to support newer versions of protocols like TLS. At the same time, software developers and system administrators need to strike a balance between supporting older versions for backward compatibility and disabling them for security reasons.

So at the end of the day, both the client and the server play a role in determining which version of TLS is used, but the final decision is typically made by the server, which should choose the highest version that both endpoints support.

Note that this is the typical behavior, but it can depend on the specific implementation of TLS on both the client and the server. Some servers can be configured to only allow certain versions of TLS, even if both the client and server technically support a higher version.

 

GET A LIST OF TLS VERSIONS A SERVER IS USING

In order to check which TLS versions a remote server supports, you have to test the connection with each TLS version. Unfortunately, there’s no direct method to list all TLS versions a server supports with a single command.

Using the commands I previously provided, you can iterate through the different TLS versions and verify which ones are successful. Here’s how you can do it with each tool:

PowerShell:

You’ll need to run a separate command for each version of TLS. You can easily create a loop in PowerShell to iterate through the different versions:

$server = "cordero.me"; $port = 443
$tlsVersions = "Tls", "Tls11", "Tls12", "Tls13"
foreach ($tlsVersion in $tlsVersions) {
$tcpClient = New-Object System.Net.Sockets.TcpClient($server, $port)
$sslStream = New-Object System.Net.Security.SslStream($tcpClient.GetStream())
$sslProtocols = [System.Security.Authentication.SslProtocols]::$tlsVersion
try {
$sslStream.AuthenticateAsClient($server, $null, $sslProtocols, $false)
Write-Output "$tlsVersion: Success"
}
catch {
Write-Output "$tlsVersion: Failed"
}
}

This script will output whether each TLS version was successful or failed.

OpenSSL:

You can create a bash script (or manually run the commands) to check each version of TLS:

for version in tls1 tls1_1 tls1_2 tls1_3
do
echo -n "Testing $version: "
if openssl s_client -connect cordero.me:443 -$version < /dev/null > /dev/null 2>&1
then
echo "Success"
else
echo "Failed"
fi
done

This script will output whether each TLS version was successful or failed.

cURL:

Similarly to OpenSSL, you can create a bash script (or manually run the commands) to check each version of TLS:

for version in tlsv1.0 tlsv1.1 tlsv1.2 tlsv1.3
do
echo -n "Testing $version: "
if curl --$version -k -s https://cordero.me > /dev/null
then
echo "Success"
else
echo "Failed"
fi
done

This script will output whether each TLS version was successful or failed.

Again, remember to adhere to your organization’s policies and guidelines when performing these tests.

Nmap:

To use `nmap` to scan for SSL/TLS versions, you can use the `ssl-enum-ciphers` script like this:

nmap --script ssl-enum-ciphers -p 443 cordero.me

The `ssl-enum-ciphers` script will provide a list of SSL/TLS protocols and ciphers that the server accepts. You can check the output under the “SSLv3“, “TLSv1.0“, “TLSv1.1“, “TLSv1.2“, and “TLSv1.3” headings to see if these protocols are accepted by the server.

Python:

For Python, you can use the `ssl` module which provides access to the Transport Layer Security and Secure Sockets Layer protocol implementations in OpenSSL. Here’s a simple script that tests each TLS version:

import ssl
import socket

def check_tls_version(hostname, tls_version):
context = ssl.SSLContext(tls_version)
try:
with socket.create_connection((hostname, 443)) as sock:
with context.wrap_socket(sock, server_hostname=hostname) as ssock:
print(f"{tls_version}: Success")
except Exception as e:
print(f"{tls_version}: Failed ({str(e)})")

hostname = 'cordero.me'
tls_versions = [ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_3]
for tls_version in tls_versions:
check_tls_version(hostname, tls_version)

This script creates a socket connection to the server and tries to wrap the socket with each TLS version. If it is successful, it prints “Success”, otherwise it prints “Failed”. Note that `ssl.PROTOCOL_TLSv1_3` was added in Python 3.7.

Please be aware that these tests only check if a connection can be established with a specific TLS version, and not whether the server exclusively supports that version. Additionally, always ensure your tests comply with your organization’s policies and guidelines.

 

VERIFY TLS VERSION ON REMOTE SERVER

Here’s how you can check the supported TLS versions of a remote server using each of the tools you mentioned:

PowerShell:

PowerShell does not have a built-in way to determine which TLS versions a remote server supports. You can modify the previous script and run it multiple times, once for each TLS version, to see which versions are successful. Here’s the PowerShell command for TLS 1.2:

$server = "cordero.me"; $port = 443; $tcpClient = New-Object System.Net.Sockets.TcpClient($server, $port); $sslStream = New-Object System.Net.Security.SslStream($tcpClient.GetStream()); $sslProtocols = [System.Security.Authentication.SslProtocols]::Tls12; $sslStream.AuthenticateAsClient($server, $null, $sslProtocols, $false); $sslStream.SslProtocol

Change `Tls12` to `Tls`, `Tls11`, `Tls12`, or `Tls13` to test different versions.

OpenSSL:

You can use OpenSSL’s `s_client` command to test different TLS versions. Here’s the command for TLS 1.2:

openssl s_client -connect cordero.me:443 -tls1_2

You should see a successful connection message if the server supports TLS 1.2. Change `-tls1_2` to `-tls1`, `-tls1_1`, `-tls1_2`, or `-tls1_3` to test different versions.

cURL:

You can use cURL’s `–tlsv1.x` options to test different TLS versions. Here’s the command for TLS 1.2:

curl --tlsv1.2 https://cordero.me

You should see the server’s response if it supports TLS 1.2. Change `–tlsv1.2` to `–tlsv1.0`, `–tlsv1.1`, `–tlsv1.2`, or `–tlsv1.3` to test different versions.

Remember to replace “cordero.me” and “443” with the hostname and port of the server you’re testing. Please be aware that these methods only test if a connection can be established using a specific TLS version, not if a server exclusively supports that version. It’s also important to follow your organization’s policies and guidelines when performing these tests.

 

TEST WITH DIFFERENCE TLS VERSIONS

Powershell:

Yes, you can use PowerShell’s built-in `System.Net.Sockets.TcpClient` class along with `System.Net.Security.SslStream` to create a connection with a specific TLS version. Here’s how you can do it:

# Define the server and port you're connecting to
$server = "cordero.me"
$port = 443

# Create a TCP connection
$tcpClient = New-Object System.Net.Sockets.TcpClient($server, $port)

# Create an SSL stream over the TCP connection
$sslStream = New-Object System.Net.Security.SslStream($tcpClient.GetStream())

# Define the TLS version
$sslProtocols = [System.Security.Authentication.SslProtocols]::Tls12

# Authenticate as a client using the SSL stream
$sslStream.AuthenticateAsClient($server, $null, $sslProtocols, $false)

# Display the SSL/TLS version used for the connection
$sslStream.SslProtocol

In the `$sslProtocols` line, you can replace `Tls12` with `Tls` for TLS 1.0 or `Tls11` for TLS 1.1. After running this script, it will output the SSL/TLS version used for the connection. If the connection is successful, it means that the server supports that TLS version.

Please note that this script does not validate the server’s SSL certificate, so it should only be used for testing purposes. Additionally, this script will not work for servers that require a client certificate for authentication.

Also, keep in mind that these tests should be performed according to your organization’s guidelines, and the results should be monitored and recorded in your firewall logs.

OpenSSL

Here is how you can do it with OpenSSL:

1. Install OpenSSL:

First, you need to install OpenSSL on your Windows PC. You can download a precompiled version of OpenSSL from this website: https://slproweb.com/products/Win32OpenSSL.html. Choose the version that fits your system (32-bit or 64-bit).

2. Open PowerShell or Command Prompt:

After installing OpenSSL, you can use PowerShell or Command Prompt to run OpenSSL commands.

3. Initiate a Connection:

To initiate a connection using TLS 1.0, use the following command:

openssl s_client -connect <hostname>:<port> -tls1

Replace `<hostname>` with the hostname or IP address of the server you want to connect to, and replace `<port>` with the port number.

To initiate a connection using TLS 1.1, use the following command:

openssl s_client -connect <hostname>:<port> -tls1_1

After running these commands, you should see output showing the details of the connection, including the SSL/TLS version. You can use this to verify whether the connection using TLS 1.0 or TLS 1.1 was successful.

In addition to this, monitor the traffic logs on the Palo Alto firewall to confirm whether it detected and handled these connections as per your Firewall Policy. Remember to set your log forwarding and filtering settings accordingly to capture and identify these test events.

Curl

Yes, you can also use cURL to initiate connections using specific TLS versions. cURL is a powerful tool that can be used to transfer data with various protocols, including HTTPS. Here’s how you can use cURL to test TLS 1.0 and TLS 1.1:

First, you’ll need to have cURL installed on your machine. You can download it from the official cURL website. Windows 10 also includes cURL by default in its Command Prompt and PowerShell environments.

1. For TLS 1.0:

curl --tlsv1.0 https://www.cordero.me

2. For TLS 1.1:

curl --tlsv1.1 https://www.cordero.me

Remember to replace `www.cordero.me` with the hostname or IP address of the server you want to connect to.

By default, cURL outputs the contents of the resource you’re accessing. If you’re just interested in the connection details (like the SSL/TLS version), you can add the `-I` (or `–head`) option to fetch only the headers:

curl --tlsv1.0 -I https://www.cordero.me

Again, make sure to conduct your tests in accordance with your organization’s guidelines and policies. Monitor your firewall logs to see if the connections using TLS 1.0 and TLS 1.1 are detected and handled as per your firewall policy.