1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-07 05:01:29 +00:00

Add tls.servername script-arg. Closes #540

This commit is contained in:
dmiller
2016-12-05 17:44:32 +00:00
parent 07c840d9ec
commit e4717fa068
8 changed files with 58 additions and 56 deletions

View File

@@ -1,5 +1,9 @@
# Nmap Changelog ($Id$); -*-text-*- # Nmap Changelog ($Id$); -*-text-*-
o [NSE][GH#540] Add tls.servername script-arg for forcing a name to be used for
TLS Server Name Indication extension. The argument overrides the default use
of the host's targetname. [Bertrand Bonnefoy-Claudet]
o [NSE] Script fingerprint-strings will print the ASCII strings it finds in the o [NSE] Script fingerprint-strings will print the ASCII strings it finds in the
service fingerprints that Nmap shows for unidentified services. [Daniel Miller] service fingerprints that Nmap shows for unidentified services. [Daniel Miller]

View File

@@ -1502,4 +1502,20 @@ function record_buffer(sock, buffer, i)
return true, buffer return true, buffer
end end
-- Get a server_name for use with the TLS Server Name Indication extension.
--
-- This returns the value of the script argument "tls.servername" if given. Otherwise, it
-- returns the target name of the host parameter.
--
-- @param host Host table as received by the action function
-- @return String of the selected host name
function servername(host)
local script_arg = stdnse.get_script_args("tls.servername")
if script_arg then
return script_arg
elseif type(host) == "table" then
return host.targetname
end
end
return _ENV; return _ENV;

View File

@@ -3,6 +3,7 @@ local shortport = require "shortport"
local sslcert = require "sslcert" local sslcert = require "sslcert"
local stdnse = require "stdnse" local stdnse = require "stdnse"
local string = require "string" local string = require "string"
local tls = require "tls"
local unicode = require "unicode" local unicode = require "unicode"
description = [[ description = [[
@@ -264,6 +265,7 @@ local function output_str(cert)
end end
action = function(host, port) action = function(host, port)
host.targetname = tls.servername(host)
local status, cert = sslcert.getCertificate(host, port) local status, cert = sslcert.getCertificate(host, port)
if ( not(status) ) then if ( not(status) ) then
stdnse.debug1("getCertificate error: %s", cert or "unknown") stdnse.debug1("getCertificate error: %s", cert or "unknown")

View File

@@ -633,11 +633,10 @@ local function get_dhe_params(host, port, protocol, ciphers)
local t = {} local t = {}
local pos = 1 local pos = 1
t.protocol = protocol t.protocol = protocol
t.extensions = {} local tlsname = tls.servername(host)
t.extensions = {
if host.targetname then server_name = tlsname and tls.EXTENSION_HELPERS["server_name"](tlsname),
t.extensions.server_name = tls.EXTENSION_HELPERS.server_name(host.targetname) }
end
-- Keep ClientHello record size below 255 bytes and the number of ciphersuites -- Keep ClientHello record size below 255 bytes and the number of ciphersuites
-- to 64 or less in order to avoid implementation issues with some TLS servers -- to 64 or less in order to avoid implementation issues with some TLS servers

View File

@@ -499,26 +499,17 @@ local function remove_high_byte_ciphers(t)
return output return output
end end
-- Claim to support every elliptic curve and EC point format -- Get TLS extensions
local base_extensions = { local function base_extensions(host)
-- Claim to support every elliptic curve local tlsname = tls.servername(host)
["elliptic_curves"] = tls.EXTENSION_HELPERS["elliptic_curves"](sorted_keys(tls.ELLIPTIC_CURVES)), return {
-- Claim to support every EC point format -- Claim to support every elliptic curve
["ec_point_formats"] = tls.EXTENSION_HELPERS["ec_point_formats"](sorted_keys(tls.EC_POINT_FORMATS)), ["elliptic_curves"] = tls.EXTENSION_HELPERS["elliptic_curves"](sorted_keys(tls.ELLIPTIC_CURVES)),
} -- Claim to support every EC point format
["ec_point_formats"] = tls.EXTENSION_HELPERS["ec_point_formats"](sorted_keys(tls.EC_POINT_FORMATS)),
-- Recursively copy a table. -- Enable SNI if a server name is available
-- Only recurs when a value is a table, other values are copied by assignment. ["server_name"] = tlsname and tls.EXTENSION_HELPERS["server_name"](tlsname),
local function tcopy (t) }
local tc = {};
for k,v in pairs(t) do
if type(v) == "table" then
tc[k] = tcopy(v);
else
tc[k] = v;
end
end
return tc;
end end
-- Get a message body from a record which has the specified property set to value -- Get a message body from a record which has the specified property set to value
@@ -587,11 +578,8 @@ local function find_ciphers_group(host, port, protocol, group, scores)
local results = {} local results = {}
local t = { local t = {
["protocol"] = protocol, ["protocol"] = protocol,
["extensions"] = tcopy(base_extensions), ["extensions"] = base_extensions(host),
} }
if host.targetname then
t["extensions"]["server_name"] = tls.EXTENSION_HELPERS["server_name"](host.targetname)
end
-- This is a hacky sort of tristate variable. There are three conditions: -- This is a hacky sort of tristate variable. There are three conditions:
-- 1. false = either ciphers or protocol is bad. Keep trying with new ciphers -- 1. false = either ciphers or protocol is bad. Keep trying with new ciphers
@@ -775,11 +763,8 @@ local function get_chunk_size(host, protocol)
local len_t = { local len_t = {
protocol = protocol, protocol = protocol,
ciphers = {}, ciphers = {},
extensions = tcopy(base_extensions), extensions = base_extensions(host),
} }
if host.targetname then
len_t.extensions.server_name = tls.EXTENSION_HELPERS.server_name(host.targetname)
end
local cipher_len_remaining = 255 - #tls.client_hello(len_t) local cipher_len_remaining = 255 - #tls.client_hello(len_t)
-- if we're over 255 anyway, just go for it. -- if we're over 255 anyway, just go for it.
-- Each cipher adds 2 bytes -- Each cipher adds 2 bytes
@@ -815,11 +800,8 @@ local function find_compressors(host, port, protocol, good_ciphers)
local t = { local t = {
["protocol"] = protocol, ["protocol"] = protocol,
["ciphers"] = good_ciphers, ["ciphers"] = good_ciphers,
["extensions"] = tcopy(base_extensions), ["extensions"] = base_extensions(host),
} }
if host.targetname then
t["extensions"]["server_name"] = tls.EXTENSION_HELPERS["server_name"](host.targetname)
end
local results = {} local results = {}
@@ -896,11 +878,8 @@ local function compare_ciphers(host, port, protocol, cipher_a, cipher_b)
local t = { local t = {
["protocol"] = protocol, ["protocol"] = protocol,
["ciphers"] = {cipher_a, cipher_b}, ["ciphers"] = {cipher_a, cipher_b},
["extensions"] = tcopy(base_extensions), ["extensions"] = base_extensions(host),
} }
if host.targetname then
t["extensions"]["server_name"] = tls.EXTENSION_HELPERS["server_name"](host.targetname)
end
local records = try_params(host, port, t) local records = try_params(host, port, t)
local server_hello = records.handshake and get_body(records.handshake, "type", "server_hello") local server_hello = records.handshake and get_body(records.handshake, "type", "server_hello")
if server_hello then if server_hello then

View File

@@ -6,6 +6,7 @@ local sslcert = require "sslcert"
local stdnse = require "stdnse" local stdnse = require "stdnse"
local string = require "string" local string = require "string"
local table = require "table" local table = require "table"
local tls = require "tls"
description = [[ description = [[
Queries Google's Certificate Catalog for the SSL certificates retrieved from Queries Google's Certificate Catalog for the SSL certificates retrieved from
@@ -41,6 +42,7 @@ end
portrule = shortport.ssl portrule = shortport.ssl
action = function(host, port) action = function(host, port)
host.targetname = tls.servername(host)
local lines, sha1, query local lines, sha1, query
local status, cert = sslcert.getCertificate(host, port) local status, cert = sslcert.getCertificate(host, port)

View File

@@ -3,6 +3,7 @@ local nmap = require "nmap"
local shortport = require "shortport" local shortport = require "shortport"
local stdnse = require "stdnse" local stdnse = require "stdnse"
local sslcert = require "sslcert" local sslcert = require "sslcert"
local tls = require "tls"
local bin = require "bin" local bin = require "bin"
-- -*- mode: lua -*- -- -*- mode: lua -*-
@@ -108,6 +109,7 @@ portrule = shortport.ssl
action = function(host, port) action = function(host, port)
-- Get script arguments. -- Get script arguments.
host.targetname = tls.servername(host)
local path = stdnse.get_script_args("ssl-known-key.fingerprintfile") or FINGERPRINT_FILE local path = stdnse.get_script_args("ssl-known-key.fingerprintfile") or FINGERPRINT_FILE
local status, result = get_fingerprints(path) local status, result = get_fingerprints(path)
if not status then if not status then

View File

@@ -174,13 +174,17 @@ local function remove_high_byte_ciphers(t)
return output return output
end end
-- Claim to support every elliptic curve and EC point format local function base_extensions(host)
local base_extensions = { local tlsname = tls.servername(host)
-- Claim to support every elliptic curve return {
["elliptic_curves"] = tls.EXTENSION_HELPERS["elliptic_curves"](sorted_keys(tls.ELLIPTIC_CURVES)), -- Claim to support every elliptic curve
-- Claim to support every EC point format ["elliptic_curves"] = tls.EXTENSION_HELPERS["elliptic_curves"](sorted_keys(tls.ELLIPTIC_CURVES)),
["ec_point_formats"] = tls.EXTENSION_HELPERS["ec_point_formats"](sorted_keys(tls.EC_POINT_FORMATS)), -- Claim to support every EC point format
} ["ec_point_formats"] = tls.EXTENSION_HELPERS["ec_point_formats"](sorted_keys(tls.EC_POINT_FORMATS)),
-- Enable SNI if a server name is available
["server_name"] = tlsname and tls.EXTENSION_HELPERS["server_name"](tlsname),
}
end
-- Recursively copy a table. -- Recursively copy a table.
-- Only recurs when a value is a table, other values are copied by assignment. -- Only recurs when a value is a table, other values are copied by assignment.
@@ -202,11 +206,8 @@ local function find_ciphers_group(host, port, protocol, group)
results = {} results = {}
local t = { local t = {
["protocol"] = protocol, ["protocol"] = protocol,
["extensions"] = tcopy(base_extensions), ["extensions"] = base_extensions(host),
} }
if host.targetname then
t["extensions"]["server_name"] = tls.EXTENSION_HELPERS["server_name"](host.targetname)
end
-- This is a hacky sort of tristate variable. There are three conditions: -- This is a hacky sort of tristate variable. There are three conditions:
-- 1. false = either ciphers or protocol is bad. Keep trying with new ciphers -- 1. false = either ciphers or protocol is bad. Keep trying with new ciphers
@@ -303,11 +304,8 @@ local function check_fallback_scsv(host, port, protocol, ciphers)
local results = {} local results = {}
local t = { local t = {
["protocol"] = protocol, ["protocol"] = protocol,
["extensions"] = tcopy(base_extensions), ["extensions"] = base_extensions(host),
} }
if host.targetname then
t["extensions"]["server_name"] = tls.EXTENSION_HELPERS["server_name"](host.targetname)
end
t["ciphers"] = tcopy(ciphers) t["ciphers"] = tcopy(ciphers)
t.ciphers[#t.ciphers+1] = "TLS_FALLBACK_SCSV" t.ciphers[#t.ciphers+1] = "TLS_FALLBACK_SCSV"