1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-10 09:49:05 +00:00

Check for actually-random TLS random instead of date in ssl-date

Patch from nnposter here: http://seclists.org/nmap-dev/2014/q3/194
This commit is contained in:
dmiller
2014-08-01 21:57:04 +00:00
parent 2a8c81c4f6
commit 718c83f367

View File

@@ -1,6 +1,7 @@
local shortport = require "shortport" local shortport = require "shortport"
local stdnse = require "stdnse" local stdnse = require "stdnse"
local table = require "table" local table = require "table"
local math = require "math"
local nmap = require "nmap" local nmap = require "nmap"
local os = require "os" local os = require "os"
local string = require "string" local string = require "string"
@@ -12,7 +13,8 @@ Retrieves a target host's time and date from its TLS ServerHello response.
In many TLS implementations, the first four bytes of server randomness In many TLS implementations, the first four bytes of server randomness
are a Unix timestamp. are a Unix timestamp. The script will test whether this is indeed true
and report the time only if it passes this test.
Original idea by Jacob Appelbaum and his TeaTime and tlsdate tools: Original idea by Jacob Appelbaum and his TeaTime and tlsdate tools:
* https://github.com/ioerror/TeaTime * https://github.com/ioerror/TeaTime
@@ -32,7 +34,7 @@ Original idea by Jacob Appelbaum and his TeaTime and tlsdate tools:
-- <elem key="date">2012-08-02T18:29:31+00:00</elem> -- <elem key="date">2012-08-02T18:29:31+00:00</elem>
-- <elem key="delta">4</elem> -- <elem key="delta">4</elem>
author = "Aleksandar Nikolic" author = "Aleksandar Nikolic, nnposter"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html" license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"discovery", "safe", "default"} categories = {"discovery", "safe", "default"}
@@ -75,7 +77,7 @@ local client_hello = function(host, port)
status, err = sock:connect(host, port) status, err = sock:connect(host, port)
if not status then if not status then
sock:close() sock:close()
stdnse.print_debug("Can't send: %s", err) stdnse.debug("Can't send: %s", err)
return false return false
end end
else else
@@ -89,7 +91,7 @@ local client_hello = function(host, port)
-- Send Client Hello to the target server -- Send Client Hello to the target server
status, err = sock:send(cli_h) status, err = sock:send(cli_h)
if not status then if not status then
stdnse.print_debug("Couldn't send: %s", err) stdnse.debug("Couldn't send: %s", err)
sock:close() sock:close()
return false return false
end end
@@ -97,7 +99,7 @@ local client_hello = function(host, port)
-- Read response -- Read response
status, response, err = tls.record_buffer(sock) status, response, err = tls.record_buffer(sock)
if not status then if not status then
stdnse.print_debug("Couldn't receive: %s", err) stdnse.debug("Couldn't receive: %s", err)
sock:close() sock:close()
return false return false
end end
@@ -109,7 +111,7 @@ end
local extract_time = function(response) local extract_time = function(response)
local i, record = tls.record_read(response, 0) local i, record = tls.record_read(response, 0)
if record == nil then if record == nil then
stdnse.debug1("Unknown response from server") stdnse.debug("%s: Unknown response from server", SCRIPT_NAME)
return nil return nil
end end
@@ -120,27 +122,51 @@ local extract_time = function(response)
end end
end end
end end
stdnse.debug1("Server response was not server_hello") stdnse.debug("%s: Server response was not server_hello", SCRIPT_NAME)
return nil return nil
end end
action = function(host, port) local get_time_sample = function (host, port)
local status, response
-- Send crafted client hello -- Send crafted client hello
status, response = client_hello(host, port) local rstatus, response = client_hello(host, port)
local now = os.time() local stm = os.time()
if status and response then if not (rstatus and response) then return nil end
-- extract time from response -- extract time from response
local result local tstatus, ttm = extract_time(response)
status, result = extract_time(response) if not tstatus then return nil end
if status then return ttm, stm
local output = { end
date = stdnse.format_timestamp(result, 0),
delta = os.difftime(result, now),
} action = function(host, port)
return output, string.format("%s; %s from local time.", output.date, local ttm, stm = get_time_sample(host, port)
stdnse.format_difftime(os.date("!*t",result),os.date("!*t", now))) if not ttm then
end return stdnse.format_output(false, "Unable to obtain data from the target")
end end
local delta = os.difftime(ttm, stm)
stdnse.debug(2, "Sample #1 time difference is %d seconds", delta)
if math.abs(delta) > 15*60 then
-- time difference is suspect
-- get a second sample to determine if the clock is simply off
-- or if the TLS randomness does not represent the time at all
ttm, stm = get_time_sample(host, port)
if not ttm then
return stdnse.format_output(false, "Unable to obtain data from the target")
end
local origdelta = delta
delta = os.difftime(ttm, stm)
stdnse.debug(2, "Sample #2 time difference is %d seconds", delta)
if math.abs(origdelta - delta) > 5 then
return stdnse.format_output(false, "TLS randomness does not represent time")
end
end
local output = {
date = stdnse.format_timestamp(ttm, 0),
delta = delta,
}
return output,
string.format("%s; %s from scanner time.", output.date,
stdnse.format_difftime(os.date("!*t",ttm),os.date("!*t", stm)))
end end