diff --git a/nselib/tls.lua b/nselib/tls.lua index 1120ad347..d3b35bb5b 100644 --- a/nselib/tls.lua +++ b/nselib/tls.lua @@ -68,6 +68,7 @@ TLS_ALERT_REGISTRY = { ["protocol_version"] = 70, ["insufficient_security"] = 71, ["internal_error"] = 80, + ["inappropriate_fallback"] = 86, ["user_canceled"] = 90, ["no_renegotiation"] = 100, ["unsupported_extension"] = 110, @@ -398,7 +399,6 @@ CIPHERS = { ["TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256"] = 0x00BD, ["TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256"] = 0x00BE, ["TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256"] = 0x00BF, -["TLS_EMPTY_RENEGOTIATION_INFO_SCSV"] = 0x00FF, ["TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256"] = 0x00C0, ["TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256"] = 0x00C1, ["TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256"] = 0x00C2, @@ -583,6 +583,11 @@ CIPHERS = { ["SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA"] = 0xFEFF, } +SCSVS = { +["TLS_EMPTY_RENEGOTIATION_INFO_SCSV"] = 0x00FF, -- rfc5746 +["TLS_FALLBACK_SCSV"] = 0x5600, -- draft-ietf-tls-downgrade-scsv-00 +} + local function find_key(t, value) local k, v @@ -768,7 +773,14 @@ function client_hello(t) if t["ciphers"] ~= nil then -- Add specified ciphers. for _, cipher in pairs(t["ciphers"]) do - table.insert(ciphers, bin.pack(">S", CIPHERS[cipher])) + if type(cipher) == "string" then + cipher = CIPHERS[cipher] or SCSVS[cipher] + end + if type(cipher) == "number" and cipher > 0 and cipher <= 0xffff then + table.insert(ciphers, bin.pack(">S", cipher)) + else + stdnse.debug1("Unknown cipher in client_hello: %s", cipher) + end end else -- Use NULL cipher diff --git a/scripts/ssl-poodle.nse b/scripts/ssl-poodle.nse index 30e4b5a2c..93b5a60ef 100644 --- a/scripts/ssl-poodle.nse +++ b/scripts/ssl-poodle.nse @@ -226,7 +226,7 @@ local function find_ciphers_group(host, port, protocol, group) ctx_log(1, protocol, "%d ciphers and/or protocol rejected. (No handshake)", #group) end break - elseif record["protocol"] ~= protocol then + elseif record["protocol"] ~= protocol or record["body"][1]["protocol"] and record.body[1].protocol ~= protocol then ctx_log(1, protocol, "Protocol rejected.") protocol_worked = nil break @@ -299,6 +299,29 @@ local function find_ciphers(host, port, protocol) return results end +-- check if draft-ietf-tls-downgrade-scsv-00 is implemented as a mitigation +local function check_fallback_scsv(host, port, protocol, ciphers) + local results = {} + local t = { + ["protocol"] = protocol, + ["extensions"] = tcopy(base_extensions), + } + if host.targetname then + t["extensions"]["server_name"] = tls.EXTENSION_HELPERS["server_name"](host.targetname) + end + + t["ciphers"] = tcopy(ciphers) + t.ciphers[#t.ciphers+1] = "TLS_FALLBACK_SCSV" + + local record = try_params(host, port, t) + + if record["type"] == "alert" and record["body"][1]["description"] == "inappropriate_fallback" then + ctx_log(2, protocol, "TLS_FALLBACK_SCSV rejected properly.") + return true + end + return false +end + portrule = function (host, port) return shortport.ssl(host, port) or sslcert.getPrepareTLSWithoutReconnect(port) end @@ -334,16 +357,16 @@ action = function(host, port) local ciphers = find_ciphers(host, port, 'SSLv3') if ciphers == nil then vuln_table.check_results = { "SSLv3 not supported" } - return report:make_output(vuln_table) - end - - if #ciphers == 0 then + elseif #ciphers == 0 then vuln_table.check_results = { "No CBC ciphersuites found" } - return report:make_output(vuln_table) + else + vuln_table.check_results = ciphers + if check_fallback_scsv(host, port, 'SSLv3', ciphers) then + table.insert(vuln_table.check_results, "TLS_FALLBACK_SCSV properly implemented") + vuln_table.state = vulns.STATE.LIKELY_VULN + else + vuln_table.state = vulns.STATE.VULN + end end - - -- else - vuln_table.check_results = ciphers - vuln_table.state = vulns.STATE.VULN return report:make_output(vuln_table) end