Search code examples
sslawktexttls1.2nmap

Using awk on Nmap ssl-enum-cipher results


I'm creating a bash script that loops through a collection of IP-addresses and scans them with the Nmap ssl-enum-ciphers script. Everything works just fine except for one feature.

I need to find a way how I can link the scanned port with the TLS versions & ciphers found.

The Nmap data looks like this ->

PORT     STATE SERVICE    VERSION
21/tcp   open  ftp        vsftpd 3.0.2
| ssl-enum-ciphers: 
|   TLSv1.0: 
|     ciphers: 
|       TLS_DHE_RSA_WITH_AES_128_CBC_SHA (dh 1024) - A
|       TLS_DHE_RSA_WITH_AES_256_CBC_SHA (dh 1024) - A
|       TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA (dh 1024) - A
|       TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA (dh 1024) - A
|       TLS_DH_anon_WITH_AES_128_CBC_SHA (dh 1024) - F
|       TLS_DH_anon_WITH_AES_256_CBC_SHA (dh 1024) - F
|       TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA (dh 1024) - F
|       TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA (dh 1024) - F
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_ECDH_anon_WITH_AES_128_CBC_SHA (secp256r1) - F
|       TLS_ECDH_anon_WITH_AES_256_CBC_SHA (secp256r1) - F
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 4096) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 4096) - A
|       TLS_RSA_WITH_CAMELLIA_128_CBC_SHA (rsa 4096) - A
|       TLS_RSA_WITH_CAMELLIA_256_CBC_SHA (rsa 4096) - A
|     compressors: 
|       NULL
|     cipher preference: client
|     warnings: 
|       Anonymous key exchange, score capped at F
|       Key exchange (dh 1024) of lower strength than certificate key
|       Key exchange (secp256r1) of lower strength than certificate key
|   TLSv1.2: 
|     ciphers: 
|       TLS_DHE_RSA_WITH_AES_128_CBC_SHA (dh 1024) - A
|       TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 (dh 1024) - A
|       TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 (dh 1024) - A
|       TLS_DHE_RSA_WITH_AES_256_CBC_SHA (dh 1024) - A
|       TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 (dh 1024) - A
|       TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 (dh 1024) - A
|       TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA (dh 1024) - A
|       TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA (dh 1024) - A
|       TLS_DH_anon_WITH_AES_128_CBC_SHA (dh 1024) - F
|       TLS_DH_anon_WITH_AES_128_CBC_SHA256 (dh 1024) - F
|       TLS_DH_anon_WITH_AES_128_GCM_SHA256 (dh 1024) - F
|       TLS_DH_anon_WITH_AES_256_CBC_SHA (dh 1024) - F
|       TLS_DH_anon_WITH_AES_256_CBC_SHA256 (dh 1024) - F
|       TLS_DH_anon_WITH_AES_256_GCM_SHA384 (dh 1024) - F
|       TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA (dh 1024) - F
|       TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA (dh 1024) - F
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (secp256r1) - A
|       TLS_ECDH_anon_WITH_AES_128_CBC_SHA (secp256r1) - F
|       TLS_ECDH_anon_WITH_AES_256_CBC_SHA (secp256r1) - F
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 4096) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA256 (rsa 4096) - A
|       TLS_RSA_WITH_AES_128_GCM_SHA256 (rsa 4096) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 4096) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA256 (rsa 4096) - A
|       TLS_RSA_WITH_AES_256_GCM_SHA384 (rsa 4096) - A
|       TLS_RSA_WITH_CAMELLIA_128_CBC_SHA (rsa 4096) - A
|       TLS_RSA_WITH_CAMELLIA_256_CBC_SHA (rsa 4096) - A
|     compressors: 
|       NULL
|     cipher preference: client
|     warnings: 
|       Anonymous key exchange, score capped at F
|       Key exchange (dh 1024) of lower strength than certificate key
|       Key exchange (secp256r1) of lower strength than certificate key
|_  least strength: F
22/tcp   open  ssh        OpenSSH 7.4 (protocol 2.0)
80/tcp   open  http       nginx
443/tcp  open  ssl/http   nginx
| ssl-enum-ciphers: 
|   TLSv1.2: 
|     ciphers: 
|       TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (secp256r1) - A
|     compressors: 
|       NULL
|     cipher preference: server
|_  least strength: A

I need to format this data in something like this ->

21/tcp   open  ftp        vsftpd 3.0.2
| ssl-enum-ciphers: 
|   TLSv1.0: 
|     ciphers: 
|       TLS_DHE_RSA_WITH_AES_128_CBC_SHA (dh 1024) - A
|       TLS_DHE_RSA_WITH_AES_256_CBC_SHA (dh 1024) - A
|       TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA (dh 1024) - A
|       TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA (dh 1024) - A
|       TLS_DH_anon_WITH_AES_128_CBC_SHA (dh 1024) - F
|       TLS_DH_anon_WITH_AES_256_CBC_SHA (dh 1024) - F
|       TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA (dh 1024) - F
|       TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA (dh 1024) - F
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_ECDH_anon_WITH_AES_128_CBC_SHA (secp256r1) - F
|       TLS_ECDH_anon_WITH_AES_256_CBC_SHA (secp256r1) - F
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 4096) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 4096) - A
|       TLS_RSA_WITH_CAMELLIA_128_CBC_SHA (rsa 4096) - A
|       TLS_RSA_WITH_CAMELLIA_256_CBC_SHA (rsa 4096) - A
|   TLSv1.2: 
|     ciphers: 
|       TLS_DHE_RSA_WITH_AES_128_CBC_SHA (dh 1024) - A
|       TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 (dh 1024) - A
|       TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 (dh 1024) - A
|       TLS_DHE_RSA_WITH_AES_256_CBC_SHA (dh 1024) - A
|       TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 (dh 1024) - A
|       TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 (dh 1024) - A
|       TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA (dh 1024) - A
|       TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA (dh 1024) - A
|       TLS_DH_anon_WITH_AES_128_CBC_SHA (dh 1024) - F
|       TLS_DH_anon_WITH_AES_128_CBC_SHA256 (dh 1024) - F
|       TLS_DH_anon_WITH_AES_128_GCM_SHA256 (dh 1024) - F
|       TLS_DH_anon_WITH_AES_256_CBC_SHA (dh 1024) - F
|       TLS_DH_anon_WITH_AES_256_CBC_SHA256 (dh 1024) - F
|       TLS_DH_anon_WITH_AES_256_GCM_SHA384 (dh 1024) - F
|       TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA (dh 1024) - F
|       TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA (dh 1024) - F
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (secp256r1) - A
|       TLS_ECDH_anon_WITH_AES_128_CBC_SHA (secp256r1) - F
|       TLS_ECDH_anon_WITH_AES_256_CBC_SHA (secp256r1) - F
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 4096) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA256 (rsa 4096) - A
|       TLS_RSA_WITH_AES_128_GCM_SHA256 (rsa 4096) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 4096) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA256 (rsa 4096) - A
|       TLS_RSA_WITH_AES_256_GCM_SHA384 (rsa 4096) - A
|       TLS_RSA_WITH_CAMELLIA_128_CBC_SHA (rsa 4096) - A
|       TLS_RSA_WITH_CAMELLIA_256_CBC_SHA (rsa 4096) - A
443/tcp  open  ssl/http   nginx
| ssl-enum-ciphers: 
|   TLSv1.2: 
|     ciphers: 
|       TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (secp256r1) - A

I've managed to create a awk script that collects all the open ports with status and versions running ->

    #!/usr/bin/awk -f
    
    /open/ {
        port = $1
        state = $2
        service = $3
    }
    /ssl-enum-ciphers/ {
        print port, state, service
    }

outputs ->

21/tcp open ftp
443/tcp open ssl/http

As you can see the only things that are missing are the found TLS versions + ciphers. Can someone give me a push in the right direction?

Thanks in advance,

Sleek


Solution

  • Using a reduced dataset:

    $ cat nmap.dat
    PORT     STATE SERVICE    VERSION
    21/tcp   open  ftp        vsftpd 3.0.2
    | ssl-enum-ciphers:
    |   TLSv1.0:
    |     ciphers:
    |       TLS_DHE_RSA_WITH_AES_128_CBC_SHA (dh 1024) - A
    |       TLS_DHE_RSA_WITH_AES_256_CBC_SHA (dh 1024) - A
    |     compressors:
    |       NULL
    |     cipher preference: client
    |     warnings:
    |       Anonymous key exchange, score capped at F
    |       Key exchange (dh 1024) of lower strength than certificate key
    |   TLSv1.2:
    |     ciphers:
    |       TLS_DHE_RSA_WITH_AES_128_CBC_SHA (dh 1024) - A
    |       TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 (dh 1024) - A
    |     compressors:
    |       NULL
    |     cipher preference: client
    |     warnings:
    |       Anonymous key exchange, score capped at F
    |       Key exchange (dh 1024) of lower strength than certificate key
    |_  least strength: F
    22/tcp   open  ssh        OpenSSH 7.4 (protocol 2.0)
    80/tcp   open  http       nginx
    443/tcp  open  ssl/http   nginx
    | ssl-enum-ciphers:
    |   TLSv1.2:
    |     ciphers:
    |       TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (secp256r1) - A
    |       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (secp256r1) - A
    |     compressors:
    |       NULL
    |     cipher preference: server
    |_  least strength: A
    

    General approach is to use a flag (printme) to determine when to print a line; comparisons will determine when to turn on (1) or off (0) the flag.

    One awk idea:

    awk '
    /open/               { port = $1
                           state = $2
                           service = $3
                         }
    /ssl-enum-ciphers/   { print port, state, service
                           printme=1
                         }
    /compressors:/       { printme=0 }
    /cipher preference:/ { printme=0 }
    /warnings:/          { printme=0 }
    /TLS.*:/             { printme=1 }
    printme
    ' nmap.dat
    

    NOTES:

    • assumes all cipher subsections (under ssl-enum-ciphers) of interest are of the form TLS*:; otherwise OP can add more patterns for enabling the print flag (printme=1)
    • based solely on the provided sample input a single test for /compressors:/ should be sufficient to clear the print flag (printme=0); I'm not familiar with all possible nmap output formats so I've gone ahead and added the /cipher preference:/ and /warnings:/ tests, too; these last two tests can be removed if OP determines /compressors:/ is sufficient for clearing the print flag

    This generates:

    21/tcp open ftp
    | ssl-enum-ciphers:
    |   TLSv1.0:
    |     ciphers:
    |       TLS_DHE_RSA_WITH_AES_128_CBC_SHA (dh 1024) - A
    |       TLS_DHE_RSA_WITH_AES_256_CBC_SHA (dh 1024) - A
    |   TLSv1.2:
    |     ciphers:
    |       TLS_DHE_RSA_WITH_AES_128_CBC_SHA (dh 1024) - A
    |       TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 (dh 1024) - A
    443/tcp open ssl/http
    | ssl-enum-ciphers:
    |   TLSv1.2:
    |     ciphers:
    |       TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (secp256r1) - A
    |       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (secp256r1) - A