TLS (Transport Layer Security) and SSL (Secure Socket Layer) are protocols used to ensure a secure connection between a client and a server through authentication, encryption and data integrity. These protocols are mostly used with web applications in combination with the HTTP protocol but are also used with other protocols such as SMTP, IMAP, FTP and VPN connections.

Image src: Pixabay

What then are TLS/ SSL ciphers? In order to ensure data encryption, SSL and TLS protocols use one or many cipher suites. A cipher suite is a combination of algorithms that ensure data authentication, encryption and integrity. These ciphers are used in negotiating security settings in a TLS/ SSL connection and also during data transfer. The stronger the ciphers, the harder it is for hackers to break.

What is Cipherscan? Cipherscan is a way of checking the ciphersuites supported by the target and it works by testing the site TLS/ SSL ordering. The collected information is important in analyzing how secure a site is as well as for planning for more hardening of the website. As mentioned before, stronger ciphers makes it hard for attackers to break and get access to website files. In this guide, we are going to look at how to use Cipherscan to test website TLS/ SSL ciphers.

Checking target SSL/ TLS with Cipherscan

First you need to download Cipherscan set up to your system. Clone Cipherscan set up from Github using the following command.

$ git clone https://github.com/mozilla/cipherscan.git
Cloning into 'cipherscan'...
remote: Enumerating objects: 4, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 1307 (delta 0), reused 1 (delta 0), pack-reused 1303
Receiving objects: 100% (1307/1307), 34.54 MiB | 1.25 MiB/s, done.
Resolving deltas: 100% (743/743), done.

Once cloned, a Ciphercan directory will be added to your system. Check using the below commands.

cd cipherscan/
ls

Output

To check a website TTL/ SSL with Cipherscan, run the command as shown.

$ ./cipherscan <your-target-website>

As an example, let us check the supported ciphersuites for facebook.com. Ensure you are in the Cipherscan directory

cd cipherscan/

Please note that Bash version 4 is required to run cipherscan. For macOS update Bash and install coreutils with the command below.

$ brew install bash coreutils
==> Downloading https://homebrew.bintray.com/bottles/bash-5.0.18.catalina.bottle.tar.gz
==> Downloading from https://d29vzk4ow07wi7.cloudfront.net/c6e7b7a521a1cfb21f2872bde253bfd40150bd4ba36ada62c05fcdb73ae094c6?response-content-disposition=attachmen
######################################################################## 100.0%
==> Pouring bash-5.0.18.catalina.bottle.tar.gz
🍺  /usr/local/Cellar/bash/5.0.18: 150 files, 9.5MB

Run the below command to see www.facebook.com ciphersuites

$ ./cipherscan www.facebook.com
...............................
./cscan.sh: tlslite-ng not found, downloading...
Cloning into '.tlslite-ng'...
remote: Enumerating objects: 280, done.
remote: Counting objects: 100% (280/280), done.
remote: Compressing objects: 100% (219/219), done.
remote: Total 280 (delta 68), reused 138 (delta 57), pack-reused 0
Receiving objects: 100% (280/280), 473.86 KiB | 171.00 KiB/s, done.
Resolving deltas: 100% (68/68), done.

./cscan.sh: python-ecdsa not found, downloading...
Cloning into '.python-ecdsa'...
remote: Enumerating objects: 45, done.
remote: Counting objects: 100% (45/45), done.
remote: Compressing objects: 100% (42/42), done.
remote: Total 45 (delta 1), reused 16 (delta 1), pack-reused 0
Unpacking objects: 100% (45/45), 123.26 KiB | 318.00 KiB/s, done.
Traceback (most recent call last):
  File "cscan.py", line 6, in 
    from tlslite.messages import ClientHello, ServerHello, ServerHelloDone, Alert
  File "/root/cipherscan/tlslite/__init__.py", line 25, in 
    from tlslite.api import *
  File "/root/cipherscan/tlslite/api.py", line 5, in 
    from .constants import AlertLevel, AlertDescription, Fault
  File "/root/cipherscan/tlslite/constants.py", line 11, in 
    from .utils.compat import a2b_hex
  File "/root/cipherscan/tlslite/utils/compat.py", line 14, in 
    import ecdsa
  File "/root/cipherscan/ecdsa/__init__.py", line 1, in 
    from .keys import (
  File "/root/cipherscan/ecdsa/keys.py", line 71, in 
    from six import PY2, b
ImportError: No module named six
.
Target: www.facebook.com:443

prio  ciphersuite                    protocols              pubkey_size  signature_algoritm       trusted  ticket_hint  ocsp_staple  npn   pfs                 curves      curves_ordering
1     ECDHE-ECDSA-AES128-GCM-SHA256  TLSv1.2                256          sha256WithRSAEncryption  True     172800       False        None  ECDH,P-256,256bits  prime256v1  server
2     ECDHE-ECDSA-AES256-GCM-SHA384  TLSv1.2                256          sha256WithRSAEncryption  True     172800       False        None  ECDH,P-256,256bits  prime256v1  server
3     ECDHE-RSA-AES128-GCM-SHA256    TLSv1.2                2048         sha256WithRSAEncryption  True     172800       False        None  ECDH,P-256,256bits  prime256v1  server
4     ECDHE-RSA-AES256-GCM-SHA384    TLSv1.2                2048         sha256WithRSAEncryption  True     172800       False        None  ECDH,P-256,256bits  prime256v1  server
5     ECDHE-ECDSA-AES128-SHA         TLSv1,TLSv1.1,TLSv1.2  256          sha256WithRSAEncryption  True     172800       False        None  ECDH,P-256,256bits  prime256v1  server
6     ECDHE-ECDSA-AES256-SHA         TLSv1,TLSv1.1,TLSv1.2  256          sha256WithRSAEncryption  True     172800       False        None  ECDH,P-256,256bits  prime256v1  server
7     ECDHE-RSA-AES128-SHA           TLSv1,TLSv1.1,TLSv1.2  2048         sha256WithRSAEncryption  True     172800       False        None  ECDH,P-256,256bits  prime256v1  server
8     ECDHE-RSA-AES256-SHA           TLSv1,TLSv1.1,TLSv1.2  2048         sha256WithRSAEncryption  True     172800       False        None  ECDH,P-256,256bits  prime256v1  server
9     AES128-GCM-SHA256              TLSv1.2                2048         sha256WithRSAEncryption  True     172800       False        None  None                None        server
10    AES256-GCM-SHA384              TLSv1.2                2048         sha256WithRSAEncryption  True     172800       False        None  None                None        server
11    AES128-SHA                     TLSv1,TLSv1.1,TLSv1.2  2048         sha256WithRSAEncryption  True     172800       False        None  None                None        server
12    AES256-SHA                     TLSv1,TLSv1.1,TLSv1.2  2048         sha256WithRSAEncryption  True     172800       False        None  None                None        server
13    ECDHE-ECDSA-DES-CBC3-SHA       TLSv1,TLSv1.1,TLSv1.2  256          sha256WithRSAEncryption  True     172800       False        None  ECDH,P-256,256bits  prime256v1  server
14    ECDHE-RSA-DES-CBC3-SHA         TLSv1,TLSv1.1,TLSv1.2  2048         sha256WithRSAEncryption  True     172800       False        None  ECDH,P-256,256bits  prime256v1  server
15    DES-CBC3-SHA                   TLSv1,TLSv1.1,TLSv1.2  2048         sha256WithRSAEncryption  True     172800       False        None  None                None        server
16    ECDHE-ECDSA-RC4-SHA            TLSv1,TLSv1.1,TLSv1.2  256          sha256WithRSAEncryption  True     172800       False        None  ECDH,P-256,256bits  prime256v1  server
17    ECDHE-RSA-RC4-SHA              TLSv1,TLSv1.1,TLSv1.2  2048         sha256WithRSAEncryption  True     172800       False        None  ECDH,P-256,256bits  prime256v1  server
18    RC4-SHA                        TLSv1,TLSv1.1,TLSv1.2  2048         sha256WithRSAEncryption  True     172800       False        None  None                None        server

OCSP stapling: not supported
Cipher ordering: server
Curves ordering: server - fallback: no
Server supports secure renegotiation
Server supported compression methods: NONE
TLS Tolerance: yes

You can exporting the results as JSON with the -j command line option:

$ ./cipherscan --curves -j techviewleo.com | jq
{
  "target": "techviewleo.com:443",
  "utctimestamp": "2020-07-20T18:15:41.0Z",
  "serverside": "True",
  "ciphersuite": [
    {
      "cipher": "ECDHE-ECDSA-CHACHA20-POLY1305",
      "protocols": [
        "TLSv1.2"
      ],
      "pubkey": [
        "256"
      ],
      "sigalg": [
        "ecdsa-with-SHA256"
      ],
      "trusted": "True",
      "ticket_hint": "64800",
      "ocsp_stapling": "False",
      "npn": [
        "h2",
        "http/1.1"
      ],
      "pfs": "ECDH,P-256,256bits",
      "curves": [
        "prime256v1"
      ],
      "curves_ordering": "server"
    },
    {
      "cipher": "ECDHE-ECDSA-AES128-GCM-SHA256",
      "protocols": [
        "TLSv1.2"
      ],
      "pubkey": [
        "256"
      ],
      "sigalg": [
        "ecdsa-with-SHA256"
      ],
      "trusted": "True",
      "ticket_hint": "64800",
      "ocsp_stapling": "False",
      "npn": [
        "h2",
        "http/1.1"
      ],
      "pfs": "ECDH,P-256,256bits",
      "curves": [
        "prime256v1"
      ],
      "curves_ordering": "server"
    },
    {
      "cipher": "ECDHE-ECDSA-AES128-SHA",
      "protocols": [
        "TLSv1",
        "TLSv1.1",
        "TLSv1.2"
      ],
      "pubkey": [
        "256"
      ],
      "sigalg": [
        "ecdsa-with-SHA256"
      ],
      "trusted": "True",
      "ticket_hint": "64800",
      "ocsp_stapling": "False",
      "npn": [
        "h2",
        "http/1.1"
      ],
      "pfs": "ECDH,P-256,256bits",
      "curves": [
        "prime256v1"
      ],
      "curves_ordering": "server"
    },
    {
      "cipher": "ECDHE-ECDSA-AES128-SHA256",
      "protocols": [
        "TLSv1.2"
      ],
      "pubkey": [
        "256"
      ],
      "sigalg": [
        "ecdsa-with-SHA256"
      ],
      "trusted": "True",
      "ticket_hint": "64800",
      "ocsp_stapling": "False",
      "npn": [
        "h2",
        "http/1.1"
      ],
      "pfs": "ECDH,P-256,256bits",
      "curves": [
        "prime256v1"
      ],
      "curves_ordering": "server"
    },
    {
      "cipher": "ECDHE-ECDSA-AES256-GCM-SHA384",
      "protocols": [
        "TLSv1.2"
      ],
      "pubkey": [
        "256"
      ],
      "sigalg": [
        "ecdsa-with-SHA256"
      ],
      "trusted": "True",
      "ticket_hint": "64800",
      "ocsp_stapling": "False",
      "npn": [
        "h2",
        "http/1.1"
      ],
      "pfs": "ECDH,P-256,256bits",
      "curves": [
        "prime256v1"
      ],
      "curves_ordering": "server"
    },
    {
      "cipher": "ECDHE-ECDSA-AES256-SHA",
      "protocols": [
        "TLSv1",
        "TLSv1.1",
        "TLSv1.2"
      ],
      "pubkey": [
        "256"
      ],
      "sigalg": [
        "ecdsa-with-SHA256"
      ],
      "trusted": "True",
      "ticket_hint": "64800",
      "ocsp_stapling": "False",
      "npn": [
        "h2",
        "http/1.1"
      ],
      "pfs": "ECDH,P-256,256bits",
      "curves": [
        "prime256v1"
      ],
      "curves_ordering": "server"
    },
    {
      "cipher": "ECDHE-ECDSA-AES256-SHA384",
      "protocols": [
        "TLSv1.2"
      ],
      "pubkey": [
        "256"
      ],
      "sigalg": [
        "ecdsa-with-SHA256"
      ],
      "trusted": "True",
      "ticket_hint": "64800",
      "ocsp_stapling": "False",
      "npn": [
        "h2",
        "http/1.1"
      ],
      "pfs": "ECDH,P-256,256bits",
      "curves": [
        "prime256v1"
      ],
      "curves_ordering": "server"
    }
  ],
  "curves_fallback": "False",
  "renegotiation": "secure",
  "compression": "NONE",
  "configs": {
    "big-SSLv3": {
      "tolerant": "False"
    },
    "big-TLSv1.0": {
      "tolerant": "True",
      "proto": "TLSv1",
      "cipher": "ECDHE-ECDSA-AES128-SHA",
      "trusted": "True"
    },
    "big-TLSv1.1": {
      "tolerant": "True",
      "proto": "TLSv1.1",
      "cipher": "ECDHE-ECDSA-AES128-SHA",
      "trusted": "True"
    },
    "big-TLSv1.2": {
      "tolerant": "True",
      "proto": "TLSv1.2",
      "cipher": "ECDHE-ECDSA-CHACHA20-POLY1305",
      "trusted": "True"
    }
  },
  "intolerancies": {
    "TLS 1.4": false,
    "TLS 1.3": false,
    "TLS 1.2": false,
    "TLS 1.1": false,
    "TLS 1.0": false,
    "SSL 3.254": false
  }
}

You can also get output of the recommendations for good TLS on your endpoints.

$ ./analyze.py -t techviewleo.com
techviewleo.com:443 has obscure or unknown ssl/tls

Changes needed to match the old level:
* enable TLSv1.3
* add cipher DES-CBC3-SHA
* use a certificate with sha1WithRSAEncryption signature
* consider enabling OCSP Stapling

Changes needed to match the intermediate level:
* remove cipher ECDHE-ECDSA-AES128-SHA
* remove cipher ECDHE-ECDSA-AES128-SHA256
* remove cipher ECDHE-ECDSA-AES256-SHA
* remove cipher ECDHE-ECDSA-AES256-SHA384
* disable TLSv1.1
* disable TLSv1
* consider enabling TLSv1.3
* consider enabling OCSP Stapling
* enforce client side ordering

Changes needed to match the modern level:
* remove cipher ECDHE-ECDSA-CHACHA20-POLY1305
* remove cipher ECDHE-ECDSA-AES128-GCM-SHA256
* remove cipher ECDHE-ECDSA-AES128-SHA
* remove cipher ECDHE-ECDSA-AES128-SHA256
* remove cipher ECDHE-ECDSA-AES256-GCM-SHA384
* remove cipher ECDHE-ECDSA-AES256-SHA
* remove cipher ECDHE-ECDSA-AES256-SHA384
* disable TLSv1.1
* disable TLSv1
* disable TLSv1.2
* consider enabling TLSv1.3
* consider enabling OCSP Stapling
* enforce client side ordering

Note on Nagios mode: analyse.py can be ran as a nagios check with --nagios. The exit code will then represent the state of the configuration:

  • 2 (critical) for bad tls
  • 1 (warning) if it doesn’t match the desired level
  • 0 (ok) if it matches. cipherscan can take more than 10 seconds to complete. To alleviate any timeout issues, you may want to run it outside of nagios, passing data through some temporary file.

Enjoy your Cipherscan usage!

LEAVE A REPLY

Please enter your comment!
Please enter your name here

3 − 3 =