1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-09 14:11:29 +00:00

Modify ssl-enum-ciphers for speed and thoroughness

Send large groups of ciphers and eliminate chosen ones until the server
gives up. This results in far fewer exchanges than trying every cipher
individually.

Also fixed a bug introduced in r26521 where failing to send NULL
compressor results in a rejected handshake, and updated the list of
ciphers from 213 to 359.

http://seclists.org/nmap-dev/2012/q3/156
This commit is contained in:
dmiller
2012-07-13 22:40:00 +00:00
parent a2f308a8f8
commit 4463296bf7

View File

@@ -201,7 +201,7 @@ CIPHERS = {
["TLS_DH_anon_WITH_3DES_EDE_CBC_SHA"] = 0x001B, ["TLS_DH_anon_WITH_3DES_EDE_CBC_SHA"] = 0x001B,
["SSL_FORTEZZA_KEA_WITH_NULL_SHA"] = 0x001C, ["SSL_FORTEZZA_KEA_WITH_NULL_SHA"] = 0x001C,
["SSL_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA"] = 0x001D, ["SSL_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA"] = 0x001D,
["TLS_KRB5_WITH_DES_CBC_SHA"] = 0x001E, ["TLS_KRB5_WITH_DES_CBC_SHA or SSL_FORTEZZA_KEA_WITH_RC4_128_SHA"] = 0x001E, --TLS vs SSLv3
["TLS_KRB5_WITH_3DES_EDE_CBC_SHA"] = 0x001F, ["TLS_KRB5_WITH_3DES_EDE_CBC_SHA"] = 0x001F,
["TLS_KRB5_WITH_RC4_128_SHA"] = 0x0020, ["TLS_KRB5_WITH_RC4_128_SHA"] = 0x0020,
["TLS_KRB5_WITH_IDEA_CBC_SHA"] = 0x0021, ["TLS_KRB5_WITH_IDEA_CBC_SHA"] = 0x0021,
@@ -242,6 +242,28 @@ CIPHERS = {
["TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA"] = 0x0044, ["TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA"] = 0x0044,
["TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA"] = 0x0045, ["TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA"] = 0x0045,
["TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA"] = 0x0046, ["TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA"] = 0x0046,
["TLS_ECDH_ECDSA_WITH_NULL_SHA-draft"] = 0x0047, --draft-ietf-tls-ecc-00
["TLS_ECDH_ECDSA_WITH_RC4_128_SHA-draft"] = 0x0048, --draft-ietf-tls-ecc-00
["TLS_ECDH_ECDSA_WITH_DES_CBC_SHA-draft"] = 0x0049, --draft-ietf-tls-ecc-00
["TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA-draft"] = 0x004A, --draft-ietf-tls-ecc-00
["TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA-draft"] = 0x004B, --draft-ietf-tls-ecc-00
["TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA-draft"] = 0x004C, --draft-ietf-tls-ecc-00
["TLS_ECDH_ECNRA_WITH_DES_CBC_SHA-draft"] = 0x004D, --draft-ietf-tls-ecc-00
["TLS_ECDH_ECNRA_WITH_3DES_EDE_CBC_SHA-draft"] = 0x004E, --draft-ietf-tls-ecc-00
["TLS_ECMQV_ECDSA_NULL_SHA-draft"] = 0x004F, --draft-ietf-tls-ecc-00
["TLS_ECMQV_ECDSA_WITH_RC4_128_SHA-draft"] = 0x0050, --draft-ietf-tls-ecc-00
["TLS_ECMQV_ECDSA_WITH_DES_CBC_SHA-draft"] = 0x0051, --draft-ietf-tls-ecc-00
["TLS_ECMQV_ECDSA_WITH_3DES_EDE_CBC_SHA-draft"] = 0x0052, --draft-ietf-tls-ecc-00
["TLS_ECMQV_ECNRA_NULL_SHA-draft"] = 0x0053, --draft-ietf-tls-ecc-00
["TLS_ECMQV_ECNRA_WITH_RC4_128_SHA-draft"] = 0x0054, --draft-ietf-tls-ecc-00
["TLS_ECMQV_ECNRA_WITH_DES_CBC_SHA-draft"] = 0x0055, --draft-ietf-tls-ecc-00
["TLS_ECMQV_ECNRA_WITH_3DES_EDE_CBC_SHA-draft"] = 0x0056, --draft-ietf-tls-ecc-00
["TLS_ECDH_anon_NULL_WITH_SHA-draft"] = 0x0057, --draft-ietf-tls-ecc-00
["TLS_ECDH_anon_WITH_RC4_128_SHA-draft"] = 0x0058, --draft-ietf-tls-ecc-00
["TLS_ECDH_anon_WITH_DES_CBC_SHA-draft"] = 0x0059, --draft-ietf-tls-ecc-00
["TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA-draft"] = 0x005A, --draft-ietf-tls-ecc-00
["TLS_ECDH_anon_EXPORT_WITH_DES40_CBC_SHA-draft"] = 0x005B, --draft-ietf-tls-ecc-00
["TLS_ECDH_anon_EXPORT_WITH_RC4_40_SHA-draft"] = 0x005C, --draft-ietf-tls-ecc-00
["TLS_RSA_EXPORT1024_WITH_RC4_56_MD5"] = 0x0060, ["TLS_RSA_EXPORT1024_WITH_RC4_56_MD5"] = 0x0060,
["TLS_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5"] = 0x0061, ["TLS_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5"] = 0x0061,
["TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA"] = 0x0062, ["TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA"] = 0x0062,
@@ -256,6 +278,19 @@ CIPHERS = {
["TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"] = 0x006B, ["TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"] = 0x006B,
["TLS_DH_anon_WITH_AES_128_CBC_SHA256"] = 0x006C, ["TLS_DH_anon_WITH_AES_128_CBC_SHA256"] = 0x006C,
["TLS_DH_anon_WITH_AES_256_CBC_SHA256"] = 0x006D, ["TLS_DH_anon_WITH_AES_256_CBC_SHA256"] = 0x006D,
["TLS_DHE_DSS_WITH_3DES_EDE_CBC_RMD"] = 0x0072, --draft-ietf-tls-openpgp-keys-05
["TLS_DHE_DSS_WITH_AES_128_CBC_RMD"] = 0x0073, --draft-ietf-tls-openpgp-keys-05
["TLS_DHE_DSS_WITH_AES_256_CBC_RMD"] = 0x0074, --draft-ietf-tls-openpgp-keys-05
["TLS_DHE_RSA_WITH_3DES_EDE_CBC_RMD"] = 0x0077, --draft-ietf-tls-openpgp-keys-05
["TLS_DHE_RSA_WITH_AES_128_CBC_RMD"] = 0x0078, --draft-ietf-tls-openpgp-keys-05
["TLS_DHE_RSA_WITH_AES_256_CBC_RMD"] = 0x0079, --draft-ietf-tls-openpgp-keys-05
["TLS_RSA_WITH_3DES_EDE_CBC_RMD"] = 0x007C, --draft-ietf-tls-openpgp-keys-05
["TLS_RSA_WITH_AES_128_CBC_RMD"] = 0x007D, --draft-ietf-tls-openpgp-keys-05
["TLS_RSA_WITH_AES_256_CBC_RMD"] = 0x007E, --draft-ietf-tls-openpgp-keys-05
["TLS_GOSTR341094_WITH_28147_CNT_IMIT"] = 0x0080, --draft-chudov-cryptopro-cptls-04
["TLS_GOSTR341001_WITH_28147_CNT_IMIT"] = 0x0081, --draft-chudov-cryptopro-cptls-04
["TLS_GOSTR341094_WITH_NULL_GOSTR3411"] = 0x0082, --draft-chudov-cryptopro-cptls-04
["TLS_GOSTR341001_WITH_NULL_GOSTR3411"] = 0x0083, --draft-chudov-cryptopro-cptls-04
["TLS_RSA_WITH_CAMELLIA_256_CBC_SHA"] = 0x0084, ["TLS_RSA_WITH_CAMELLIA_256_CBC_SHA"] = 0x0084,
["TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA"] = 0x0085, ["TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA"] = 0x0085,
["TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA"] = 0x0086, ["TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA"] = 0x0086,
@@ -322,7 +357,6 @@ CIPHERS = {
["TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256"] = 0x00C3, ["TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256"] = 0x00C3,
["TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256"] = 0x00C4, ["TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256"] = 0x00C4,
["TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256"] = 0x00C5, ["TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256"] = 0x00C5,
["TLS_RENEGO_PROTECTION_REQUEST"] = 0x00FF,
["TLS_ECDH_ECDSA_WITH_NULL_SHA"] = 0xC001, ["TLS_ECDH_ECDSA_WITH_NULL_SHA"] = 0xC001,
["TLS_ECDH_ECDSA_WITH_RC4_128_SHA"] = 0xC002, ["TLS_ECDH_ECDSA_WITH_RC4_128_SHA"] = 0xC002,
["TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA"] = 0xC003, ["TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA"] = 0xC003,
@@ -382,8 +416,120 @@ CIPHERS = {
["TLS_ECDHE_PSK_WITH_NULL_SHA"] = 0xC039, ["TLS_ECDHE_PSK_WITH_NULL_SHA"] = 0xC039,
["TLS_ECDHE_PSK_WITH_NULL_SHA256"] = 0xC03A, ["TLS_ECDHE_PSK_WITH_NULL_SHA256"] = 0xC03A,
["TLS_ECDHE_PSK_WITH_NULL_SHA384"] = 0xC03B, ["TLS_ECDHE_PSK_WITH_NULL_SHA384"] = 0xC03B,
["TLS_RSA_WITH_ARIA_128_CBC_SHA256"] = 0xC03C,
["TLS_RSA_WITH_ARIA_256_CBC_SHA384"] = 0xC03D,
["TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256"] = 0xC03E,
["TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384"] = 0xC03F,
["TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256"] = 0xC040,
["TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384"] = 0xC041,
["TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256"] = 0xC042,
["TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384"] = 0xC043,
["TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256"] = 0xC044,
["TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384"] = 0xC045,
["TLS_DH_anon_WITH_ARIA_128_CBC_SHA256"] = 0xC046,
["TLS_DH_anon_WITH_ARIA_256_CBC_SHA384"] = 0xC047,
["TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256"] = 0xC048,
["TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384"] = 0xC049,
["TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256"] = 0xC04A,
["TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384"] = 0xC04B,
["TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256"] = 0xC04C,
["TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384"] = 0xC04D,
["TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256"] = 0xC04E,
["TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384"] = 0xC04F,
["TLS_RSA_WITH_ARIA_128_GCM_SHA256"] = 0xC050,
["TLS_RSA_WITH_ARIA_256_GCM_SHA384"] = 0xC051,
["TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256"] = 0xC052,
["TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384"] = 0xC053,
["TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256"] = 0xC054,
["TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384"] = 0xC055,
["TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256"] = 0xC056,
["TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384"] = 0xC057,
["TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256"] = 0xC058,
["TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384"] = 0xC059,
["TLS_DH_anon_WITH_ARIA_128_GCM_SHA256"] = 0xC05A,
["TLS_DH_anon_WITH_ARIA_256_GCM_SHA384"] = 0xC05B,
["TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256"] = 0xC05C,
["TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384"] = 0xC05D,
["TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256"] = 0xC05E,
["TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384"] = 0xC05F,
["TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256"] = 0xC060,
["TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384"] = 0xC061,
["TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256"] = 0xC062,
["TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384"] = 0xC063,
["TLS_PSK_WITH_ARIA_128_CBC_SHA256"] = 0xC064,
["TLS_PSK_WITH_ARIA_256_CBC_SHA384"] = 0xC065,
["TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256"] = 0xC066,
["TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384"] = 0xC067,
["TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256"] = 0xC068,
["TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384"] = 0xC069,
["TLS_PSK_WITH_ARIA_128_GCM_SHA256"] = 0xC06A,
["TLS_PSK_WITH_ARIA_256_GCM_SHA384"] = 0xC06B,
["TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256"] = 0xC06C,
["TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384"] = 0xC06D,
["TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256"] = 0xC06E,
["TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384"] = 0xC06F,
["TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256"] = 0xC070,
["TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384"] = 0xC071,
["TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256"] = 0xC072,
["TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384"] = 0xC073,
["TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256"] = 0xC074,
["TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384"] = 0xC075,
["TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256"] = 0xC076,
["TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384"] = 0xC077,
["TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256"] = 0xC078,
["TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384"] = 0xC079,
["TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256"] = 0xC07A,
["TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384"] = 0xC07B,
["TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256"] = 0xC07C,
["TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384"] = 0xC07D,
["TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256"] = 0xC07E,
["TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384"] = 0xC07F,
["TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256"] = 0xC080,
["TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384"] = 0xC081,
["TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256"] = 0xC082,
["TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384"] = 0xC083,
["TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256"] = 0xC084,
["TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384"] = 0xC085,
["TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256"] = 0xC086,
["TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384"] = 0xC087,
["TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256"] = 0xC088,
["TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384"] = 0xC089,
["TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256"] = 0xC08A,
["TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384"] = 0xC08B,
["TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256"] = 0xC08C,
["TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384"] = 0xC08D,
["TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256"] = 0xC08E,
["TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384"] = 0xC08F,
["TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256"] = 0xC090,
["TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384"] = 0xC091,
["TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256"] = 0xC092,
["TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384"] = 0xC093,
["TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256"] = 0xC094,
["TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384"] = 0xC095,
["TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256"] = 0xC096,
["TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384"] = 0xC097,
["TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256"] = 0xC098,
["TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384"] = 0xC099,
["TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256"] = 0xC09A,
["TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384"] = 0xC09B,
["TLS_RSA_WITH_AES_128_CCM"] = 0xC09C,
["TLS_RSA_WITH_AES_256_CCM"] = 0xC09D,
["TLS_DHE_RSA_WITH_AES_128_CCM"] = 0xC09E,
["TLS_DHE_RSA_WITH_AES_256_CCM"] = 0xC09F,
["TLS_RSA_WITH_AES_128_CCM_8"] = 0xC0A0,
["TLS_RSA_WITH_AES_256_CCM_8"] = 0xC0A1,
["TLS_DHE_RSA_WITH_AES_128_CCM_8"] = 0xC0A2,
["TLS_DHE_RSA_WITH_AES_256_CCM_8"] = 0xC0A3,
["TLS_PSK_WITH_AES_128_CCM"] = 0xC0A4,
["TLS_PSK_WITH_AES_256_CCM"] = 0xC0A5,
["TLS_DHE_PSK_WITH_AES_128_CCM"] = 0xC0A6,
["TLS_DHE_PSK_WITH_AES_256_CCM"] = 0xC0A7,
["TLS_PSK_WITH_AES_128_CCM_8"] = 0xC0A8,
["TLS_PSK_WITH_AES_256_CCM_8"] = 0xC0A9,
["TLS_PSK_DHE_WITH_AES_128_CCM_8"] = 0xC0AA,
["TLS_PSK_DHE_WITH_AES_256_CCM_8"] = 0xC0AB,
["SSL_RSA_FIPS_WITH_DES_CBC_SHA"] = 0xFEFE, ["SSL_RSA_FIPS_WITH_DES_CBC_SHA"] = 0xFEFE,
["SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA"] = 0xFEFF ["SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA"] = 0xFEFF,
} }
cipherstrength = { cipherstrength = {
@@ -542,8 +688,11 @@ local function client_hello(t)
if t["compressors"] ~= nil then if t["compressors"] ~= nil then
-- Add specified compressors. -- Add specified compressors.
for _, compressor in pairs(t["compressors"]) do for _, compressor in pairs(t["compressors"]) do
if compressor ~= "NULL" then
compressors = compressors .. bin.pack("C", COMPRESSORS[compressor]) compressors = compressors .. bin.pack("C", COMPRESSORS[compressor])
end end
end
compressors = compressors .. bin.pack("C", 0) -- Always include NULL as last choice
else else
-- Add all known compressors. -- Add all known compressors.
for _, compressor in pairs(COMPRESSORS) do for _, compressor in pairs(COMPRESSORS) do
@@ -569,9 +718,8 @@ local function client_hello(t)
return record_write("handshake", t["protocol"], h .. b) return record_write("handshake", t["protocol"], h .. b)
end end
local function try_params(host, port, t, name, records) local function try_params(host, port, t)
local buffer, err, i, record, req, resp, sock, status local buffer, err, i, record, req, resp, sock, status
local condvar = nmap.condvar(records)
-- Create socket. -- Create socket.
sock = nmap.new_socket() sock = nmap.new_socket()
@@ -580,7 +728,6 @@ local function try_params(host, port, t, name, records)
if not status then if not status then
stdnse.print_debug(1, "Can't connect: %s", err) stdnse.print_debug(1, "Can't connect: %s", err)
sock:close() sock:close()
condvar "signal"
return nil return nil
end end
@@ -590,7 +737,6 @@ local function try_params(host, port, t, name, records)
if not status then if not status then
stdnse.print_debug(1, "Can't send: %s", err) stdnse.print_debug(1, "Can't send: %s", err)
sock:close() sock:close()
condvar "signal"
return nil return nil
end end
@@ -602,8 +748,7 @@ local function try_params(host, port, t, name, records)
status, resp = sock:receive() status, resp = sock:receive()
if not status then if not status then
sock:close() sock:close()
condvar "signal" return nil
return record
end end
buffer = buffer .. resp buffer = buffer .. resp
@@ -612,70 +757,167 @@ local function try_params(host, port, t, name, records)
i, record = record_read(buffer, i) i, record = record_read(buffer, i)
if record ~= nil then if record ~= nil then
sock:close() sock:close()
record.name = name return record
table.insert(records, record)
condvar "signal"
return
end end
end end
end end
local function try_protocol(host, port, protocol) local function keys(t)
local ciphers, compressors, results local ret = {}
for k, _ in pairs(t) do
ret[#ret+1] = k
end
return ret
end
local function find_ciphers() local function keys_in_chunks(t)
local ret = {{}}
local c = 0
local b = 1
for k, _ in pairs(t) do
c = c+1
ret[b][c] = k
if c > 64 then
c = 0
b = b + 1
ret[b] = {}
end
end
return ret
end
local function remove(t, e)
for i, v in ipairs(t) do
if v == e then
table.remove(t, i)
return i
end
end
return nil
end
local function find_ciphers(host, port, protocol)
local name, protocol_worked, record, results, t,cipherstr local name, protocol_worked, record, results, t,cipherstr
local records, threads = {}, {} local ciphers = keys_in_chunks(CIPHERS)
local condvar = nmap.condvar(records)
results = {} results = {}
-- Try every cipher. -- Try every cipher.
protocol_worked = false protocol_worked = false
for name, _ in pairs(CIPHERS) do for _, group in ipairs(ciphers) do
while (next(group)) do
-- Create structure. -- Create structure.
t = { t = {
["ciphers"] = {name}, ["ciphers"] = group,
["protocol"] = protocol ["protocol"] = protocol
} }
-- Try connecting with cipher. record = try_params(host, port, t)
local co = stdnse.new_thread(try_params, host, port, t, name, records)
threads[co] = true
end
repeat
for thread in pairs(threads) do
if coroutine.status(thread) == "dead" then threads[thread] = nil end
end
if ( next(threads) ) then
condvar "wait"
end
until next(threads) == nil
for _, record in ipairs(records) do
local name = record.name
if record == nil then if record == nil then
if protocol_worked then if protocol_worked then
stdnse.print_debug(2, "Cipher %s rejected.", name) stdnse.print_debug(2, "%d ciphers rejected. (No handshake)", #group)
else else
stdnse.print_debug(2, "Cipher %s and/or protocol %s rejected.", name, protocol) stdnse.print_debug(1, "%d ciphers and/or protocol %s rejected. (No handshake)", #group, protocol)
end end
break
elseif record["protocol"] ~= protocol then
stdnse.print_debug(1, "Protocol %s rejected.", protocol)
protocol_worked = nil
break
elseif record["type"] == "alert" and record["body"]["description"] == "handshake_failure" then
protocol_worked = true
stdnse.print_debug(2, "%d ciphers rejected.", #group)
break
elseif record["type"] ~= "handshake" or record["body"]["type"] ~= "server_hello" then
stdnse.print_debug(2, "Unexpected record received.")
break
else
protocol_worked = true
name = record["body"]["cipher"]
stdnse.print_debug(2, "Cipher %s chosen.", name)
remove(group, name)
-- Add cipher to the list of accepted ciphers.
table.insert(results, name)
end
end
if protocol_worked == nil then break end
end
return results
end
local function find_compressors(host, port, protocol, good_cipher)
local name, protocol_worked, record, results, t
local compressors = keys(COMPRESSORS)
results = {}
-- Try every compressor.
protocol_worked = false
while (next(compressors)) do
-- Create structure.
t = {
["compressors"] = compressors,
["ciphers"] = {good_cipher},
["protocol"] = protocol
}
-- Try connecting with compressor.
record = try_params(host, port, t)
if record == nil then
if protocol_worked then
stdnse.print_debug(2, "%d compressors rejected. (No handshake)", #compressors)
else
stdnse.print_debug(1, "%d compressors and/or protocol %s rejected. (No handshake)", #compressors, protocol)
end
break
elseif record["protocol"] ~= protocol then elseif record["protocol"] ~= protocol then
stdnse.print_debug(1, "Protocol %s rejected.", protocol) stdnse.print_debug(1, "Protocol %s rejected.", protocol)
break break
elseif record["type"] == "alert" and record["body"]["description"] == "handshake_failure" then elseif record["type"] == "alert" and record["body"]["description"] == "handshake_failure" then
protocol_worked = true protocol_worked = true
stdnse.print_debug(2, "Cipher %s rejected.", name) stdnse.print_debug(2, "%d compressors rejected.", #compressors)
break
elseif record["type"] ~= "handshake" or record["body"]["type"] ~= "server_hello" then elseif record["type"] ~= "handshake" or record["body"]["type"] ~= "server_hello" then
stdnse.print_debug(2, "Unexpected record received.") stdnse.print_debug(2, "Unexpected record received.")
break
else else
protocol_worked = true protocol_worked = true
stdnse.print_debug(2, "Cipher %s chosen.", name) name = record["body"]["compressor"]
stdnse.print_debug(2, "Compressor %s chosen.", name)
remove(compressors, name)
-- Add cipher to the list of accepted ciphers. -- Add compressor to the list of accepted compressors.
name = record["body"]["cipher"] table.insert(results, name)
if name == "NULL" then
break -- NULL is always last choice, and must be included
end
end
end
return results
end
local function try_protocol(host, port, protocol, upresults)
local ciphers, compressors, results
local condvar = nmap.condvar(upresults)
results = {}
-- Find all valid ciphers.
ciphers = find_ciphers(host, port, protocol)
if #ciphers == 0 then
condvar "signal"
return nil
end
-- Find all valid compression methods.
compressors = find_compressors(host, port, protocol, ciphers[1])
-- Add rankings to ciphers
for i, name in ipairs(ciphers) do
if rankedciphersfilename and rankedciphers[name] then if rankedciphersfilename and rankedciphers[name] then
cipherstr=rankedciphers[name] cipherstr=rankedciphers[name]
else else
@@ -686,85 +928,8 @@ local function try_protocol(host, port, protocol)
stdnse.print_debug(2, "Downgrading min cipher strength to %d.",cipherstrength[cipherstr]) stdnse.print_debug(2, "Downgrading min cipher strength to %d.",cipherstrength[cipherstr])
mincipherstrength=cipherstrength[cipherstr] mincipherstrength=cipherstrength[cipherstr]
end end
name=name.." - "..cipherstr ciphers[i]=name.." - "..cipherstr
table.insert(results, name)
end end
end
return results
end
local function find_compressors()
local name, protocol_worked, record, results, t
local records, threads = {}, {}
local condvar = nmap.condvar(records)
results = {}
-- Try every compressor.
protocol_worked = false
for name, _ in pairs(COMPRESSORS) do
-- Create structure.
t = {
["compressors"] = {name},
["protocol"] = protocol
}
-- Try connecting with compressor.
local co = stdnse.new_thread(try_params, host, port, t, name, records)
threads[co] = true
end
repeat
for thread in pairs(threads) do
if coroutine.status(thread) == "dead" then threads[thread] = nil end
end
if ( next(threads) ) then
condvar "wait"
end
until next(threads) == nil
for _, record in ipairs(records) do
local name = record.name
if record == nil then
if protocol_worked then
stdnse.print_debug(2, "Compressor %s rejected.", name)
else
stdnse.print_debug(2, "Compressor %s and/or protocol %s rejected.", name, protocol)
end
elseif record["protocol"] ~= protocol then
stdnse.print_debug(1, "Protocol %s rejected.", protocol)
break
elseif record["type"] == "alert" and record["body"]["description"] == "handshake_failure" then
protocol_worked = true
stdnse.print_debug(2, "Compressor %s rejected.", name)
elseif record["type"] ~= "handshake" or record["body"]["type"] ~= "server_hello" then
stdnse.print_debug(2, "Unexpected record received.")
elseif record["body"]["compressor"] ~= name then
protocol_worked = true
stdnse.print_debug(2, "Compressor %s rejected.", name)
else
protocol_worked = true
stdnse.print_debug(2, "Compressor %s chosen.", name)
-- Add compressor to the list of accepted compressors.
table.insert(results, name)
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. -- Format the cipher table.
table.sort(ciphers) table.sort(ciphers)
@@ -776,7 +941,12 @@ local function try_protocol(host, port, protocol)
compressors["name"] = "Compressors (" .. #compressors .. ")" compressors["name"] = "Compressors (" .. #compressors .. ")"
table.insert(results, compressors) table.insert(results, compressors)
return results if #results > 0 then
results["name"] = protocol
table.insert(upresults, results)
end
condvar "signal"
return nil
end end
-- Shamelessly stolen from nselib/unpwdb.lua and changed a bit. (Gabriel Lawrence) -- Shamelessly stolen from nselib/unpwdb.lua and changed a bit. (Gabriel Lawrence)
@@ -830,14 +1000,23 @@ action = function(host, port)
results = {} results = {}
local condvar = nmap.condvar(results)
local threads = {}
for name, _ in pairs(PROTOCOLS) do for name, _ in pairs(PROTOCOLS) do
stdnse.print_debug(1, "Trying protocol %s.", name) stdnse.print_debug(1, "Trying protocol %s.", name)
result = try_protocol(host.ip, port.number, name) local co = stdnse.new_thread(try_protocol, host.ip, port.number, name, results)
if #result > 0 then threads[co] = true
result["name"] = name
table.insert(results, result)
end end
repeat
for thread in pairs(threads) do
if coroutine.status(thread) == "dead" then threads[thread] = nil end
end end
if ( next(threads) ) then
condvar "wait"
end
until next(threads) == nil
-- Sort protocol results by name. -- Sort protocol results by name.
table.sort(results, function(a, b) return a["name"] < b["name"] end) table.sort(results, function(a, b) return a["name"] < b["name"] end)