diff options
Diffstat (limited to 'scripts/ssh2-enum-algos.nse')
-rw-r--r-- | scripts/ssh2-enum-algos.nse | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/scripts/ssh2-enum-algos.nse b/scripts/ssh2-enum-algos.nse new file mode 100644 index 0000000..fda9f0e --- /dev/null +++ b/scripts/ssh2-enum-algos.nse @@ -0,0 +1,212 @@ +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local stringaux = require "stringaux" +local table = require "table" + +local openssl = stdnse.silent_require "openssl" +local ssh2 = stdnse.silent_require "ssh2" + +description = [[ +Reports the number of algorithms (for encryption, compression, etc.) that +the target SSH2 server offers. If verbosity is set, the offered algorithms +are each listed by type. + +If the "client to server" and "server to client" algorithm lists are identical +(order specifies preference) then the list is shown only once under a combined +type. +]] + +--- +-- @usage +-- nmap --script ssh2-enum-algos target +-- +-- @output +-- PORT STATE SERVICE +-- 22/tcp open ssh +-- | ssh2-enum-algos: +-- | kex_algorithms (4) +-- | diffie-hellman-group-exchange-sha256 +-- | diffie-hellman-group-exchange-sha1 +-- | diffie-hellman-group14-sha1 +-- | diffie-hellman-group1-sha1 +-- | server_host_key_algorithms (2) +-- | ssh-rsa +-- | ssh-dss +-- | encryption_algorithms (13) +-- | aes128-ctr +-- | aes192-ctr +-- | aes256-ctr +-- | arcfour256 +-- | arcfour128 +-- | aes128-cbc +-- | 3des-cbc +-- | blowfish-cbc +-- | cast128-cbc +-- | aes192-cbc +-- | aes256-cbc +-- | arcfour +-- | rijndael-cbc@lysator.liu.se +-- | mac_algorithms (6) +-- | hmac-md5 +-- | hmac-sha1 +-- | hmac-ripemd160 +-- | hmac-ripemd160@openssh.com +-- | hmac-sha1-96 +-- | hmac-md5-96 +-- | compression_algorithms (2) +-- | none +-- |_ zlib@openssh.com +-- +-- @xmloutput +-- <table key="kex_algorithms"> +-- <elem>ecdh-sha2-nistp256</elem> +-- <elem>ecdh-sha2-nistp384</elem> +-- <elem>ecdh-sha2-nistp521</elem> +-- <elem>diffie-hellman-group-exchange-sha256</elem> +-- <elem>diffie-hellman-group-exchange-sha1</elem> +-- <elem>diffie-hellman-group14-sha1</elem> +-- <elem>diffie-hellman-group1-sha1</elem> +-- </table> +-- <table key="server_host_key_algorithms"> +-- <elem>ssh-rsa</elem> +-- <elem>ecdsa-sha2-nistp256</elem> +-- </table> +-- <table key="encryption_algorithms"> +-- <elem>aes128-ctr</elem> +-- <elem>aes192-ctr</elem> +-- <elem>aes256-ctr</elem> +-- <elem>aes128-cbc</elem> +-- <elem>3des-cbc</elem> +-- <elem>blowfish-cbc</elem> +-- <elem>cast128-cbc</elem> +-- <elem>aes192-cbc</elem> +-- <elem>aes256-cbc</elem> +-- </table> +-- <table key="mac_algorithms"> +-- <elem>hmac-sha1</elem> +-- <elem>umac-64@openssh.com</elem> +-- <elem>hmac-ripemd160</elem> +-- <elem>hmac-sha2-256</elem> +-- <elem>hmac-sha2-512</elem> +-- </table> +-- <table key="compression_algorithms"> +-- <elem>none</elem> +-- <elem>zlib@openssh.com</elem> +-- </table> + +author = "Kris Katterjohn" + +license = "Same as Nmap--See https://nmap.org/book/man-legal.html" + +categories = {"safe", "discovery"} + + +portrule = shortport.ssh + +-- Build onto lists{} and possibly modify parsed{} based on whether the +-- algorithm name-lists are identical between the server-to-client and +-- client-to-server types. Note that this simply modifies the passed tables. +local combine_types = function(parsed, lists) + local doubles = { + "encryption_algorithms", + "mac_algorithms", + "compression_algorithms" + } + + for _, i in ipairs(doubles) do + local c2s = i .. "_client_to_server" + local s2c = i .. "_server_to_client" + + if parsed[c2s] == parsed[s2c] then + parsed[i] = parsed[c2s] + parsed[c2s] = nil + parsed[s2c] = nil + table.insert(lists, i) + else + table.insert(lists, c2s) + table.insert(lists, s2c) + end + end +end + +-- Build and return the output table +local output = function(parsed, lists) + local out = stdnse.output_table() + + for _, l in ipairs(lists) do + local v = parsed[l] + local a = v:len() > 0 and stringaux.strsplit(",", v) or {} + if nmap.verbosity() > 0 then + setmetatable(a, { + __tostring = function(t) + return string.format("(%d)\n %s", #t, table.concat(t, "\n ")) + end + }) + else + setmetatable(a, { + __tostring = function(t) + return string.format("(%d)", #t) + end + }) + end + out[l] = a + end + + return out +end + +action = function(host, port) + local sock = nmap.new_socket() + local status = sock:connect(host, port) + if not status then + return + end + + -- send the client banner + -- NB: The protocol does not prescribe which side sends the banner first + status = sock:send("SSH-2.0-Nmap_SSH2_Enum_Algos\r\n") + if not status then + sock:close() + return + end + + -- slurp the server banner + status = sock:receive_buf("\r?\n", false) + if not status then + sock:close() + return + end + + local ssh = ssh2.transport + + -- send the client key exchange + -- NB: The protocol does not prescribe which side sends the kex init first + status = sock:send(ssh.build(ssh.kex_init())) + if not status then + sock:close() + return + end + + local response + status, response = ssh.receive_packet(sock) + sock:close() + if not status then + return + end + + local parsed = ssh.parse_kex_init(ssh.payload(response)) + + local lists = { + "kex_algorithms", + "server_host_key_algorithms" + -- Other types will be added below in combine_types() + } + + -- Modifies tables + combine_types(parsed, lists) + + return output(parsed, lists) +end + |