description = [[ This script repeatedly initiates SSL/TLS connections, each time removing whichever cipher or compressor was chosen by the server when making the previous connection. The end result is a list of all the ciphers and compressors that a server accepts. SSLv3/TLSv1 requires more effort to determine which ciphers and compression methods a server supports than SSLv2. A client lists the ciphers and compressors that it is capable of supporting, and the server will respond with a single cipher and compressor chosen, or a rejection notice. By default, the ciphers and compressors are presented in the order the server prefers them. Passing ssl-enum-ciphers.sort=name as an argument to this script will instead order them alphabetically, which is more useful for comparing cipher lists between servers. This script is intrusive since it must initiate many connections so a server, and therefore is quite noisy. For a server that supports 10 ciphers and 2 compressors, this script will need to initiate 14 connections (10 successful ciphers, 1 failed cipher, 2 accepted compressors, and 1 failed compressor). ]] --- -- @usage -- nmap --script ssl-enum-algorithms -p 443 -- -- @args ssl-enum-ciphers.sort If set to name, sort results -- alphabetically instead of in the order in which they were accepted. -- -- @output -- PORT STATE SERVICE REASON -- 443/tcp open https syn-ack -- | sslv3-enum: -- | SSLv3 -- | Ciphers (18) -- | TLS_RSA_WITH_AES_128_CBC_SHA -- | TLS_RSA_WITH_AES_256_CBC_SHA -- | TLS_RSA_WITH_3DES_EDE_CBC_SHA -- | TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA -- | TLS_RSA_WITH_DES_CBC_SHA -- | TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 -- | TLS_RSA_WITH_RC4_128_MD5 -- | TLS_RSA_EXPORT_WITH_RC4_40_MD5 -- | TLS_DHE_RSA_WITH_DES_CBC_SHA -- | TLS_RSA_WITH_CAMELLIA_256_CBC_SHA -- | TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA -- | TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA -- | TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA -- | TLS_DHE_RSA_WITH_AES_128_CBC_SHA -- | TLS_RSA_WITH_RC4_128_SHA -- | TLS_DHE_RSA_WITH_AES_256_CBC_SHA -- | TLS_RSA_WITH_CAMELLIA_128_CBC_SHA -- | TLS_RSA_EXPORT_WITH_DES40_CBC_SHA -- | Compressors (1) -- | uncompressed -- | TLSv1.0 -- | Ciphers (18) -- | TLS_RSA_WITH_AES_128_CBC_SHA -- | TLS_RSA_WITH_AES_256_CBC_SHA -- | TLS_RSA_WITH_3DES_EDE_CBC_SHA -- | TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA -- | TLS_RSA_WITH_DES_CBC_SHA -- | TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 -- | TLS_RSA_WITH_RC4_128_MD5 -- | TLS_RSA_EXPORT_WITH_RC4_40_MD5 -- | TLS_DHE_RSA_WITH_DES_CBC_SHA -- | TLS_RSA_WITH_CAMELLIA_256_CBC_SHA -- | TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA -- | TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA -- | TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA -- | TLS_DHE_RSA_WITH_AES_128_CBC_SHA -- | TLS_RSA_WITH_RC4_128_SHA -- | TLS_DHE_RSA_WITH_AES_256_CBC_SHA -- | TLS_RSA_WITH_CAMELLIA_128_CBC_SHA -- | TLS_RSA_EXPORT_WITH_DES40_CBC_SHA -- | Compressors (1) -- |_ uncompressed author = "Mak Kolybabi " license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "intrusive"} require("bin") require("nmap") require("shortport") require("stdnse") local SSL_PORTS = { 443, 465, 587, 636, 989, 990, 992, 993, 994, 995, 5061, 6679, 6697, 8443 } local SSL_SERVICES = { "ftps", "ftps-data", "https", "https-alt", "imaps", "ircs", "ldapssl", "pop3s", "sip-tls", "smtps", "telnets" } -- All of the values in the tables below are from: -- http://www.iana.org/assignments/tls-parameters/ PROTOCOLS = { ["SSLv3"] = 0x0300, ["TLSv1.0"] = 0x0301, ["TLSv1.1"] = 0x0302, ["TLSv1.2"] = 0x0303 } -- -- TLS Record Types -- TLS_RECORD_HEADER_LENGTH = 5 TLS_CONTENTTYPE_REGISTRY = { ["change_cipher_spec"] = 20, ["alert"] = 21, ["handshake"] = 22, ["application_data"] = 23 } -- -- TLS Alert Levels -- TLS_ALERT_LEVELS = { ["warning"] = 1, ["fatal"] = 2, } -- -- TLS Alert Record Types -- TLS_ALERT_REGISTRY = { ["close_notify"] = 0, ["unexpected_message"] = 10, ["bad_record_mac"] = 20, ["decryption_failed"] = 21, ["record_overflow"] = 22, ["decompression_failure"] = 30, ["handshake_failure"] = 40, ["no_certificate"] = 41, ["bad_certificate"] = 42, ["unsupported_certificate"] = 43, ["certificate_revoked"] = 44, ["certificate_expired"] = 45, ["certificate_unknown"] = 46, ["illegal_parameter"] = 47, ["unknown_ca"] = 48, ["access_denied"] = 49, ["decode_error"] = 50, ["decrypt_error"] = 51, ["export_restriction"] = 60, ["protocol_version"] = 70, ["insufficient_security"] = 71, ["internal_error"] = 80, ["user_canceled"] = 90, ["no_renegotiation"] = 100, ["unsupported_extension"] = 110, ["certificate_unobtainable"] = 111, ["unrecognized_name"] = 112, ["bad_certificate_status_response"] = 113, ["bad_certificate_hash_value"] = 114, ["unknown_psk_identity"] = 115 } -- -- TLS Handshake Record Types -- TLS_HANDSHAKETYPE_REGISTRY = { ["hello_request"] = 0, ["client_hello"] = 1, ["server_hello"] = 2, ["hello_verify_request"] = 3, ["NewSessionTicket"] = 4, ["certificate"] = 11, ["server_key_exchange"] = 12, ["certificate_request"] = 13, ["server_hello_done"] = 14, ["certificate_verify"] = 15, ["client_key_exchange"] = 16, ["finished"] = 20, ["certificate_url"] = 21, ["certificate_status"] = 22, ["supplemental_data"] = 23 } -- -- Compression Algorithms -- COMPRESSORS = { ["uncompressed"] = 0, ["ansiX962_compressed_prime"] = 1, ["ansiX962_compressed_char2"] = 2 } -- -- Encryption Algorithms -- CIPHERS = { ["TLS_NULL_WITH_NULL_NULL"] = 0x0000, ["TLS_RSA_WITH_NULL_MD5"] = 0x0001, ["TLS_RSA_WITH_NULL_SHA"] = 0x0002, ["TLS_RSA_EXPORT_WITH_RC4_40_MD5"] = 0x0003, ["TLS_RSA_WITH_RC4_128_MD5"] = 0x0004, ["TLS_RSA_WITH_RC4_128_SHA"] = 0x0005, ["TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5"] = 0x0006, ["TLS_RSA_WITH_IDEA_CBC_SHA"] = 0x0007, ["TLS_RSA_EXPORT_WITH_DES40_CBC_SHA"] = 0x0008, ["TLS_RSA_WITH_DES_CBC_SHA"] = 0x0009, ["TLS_RSA_WITH_3DES_EDE_CBC_SHA"] = 0x000A, ["TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA"] = 0x000B, ["TLS_DH_DSS_WITH_DES_CBC_SHA"] = 0x000C, ["TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA"] = 0x000D, ["TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA"] = 0x000E, ["TLS_DH_RSA_WITH_DES_CBC_SHA"] = 0x000F, ["TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA"] = 0x0010, ["TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"] = 0x0011, ["TLS_DHE_DSS_WITH_DES_CBC_SHA"] = 0x0012, ["TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA"] = 0x0013, ["TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA"] = 0x0014, ["TLS_DHE_RSA_WITH_DES_CBC_SHA"] = 0x0015, ["TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA"] = 0x0016, ["TLS_DH_anon_EXPORT_WITH_RC4_40_MD5"] = 0x0017, ["TLS_DH_anon_WITH_RC4_128_MD5"] = 0x0018, ["TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA"] = 0x0019, ["TLS_DH_anon_WITH_DES_CBC_SHA"] = 0x001A, ["TLS_DH_anon_WITH_3DES_EDE_CBC_SHA"] = 0x001B, ["TLS_KRB5_WITH_DES_CBC_SHA"] = 0x001E, ["TLS_KRB5_WITH_3DES_EDE_CBC_SHA"] = 0x001F, ["TLS_KRB5_WITH_RC4_128_SHA"] = 0x0020, ["TLS_KRB5_WITH_IDEA_CBC_SHA"] = 0x0021, ["TLS_KRB5_WITH_DES_CBC_MD5"] = 0x0022, ["TLS_KRB5_WITH_3DES_EDE_CBC_MD5"] = 0x0023, ["TLS_KRB5_WITH_RC4_128_MD5"] = 0x0024, ["TLS_KRB5_WITH_IDEA_CBC_MD5"] = 0x0025, ["TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA"] = 0x0026, ["TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA"] = 0x0027, ["TLS_KRB5_EXPORT_WITH_RC4_40_SHA"] = 0x0028, ["TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5"] = 0x0029, ["TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5"] = 0x002A, ["TLS_KRB5_EXPORT_WITH_RC4_40_MD5"] = 0x002B, ["TLS_PSK_WITH_NULL_SHA"] = 0x002C, ["TLS_DHE_PSK_WITH_NULL_SHA"] = 0x002D, ["TLS_RSA_PSK_WITH_NULL_SHA"] = 0x002E, ["TLS_RSA_WITH_AES_128_CBC_SHA"] = 0x002F, ["TLS_DH_DSS_WITH_AES_128_CBC_SHA"] = 0x0030, ["TLS_DH_RSA_WITH_AES_128_CBC_SHA"] = 0x0031, ["TLS_DHE_DSS_WITH_AES_128_CBC_SHA"] = 0x0032, ["TLS_DHE_RSA_WITH_AES_128_CBC_SHA"] = 0x0033, ["TLS_DH_anon_WITH_AES_128_CBC_SHA"] = 0x0034, ["TLS_RSA_WITH_AES_256_CBC_SHA"] = 0x0035, ["TLS_DH_DSS_WITH_AES_256_CBC_SHA"] = 0x0036, ["TLS_DH_RSA_WITH_AES_256_CBC_SHA"] = 0x0037, ["TLS_DHE_DSS_WITH_AES_256_CBC_SHA"] = 0x0038, ["TLS_DHE_RSA_WITH_AES_256_CBC_SHA"] = 0x0039, ["TLS_DH_anon_WITH_AES_256_CBC_SHA"] = 0x003A, ["TLS_RSA_WITH_NULL_SHA256"] = 0x003B, ["TLS_RSA_WITH_AES_128_CBC_SHA256"] = 0x003C, ["TLS_RSA_WITH_AES_256_CBC_SHA256"] = 0x003D, ["TLS_DH_DSS_WITH_AES_128_CBC_SHA256"] = 0x003E, ["TLS_DH_RSA_WITH_AES_128_CBC_SHA256"] = 0x003F, ["TLS_DHE_DSS_WITH_AES_128_CBC_SHA256"] = 0x0040, ["TLS_RSA_WITH_CAMELLIA_128_CBC_SHA"] = 0x0041, ["TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA"] = 0x0042, ["TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA"] = 0x0043, ["TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA"] = 0x0044, ["TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA"] = 0x0045, ["TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA"] = 0x0046, ["TLS_DHE_RSA_WITH_AES_128_CBC_SHA256"] = 0x0067, ["TLS_DH_DSS_WITH_AES_256_CBC_SHA256"] = 0x0068, ["TLS_DH_RSA_WITH_AES_256_CBC_SHA256"] = 0x0069, ["TLS_DHE_DSS_WITH_AES_256_CBC_SHA256"] = 0x006A, ["TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"] = 0x006B, ["TLS_DH_anon_WITH_AES_128_CBC_SHA256"] = 0x006C, ["TLS_DH_anon_WITH_AES_256_CBC_SHA256"] = 0x006D, ["TLS_RSA_WITH_CAMELLIA_256_CBC_SHA"] = 0x0084, ["TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA"] = 0x0085, ["TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA"] = 0x0086, ["TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA"] = 0x0087, ["TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA"] = 0x0088, ["TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA"] = 0x0089, ["TLS_PSK_WITH_RC4_128_SHA"] = 0x008A, ["TLS_PSK_WITH_3DES_EDE_CBC_SHA"] = 0x008B, ["TLS_PSK_WITH_AES_128_CBC_SHA"] = 0x008C, ["TLS_PSK_WITH_AES_256_CBC_SHA"] = 0x008D, ["TLS_DHE_PSK_WITH_RC4_128_SHA"] = 0x008E, ["TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA"] = 0x008F, ["TLS_DHE_PSK_WITH_AES_128_CBC_SHA"] = 0x0090, ["TLS_DHE_PSK_WITH_AES_256_CBC_SHA"] = 0x0091, ["TLS_RSA_PSK_WITH_RC4_128_SHA"] = 0x0092, ["TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA"] = 0x0093, ["TLS_RSA_PSK_WITH_AES_128_CBC_SHA"] = 0x0094, ["TLS_RSA_PSK_WITH_AES_256_CBC_SHA"] = 0x0095, ["TLS_RSA_WITH_SEED_CBC_SHA"] = 0x0096, ["TLS_DH_DSS_WITH_SEED_CBC_SHA"] = 0x0097, ["TLS_DH_RSA_WITH_SEED_CBC_SHA"] = 0x0098, ["TLS_DHE_DSS_WITH_SEED_CBC_SHA"] = 0x0099, ["TLS_DHE_RSA_WITH_SEED_CBC_SHA"] = 0x009A, ["TLS_DH_anon_WITH_SEED_CBC_SHA"] = 0x009B, ["TLS_RSA_WITH_AES_128_GCM_SHA256"] = 0x009C, ["TLS_RSA_WITH_AES_256_GCM_SHA384"] = 0x009D, ["TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"] = 0x009E, ["TLS_DHE_RSA_WITH_AES_256_GCM_SHA384"] = 0x009F, ["TLS_DH_RSA_WITH_AES_128_GCM_SHA256"] = 0x00A0, ["TLS_DH_RSA_WITH_AES_256_GCM_SHA384"] = 0x00A1, ["TLS_DHE_DSS_WITH_AES_128_GCM_SHA256"] = 0x00A2, ["TLS_DHE_DSS_WITH_AES_256_GCM_SHA384"] = 0x00A3, ["TLS_DH_DSS_WITH_AES_128_GCM_SHA256"] = 0x00A4, ["TLS_DH_DSS_WITH_AES_256_GCM_SHA384"] = 0x00A5, ["TLS_DH_anon_WITH_AES_128_GCM_SHA256"] = 0x00A6, ["TLS_DH_anon_WITH_AES_256_GCM_SHA384"] = 0x00A7, ["TLS_PSK_WITH_AES_128_GCM_SHA256"] = 0x00A8, ["TLS_PSK_WITH_AES_256_GCM_SHA384"] = 0x00A9, ["TLS_DHE_PSK_WITH_AES_128_GCM_SHA256"] = 0x00AA, ["TLS_DHE_PSK_WITH_AES_256_GCM_SHA384"] = 0x00AB, ["TLS_RSA_PSK_WITH_AES_128_GCM_SHA256"] = 0x00AC, ["TLS_RSA_PSK_WITH_AES_256_GCM_SHA384"] = 0x00AD, ["TLS_PSK_WITH_AES_128_CBC_SHA256"] = 0x00AE, ["TLS_PSK_WITH_AES_256_CBC_SHA384"] = 0x00AF, ["TLS_PSK_WITH_NULL_SHA256"] = 0x00B0, ["TLS_PSK_WITH_NULL_SHA384"] = 0x00B1, ["TLS_DHE_PSK_WITH_AES_128_CBC_SHA256"] = 0x00B2, ["TLS_DHE_PSK_WITH_AES_256_CBC_SHA384"] = 0x00B3, ["TLS_DHE_PSK_WITH_NULL_SHA256"] = 0x00B4, ["TLS_DHE_PSK_WITH_NULL_SHA384"] = 0x00B5, ["TLS_RSA_PSK_WITH_AES_128_CBC_SHA256"] = 0x00B6, ["TLS_RSA_PSK_WITH_AES_256_CBC_SHA384"] = 0x00B7, ["TLS_RSA_PSK_WITH_NULL_SHA256"] = 0x00B8, ["TLS_RSA_PSK_WITH_NULL_SHA384"] = 0x00B9, ["TLS_RENEGO_PROTECTION_REQUEST"] = 0x00FF, ["TLS_ECDH_ECDSA_WITH_NULL_SHA"] = 0xC001, ["TLS_ECDH_ECDSA_WITH_RC4_128_SHA"] = 0xC002, ["TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA"] = 0xC003, ["TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA"] = 0xC004, ["TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA"] = 0xC005, ["TLS_ECDHE_ECDSA_WITH_NULL_SHA"] = 0xC006, ["TLS_ECDHE_ECDSA_WITH_RC4_128_SHA"] = 0xC007, ["TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA"] = 0xC008, ["TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA"] = 0xC009, ["TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA"] = 0xC00A, ["TLS_ECDH_RSA_WITH_NULL_SHA"] = 0xC00B, ["TLS_ECDH_RSA_WITH_RC4_128_SHA"] = 0xC00C, ["TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA"] = 0xC00D, ["TLS_ECDH_RSA_WITH_AES_128_CBC_SHA"] = 0xC00E, ["TLS_ECDH_RSA_WITH_AES_256_CBC_SHA"] = 0xC00F, ["TLS_ECDHE_RSA_WITH_NULL_SHA"] = 0xC010, ["TLS_ECDHE_RSA_WITH_RC4_128_SHA"] = 0xC011, ["TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA"] = 0xC012, ["TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"] = 0xC013, ["TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"] = 0xC014, ["TLS_ECDH_anon_WITH_NULL_SHA"] = 0xC015, ["TLS_ECDH_anon_WITH_RC4_128_SHA"] = 0xC016, ["TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA"] = 0xC017, ["TLS_ECDH_anon_WITH_AES_128_CBC_SHA"] = 0xC018, ["TLS_ECDH_anon_WITH_AES_256_CBC_SHA"] = 0xC019, ["TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA"] = 0xC01A, ["TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA"] = 0xC01B, ["TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA"] = 0xC01C, ["TLS_SRP_SHA_WITH_AES_128_CBC_SHA"] = 0xC01D, ["TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA"] = 0xC01E, ["TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA"] = 0xC01F, ["TLS_SRP_SHA_WITH_AES_256_CBC_SHA"] = 0xC020, ["TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA"] = 0xC021, ["TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA"] = 0xC022, ["TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"] = 0xC023, ["TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384"] = 0xC024, ["TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256"] = 0xC025, ["TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384"] = 0xC026, ["TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"] = 0xC027, ["TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384"] = 0xC028, ["TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256"] = 0xC029, ["TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384"] = 0xC02A, ["TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"] = 0xC02B, ["TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"] = 0xC02C, ["TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256"] = 0xC02D, ["TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384"] = 0xC02E, ["TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"] = 0xC02F, ["TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"] = 0xC030, ["TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256"] = 0xC031, ["TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384"] = 0xC032, ["TLS_ECDHE_PSK_WITH_RC4_128_SHA"] = 0xC033, ["TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA"] = 0xC034, ["TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA"] = 0xC035, ["TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA"] = 0xC036, ["TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256"] = 0xC037, ["TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384"] = 0xC038, ["TLS_ECDHE_PSK_WITH_NULL_SHA"] = 0xC039, ["TLS_ECDHE_PSK_WITH_NULL_SHA256"] = 0xC03A, ["TLS_ECDHE_PSK_WITH_NULL_SHA384"] = 0xC03B } local function record_read(buffer, i) local _, b, h, j, len local function find_key(t, value) local k, v for k, v in pairs(t) do if v == value then return k end end return nil end ------------ -- Header -- ------------ -- Ensure we have enough data for the header. if #buffer - i < TLS_RECORD_HEADER_LENGTH then return i, nil end -- Parse header. h = {} j, h["type"] = bin.unpack("C", buffer, i) j, h["protocol"] = bin.unpack(">S", buffer, j) j, h["length"] = bin.unpack(">S", buffer, j) -- Ensure we have enough data for the body. len = j + h["length"] if #buffer < len then return i, nil end -- Convert to human-readable form. h["type"] = find_key(TLS_CONTENTTYPE_REGISTRY, h["type"]) h["protocol"] = find_key(PROTOCOLS, h["protocol"]) ---------- -- Body -- ---------- b = {} h["body"] = b if h["type"] == "alert" then -- Parse body. j, b["level"] = bin.unpack("C", buffer, j) j, b["description"] = bin.unpack("C", buffer, j) -- Convert to human-readable form. b["level"] = find_key(TLS_ALERT_LEVELS, b["level"]) b["description"] = find_key(TLS_ALERT_REGISTRY, b["description"]) elseif h["type"] == "handshake" then -- Parse body. j, b["type"] = bin.unpack("C", buffer, j) j, _ = bin.unpack("A3", buffer, j) -- Convert to human-readable form. b["type"] = find_key(TLS_HANDSHAKETYPE_REGISTRY, b["type"]) if b["type"] == "server_hello" then -- Parse body. j, b["protocol"] = bin.unpack(">S", buffer, j) j, b["time"] = bin.unpack(">I", buffer, j) j, b["random"] = bin.unpack("A28", buffer, j) j, b["session_id_length"] = bin.unpack("C", buffer, j) j, b["session_id"] = bin.unpack("A" .. b["session_id_length"], buffer, j) j, b["cipher"] = bin.unpack(">S", buffer, j) j, b["compressor"] = bin.unpack("C", buffer, j) -- Convert to human-readable form. b["protocol"] = find_key(PROTOCOLS, b["protocol"]) b["cipher"] = find_key(CIPHERS, b["cipher"]) b["compressor"] = find_key(COMPRESSORS, b["compressor"]) end end -- Check for overflow beyond length. if j > len then stdnse.print_debug(2, "SSL: Parsing error, body %d bytes larger than header declares.", j - len) j = len end -- Consume any unparsed bytes in record body. if j < len then stdnse.print_debug(2, "SSL: Parsing error, ignoring %d unused bytes in body.", len - j) j = len end return j, h end local function record_write(type, protocol, b) local h h = "" -- Set the header as a handshake. h = h .. bin.pack("C", TLS_CONTENTTYPE_REGISTRY[type]) -- Set the protocol. h = h .. bin.pack(">S", PROTOCOLS[protocol]) -- Set the length of the header body. h = h .. bin.pack(">S", #b) return h .. b end local function client_hello(t) local b, cipher, ciphers, compressor, compressors, h, len ---------- -- Body -- ---------- b = "" -- Set the random data. b = b .. bin.pack(">I", os.time()) -- Set the random data. b = b .. string.rep("nmap", 7) -- Set the session ID. b = b .. bin.pack("C", 0) -- Cipher suites. ciphers = "" if t["ciphers"] ~= nil then for _, cipher in pairs(t["ciphers"]) do ciphers = ciphers .. bin.pack(">S", CIPHERS[cipher]) end else for _, cipher in pairs(CIPHERS) do ciphers = ciphers .. bin.pack(">S", cipher) end end b = b .. bin.pack(">S", #ciphers) b = b .. ciphers -- Compression methods. compressors = "" if t["compressors"] ~= nil then for _, compressor in pairs(t["compressors"]) do compressors = compressors .. bin.pack("C", COMPRESSORS[compressor]) end else ciphers = b .. bin.pack("C", #COMPRESSORS) for _, compressor in pairs(COMPRESSORS) do compressors = compressors .. bin.pack("C", compressor) end end b = b .. bin.pack("C", #compressors) b = b .. compressors -- Extensions. b = b .. bin.pack(">S", 0) ------------ -- Header -- ------------ h = "" -- Set type to ClientHello. h = h .. bin.pack("C", TLS_HANDSHAKETYPE_REGISTRY["client_hello"]) -- Set the length of the body. len = bin.pack(">I", #b) h = h .. bin.pack("CCC", len:byte(2), len:byte(3), len:byte(4)) -- Set the protocol. h = h .. bin.pack(">S", PROTOCOLS[t["protocol"]]) return record_write("handshake", t["protocol"], h .. b) end local function try_params(host, port, t) local buffer, err, i, kind, length, record, req, resp, sock, status -- Create socket. sock = nmap.new_socket() sock:set_timeout(5000) status, err = sock:connect(host, port, "tcp") if not status then stdnse.print_debug(1, "Can't connect: %s", err) sock:close() return nil end -- Send request. req = client_hello(t) status, err = sock:send(req) if not status then stdnse.print_debug(1, "Can't send: %s", err) sock:close() return nil end -- Read response. i = 0 buffer = "" while true do status, chunk = sock:receive() if not status then sock:close() return nil end buffer = buffer .. chunk -- Parse response. i, record = record_read(buffer, i) if record ~= nil then sock:close() return record end end end local function try_protocol(host, port, protocol) local ciphers, compressors, result local function find_ciphers() local k, name, record, results, t, v results = {} -- Create list of ciphers. t = { ["ciphers"] = {}, ["protocol"] = protocol } for name, id in pairs(CIPHERS) do table.insert(t["ciphers"], name) end -- Create connections while removing previously accepted ciphers. while true do -- Try connecting with remaining ciphers. record = try_params(host, port, t) if record == nil then break end if record["protocol"] ~= protocol then stdnse.print_debug(1, "Protocol not supported, server using %s.", record["protocol"]) break end if record["type"] == "alert" and record["body"]["description"] == "handshake_failure" then stdnse.print_debug(2, "No ciphers chosen.") break end if record["type"] ~= "handshake" or record["body"]["type"] ~= "server_hello" then stdnse.print_debug(2, "Unexpected record received.") break end -- Add cipher to the list of accepted ciphers. name = record["body"]["cipher"] table.insert(results, name) stdnse.print_debug(2, "Cipher %s chosen.", name) -- Remove cipher from list for next attempt. for k, v in pairs(t["ciphers"]) do if v == name then table.remove(t["ciphers"], k) break end end end return results end local function find_compressors() local compressors, k, name, record, results, t, v results = {} -- Create list of compressors. t = { ["compressors"] = {}, ["protocol"] = protocol } for name, id in pairs(COMPRESSORS) do table.insert(t["compressors"], name) end -- Create connections while removing previously accepted compressors. while true do -- Try connecting with remaining ciphers. record = try_params(host, port, t) if record == nil then break end if record["protocol"] ~= protocol then stdnse.print_debug(1, "Protocol not supported, server using %s.", record["protocol"]) break end if record["type"] == "alert" and record["body"]["description"] == "handshake_failure" then stdnse.print_debug(2, "No compressors chosen.") break end if record["type"] ~= "handshake" or record["body"]["type"] ~= "server_hello" then stdnse.print_debug(2, "Unexpected record received.") break end -- Add compressor to the list of accepted compressors. name = record["body"]["compressor"] table.insert(results, name) stdnse.print_debug(2, "Compressor %s chosen.", name) -- Remove compressor from list for next attempt. for k, v in pairs(t["compressors"]) do if v == name then table.remove(t["compressors"], k) break end end end return results end results = {} -- Find all valid ciphers. ciphers = find_ciphers() if #ciphers == 0 then return {} end -- Find all valid compression methods. compressors = find_compressors() -- Format the cipher table. if nmap.registry.args["ssl-enum-ciphers.sort"] == "name" then table.sort(ciphers) end ciphers["name"] = "Ciphers (" .. #ciphers .. ")" table.insert(results, ciphers) -- Format the compressor table. if nmap.registry.args["ssl-enum-ciphers.sort"] == "name" then table.sort(compressors) end compressors["name"] = "Compressors (" .. #compressors .. ")" table.insert(results, compressors) return results end portrule = function(host, port) local is_ssl = shortport.port_or_service(SSL_PORTS, SSL_SERVICES) -- This script only handles SSL/TLS over TCP. if port.protocol ~= "tcp" then return false end if port.version.service_tunnel == "ssl" then return true end if is_ssl(host, port) then return true end return false end action = function(host, port) local result, results results = {} for name, _ in pairs(PROTOCOLS) do stdnse.print_debug(1, "Trying protocol %s.", name) result = try_protocol(host.ip, port.number, name) if #result > 0 then result["name"] = name table.insert(results, result) end end -- Sort protocol results by name. table.sort(results, function(a, b) return a["name"] < b["name"] end) return stdnse.format_output(true, results) end