diff --git a/scripts/ssh-hostkey.nse b/scripts/ssh-hostkey.nse
index f388eed9e..bf9911f14 100644
--- a/scripts/ssh-hostkey.nse
+++ b/scripts/ssh-hostkey.nse
@@ -1,4 +1,3 @@
-local base64 = require "base64"
local ipOps = require "ipOps"
local nmap = require "nmap"
local shortport = require "shortport"
@@ -97,6 +96,15 @@ gathered keys.
-- f058cef4aaa4591c8edd4d0744c82511
-- ssh-rsa
--
+--
+--
+--
+-- 5
+-- localhost
+-- ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAwVuv2gcr0maaKQ69VVIEv2ob4OxnuI64fkeOnCXD1lUx5tTA+vefXUWEMxgMuA7iX4irJHy2zer0NQ3Z3yJvr5scPgTYIaEOp5Uo/eGFG9Agpk5wE8CoF0e47iCAPHqzlmP2V7aNURLMODb3jVZuI07A2ZRrMGrD8d888E2ORVORv1rYeTYCqcMMoVFmX9l3gWEdk4yx3w5sD8v501Iuyd1v19mPfyhrI5E1E1nl/Xjp5N0/xP2GUBrdkDMxKaxqTPMie/f0dXBUPQQN697a5q+5lBRPhKYOtn6yQKCd9s1Q22nxn72Jmi1RzbMyYJ52FosDT755Qmb46GLrDMaZMQ==
+--
+--
+--
--
--@xmloutput
--
@@ -175,7 +183,7 @@ local function check_keys(host, keys, f)
if not foundhostname then
for _, k in ipairs(keys_found) do
if ("%s %s"):format(parts[2], parts[3]) == k then
- table.insert(same_key_hashed, {lnumber = lnumber})
+ table.insert(same_key_hashed, {name="", key=k, lnumber = lnumber})
end
end
end
@@ -214,45 +222,49 @@ local function check_keys(host, keys, f)
end
-- Start making output.
- local return_string = "Key comparison with known_hosts file: "
+ local out
if #keys_from_file == 0 then
- return_string = return_string .. "\n\t" .. "No entry for scanned host found in known_hosts file."
+ out = "No entry for scanned host found in known_hosts file."
else
- if next(matched_keys) or next(same_key_hashed) or next(same_key) then
- return_string = return_string .. "\n\tGOOD Matches in known_hosts file: "
- if next(matched_keys) then
- for __, gm in ipairs(matched_keys) do
- return_string = return_string .. "\n\t\tL" .. gm.lnumber .. ": " .. gm.name
- end
- end
- if next(same_key) then
- for __, gm in ipairs(same_key) do
- return_string = return_string .. "\n\t\tL" .. gm.lnumber .. ": " .. gm.name
- end
+ out = stdnse.output_table()
+ local match_mt = {
+ __tostring = function(self)
+ return string.format("L%d: %s", self.lnumber, self.name)
end
+ }
+ local good = {}
+ for __, gm in ipairs(matched_keys) do
+ setmetatable(gm, match_mt)
+ good[#good+1] = gm
+ end
+ for __, gm in ipairs(same_key) do
+ setmetatable(gm, match_mt)
+ good[#good+1] = gm
+ end
+ for __, gm in ipairs(same_key_hashed) do
+ setmetatable(gm, match_mt)
+ good[#good+1] = gm
+ end
+ if #good > 0 then
+ out["GOOD Matches in known_hosts file"] = good
+ end
- if next(same_key_hashed) then
- for __, gm in ipairs(same_key_hashed) do
- return_string = return_string .. "\n\t\tL" .. gm.lnumber .. ": "
- end
- end
-
- if different_keys ~= 0 then
- return_string = return_string .. "\n\tWRONG Matches in known_hosts file: "
- for __, gm in ipairs(different_keys) do
- return_string = return_string .. "\n\t\tL" .. gm.lnumber .. ": " .. gm.name
- end
- end
+ local wrong = {}
+ for __, gm in ipairs(different_keys) do
+ setmetatable(gm, match_mt)
+ wrong[#wrong+1] = gm
+ end
+ if #wrong > 0 then
+ out["WRONG Matches in known_hosts file"] = wrong
end
end
- return true, return_string
+ return out
end
--- gather host keys
--@param host nmap host table
--@param port nmap port table of the currently probed port
local function portaction(host, port)
- local output = {}
local output_tab = {}
local keys = {}
local _,key
@@ -277,14 +289,19 @@ local function portaction(host, port)
key = ssh2.fetch_host_key( host, port, "ecdsa-sha2-nistp521" )
if key then table.insert( keys, key ) end
+ if #keys < 0 then
+ return nil
+ end
+
for _, key in ipairs( keys ) do
add_key_to_registry( host, key )
- table.insert(output_tab, {
- fingerprint=stdnse.tohex(key.fingerprint),
- type=key.key_type,
- bits=key.bits,
- key=base64.enc(key.key),
- })
+ local output = {}
+ local out = {
+ fingerprint=stdnse.tohex(key.fingerprint),
+ type=key.key_type,
+ bits=key.bits,
+ key=base64.enc(key.key),
+ }
if format:find( 'hex', 1, true ) or all_formats then
table.insert( output, ssh1.fingerprint_hex( key.fingerprint, key.algorithm, key.bits ) )
end
@@ -292,29 +309,28 @@ local function portaction(host, port)
table.insert( output, ssh1.fingerprint_bubblebabble( openssl.sha1(key.fp_input), key.algorithm, key.bits ) )
end
if format:find( 'visual', 1, true ) or all_formats then
- -- insert empty line so table is not destroyed if this is the first
- -- line of output
- if #output == 0 then table.insert( output, " " ) end
table.insert( output, ssh1.fingerprint_visual( key.fingerprint, key.algorithm, key.bits ) )
end
if nmap.verbosity() > 1 or format:find( 'full', 1, true ) or all_formats then
table.insert( output, key.full_key )
end
+ setmetatable(out, {
+ __tostring = function(self)
+ return table.concat(output, "\n")
+ end
+ })
+ table.insert(output_tab, out)
end
-- if a known_hosts file was given, then check if it contains a key for the host being scanned
local known_hosts = stdnse.get_script_args("ssh-hostkey.known-hosts") or false
if known_hosts then
known_hosts = ssh1.parse_known_hosts_file(known_hosts)
- local res, status
- res, status = check_keys(host, keys, known_hosts)
- table.insert(output, 1, status)
+ output_tab["Key comparison with known_hosts file"] = check_keys(
+ host, keys, known_hosts)
end
-
- if #output > 0 then
- return output_tab, table.concat( output, '\n' )
- end
+ return output_tab
end
--- iterate over the list of gathered keys and look for duplicate hosts (sharing the same hostkeys)