Nmap NSE script to check for TLS Extended Random support. Requires Nmap (http://nmap.org) and the latest version of the tls.lua library from https://svn.nmap.org/nmap/nselib/tls.lua
local nmap = require "nmap" | |
local shortport = require "shortport" | |
local stdnse = require "stdnse" | |
local bin = require "bin" | |
local tls = require "tls" | |
description = [[ | |
Checks for server support of the Extended Random TLS extension, which was | |
allegedly created to make exploitation of the Dual EC DRBG weakness easier. The | |
extension was never widely adopted, and IANA did not assign an ExtensionType | |
number, but the RSA BSAFE library uses 0x0028 for this purpose. Note that if | |
this extension number is used for some other purpose, it is possible that this | |
script will return a false-positive. | |
References: | |
* http://tools.ietf.org/html/draft-rescorla-tls-extended-random-02 | |
* https://developer-content.emc.com/docs/rsashare/share_for_c/1.1/api_guide/group___t_l_s___e_x_t___t_y_p_e.html | |
* https://projectbullrun.org/dual-ec/ext-rand.html | |
]] | |
--- | |
-- @usage | |
-- nmap --script=tls-extended-random <targets> | |
-- | |
--@output | |
-- 443/tcp open https | |
-- |_tls-extended-random: Supported. | |
-- | |
-- @xmloutput | |
-- <elem>true</elem> | |
author = "Daniel Miller" | |
license = "Same as Nmap--See http://nmap.org/book/man-legal.html" | |
categories = {"discovery", "safe"} | |
portrule = shortport.ssl | |
local RANDDATA = "DUAL_EC DRBG YO!" | |
--- Function that sends a client hello packet with the TLS Extended Random extension to the | |
-- target host and returns the response | |
--@args host The target host table. | |
--@args port The target port table. | |
--@return status true if response, false else. | |
--@return response if status is true. | |
local client_hello = function(host, port) | |
local sock, status, response, err, cli_h | |
cli_h = tls.client_hello({ | |
["protocol"] = "TLSv1.0", | |
["ciphers"] = { | |
"TLS_ECDHE_RSA_WITH_RC4_128_SHA", | |
"TLS_DHE_RSA_WITH_AES_256_CBC_SHA", | |
"TLS_RSA_WITH_RC4_128_MD5", | |
}, | |
["compressors"] = {"NULL"}, | |
["extensions"] = { | |
[0x0028] = bin.pack(">P", RANDDATA) | |
}, | |
}) | |
-- Connect to the target server | |
sock = nmap.new_socket() | |
sock:set_timeout(5000) | |
status, err = sock:connect(host, port) | |
if not status then | |
sock:close() | |
stdnse.print_debug("Can't send: %s", err) | |
return false | |
end | |
-- Send Client Hello to the target server | |
status, err = sock:send(cli_h) | |
if not status then | |
stdnse.print_debug("Couldn't send: %s", err) | |
sock:close() | |
return false | |
end | |
-- Read response | |
status, response, err = tls.record_buffer(sock) | |
if not status then | |
stdnse.print_debug("Couldn't receive: %s", err) | |
sock:close() | |
return false | |
end | |
return true, response | |
end | |
--- Function that checks for the response to a Extended Random extension request. | |
--@args response Response to parse. | |
--@return results The random data generated by the server, or nil if the extension is not supported | |
local check_rand = function(response) | |
local i, record = tls.record_read(response, 0) | |
if record == nil then | |
stdnse.print_debug("%s: Unknown response from server", SCRIPT_NAME) | |
return nil | |
end | |
if record.type == "handshake" and record.body[1].type == "server_hello" then | |
if record.body[1].extensions == nil then | |
stdnse.print_debug("%s: Server does not support TLS Extended Random extension.", SCRIPT_NAME) | |
return nil | |
end | |
local randdata = record.body[1].extensions[0x0028] | |
if randdata == nil then | |
stdnse.print_debug("%s: Server does not support TLS Extended Random extension.", SCRIPT_NAME) | |
return nil | |
end | |
-- Parse data | |
local _, results = bin.unpack(">P", randdata, 0) | |
return results | |
else | |
stdnse.print_debug("%s: Server response was not server_hello", SCRIPT_NAME) | |
return nil | |
end | |
end | |
action = function(host, port) | |
local status, response | |
-- Send crafted client hello | |
status, response = client_hello(host, port) | |
if status and response then | |
-- Analyze response | |
local results = check_rand(response) | |
if results then --#results == #RANDDATA then | |
return true, "Supported." | |
end | |
end | |
return nil | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment