Nmap Development mailing list archives

Re: [NSE script] SSH2 hostkey


From: Sven Klemm <sven () c3d2 de>
Date: Tue, 05 Aug 2008 19:18:07 +0200

Hi Brandon,

You might consider only displaying the key fingerprint instead of the
full key unless verbose is set to at least 2.  Here is what that would
look like:

Starting Nmap 4.68 ( http://nmap.org ) at 2008-08-05 16:34 CEST
Interesting ports on localhost (127.0.0.1):
PORT   STATE SERVICE
22/tcp open  ssh
|  SSH2-Hostkey: ssh-rsa 2048 f0:58:ce:f4:aa:a4:59:1c:8e:dd:4d:07:44:c8:25:11
|_ ssh-dss 1024 23:23:8c:73:26:22:4a:63:d8:5d:41:eb:86:cf:a0:58

You'll have to dig into the standard spec to figure out what part of
the key you compute the hash over.  For RSA it is probably the modulus
but I'm not sure for DSA.

I've attached a new version that implements your proposal.

Sample output:

> ./nmap --script SSH2-hostkey -p 22 localhost

Starting Nmap 4.68 ( http://nmap.org ) at 2008-08-05 19:13 CEST
Interesting ports on localhost (127.0.0.1):
PORT   STATE SERVICE
22/tcp open  ssh
| SSH2-Hostkey: ssh-rsa 2048 f0:58:ce:f4:aa:a4:59:1c:8e:dd:4d:07:44:c8:25:11
|_ ssh-dsa 1024 23:23:8c:73:26:22:4a:63:d8:5d:41:eb:86:cf:a0:58

Nmap done: 1 IP address (1 host up) scanned in 0.06 seconds


Sample output with verbosity 2:

> ./nmap --script SSH2-hostkey -p 22 localhost -vv

Starting Nmap 4.68 ( http://nmap.org ) at 2008-08-05 19:12 CEST
Initiating Ping Scan at 19:12
Scanning 127.0.0.1 [1 port]
Completed Ping Scan at 19:12, 0.00s elapsed (1 total hosts)
Initiating Connect Scan at 19:12
Scanning localhost (127.0.0.1) [1 port]
Discovered open port 22/tcp on 127.0.0.1
Completed Connect Scan at 19:12, 0.00s elapsed (1 total ports)
SCRIPT ENGINE: Initiating script scanning.
Initiating SCRIPT ENGINE at 19:12
Completed SCRIPT ENGINE at 19:12, 0.03s elapsed
Host localhost (127.0.0.1) appears to be up ... good.
Scanned at 2008-08-05 19:12:40 CEST for 0s
Interesting ports on localhost (127.0.0.1):
PORT   STATE SERVICE
22/tcp open  ssh
| SSH2-Hostkey: ssh-rsa 2048 f0:58:ce:f4:aa:a4:59:1c:8e:dd:4d:07:44:c8:25:11 AAAAB3NzaC1yc2EAAAABIwAAAQEAwVuv2gcr0maaKQ69VVIEv2ob4OxnuI64fkeOnCXD1lUx5tTA+vefXUWEMxgMuA7iX4irJHy2zer0NQ3Z3yJvr5scPgTYIaEOp5Uo/eGFG9Agpk5wE8CoF0e47iCAPHqzlmP2V7aNURLMODb3jVZuI07A2ZRrMGrD8d888E2ORVORv1rYeTYCqcMMoVFmX9l3gWEdk4yx3w5sD8v501Iuyd1v19mPfyhrI5E1E1nl/Xjp5N0/xP2GUBrdkDMxKaxqTPMie/f0dXBUPQQN697a5q+5lBRPhKYOtn6yQKCd9s1Q22nxn72Jmi1RzbMyYJ52FosDT755Qmb46GLrDMaZMQ== |_ ssh-dsa 1024 23:23:8c:73:26:22:4a:63:d8:5d:41:eb:86:cf:a0:58 AAAAB3NzaC1kc3MAAACBAJD6ApUbSAGL/jKRaxE0QQLGB3eH7sEPxAFYhWz1nEiwOIh50ONd0Nr2UAFsQlYvnk7Bchx7tElWP57eHpyr9BWZwFOTQQAEM77dKNbUzqQhoSppRqnbFjErTp/PnvwY95M05Kdm98MnxA6ngE4Nz8C0eL69sm/oFRQ6ahGmWcSLAAAAFQCW+NG4KsuIgk/9LuuKmUy/9MMQ1wAAAIA8vwBaH5evPRJi1rmo/QGhJiC8iQCnwbXqwnJGVIWFvYuofQCERs0xzfcrMOi8J3AMd1qhOjUC0YTg6xXtxPlW3Un7cmLcia3IVPUewjsNfLUIQ6TVXqAP8yU9elSE39zrBNrC0o30K2fMDB/ngn+ml/G9gd0/W0XStfx8svglsQAAAIEAgXXWoZej/rbTwTd61Gz+XpLwwqJkPT9EHgPVSVRD399BN3zxP9ghib+K9c6snavFvhWxrTgU/ZZZmiyOwOMcltp08REErOj5U54dzM/hYbYio0Ke83y1/llnFwoOimCHdJ0NSr/a69ZudNN3j8651ufIp13kDETBmEMMCGy8OqY=

Read data files from: .
Nmap done: 1 IP address (1 host up) scanned in 0.10 seconds


Cheers,
Sven

--
Sven Klemm
http://cthulhu.c3d2.de/~sven/


id = "SSH2-Hostkey"
author = "Sven Klemm <sven () c3d2 de>"
description = "Show SSH2 Hostkey"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html";
categories = {"safe"}

require("stdnse")
require("shortport")
require("openssl")
require("bin")
require("base64")
require("hash")

portrule = shortport.port_or_service(22, "ssh")

local ssh2
ssh2 = {
  transport = {
    build = function( payload )
      local packet_length, padding_length
      padding_length = 8 - ( (payload:len() + 1 + 4 ) % 8 )
      packet_length = payload:len() + padding_length + 1
      return bin.pack( ">IcAA", packet_length, padding_length, payload, openssl.rand_pseudo_bytes( padding_length ) )
    end,

    payload = function( packet )
      local packet_length, padding_length, payload_length, payload, offset
      offset, packet_length, padding_length = bin.unpack( ">Ic", packet )
      payload_length = packet_length - padding_length - 1
      offset, payload = bin.unpack( ">A" .. payload_length, packet, offset )
      return payload
    end,

    dh_gex_request = function( min, opt, max )
      return bin.pack( ">cIII", 34, min, opt, max )
    end,

    kexdh_init = function( e )
      return bin.pack( ">cIA", 30, e:num_bytes(), e:to_bin() )
    end,

    kex_init = function( cookie, options )
      options = options or {}
      kex_algorithms = "diffie-hellman-group1-sha1"
      host_key_algorithms = options['host_key_algorithms'] or "ssh-dss,ssh-rsa"
      encryption_algorithms = "aes128-cbc,3des-cbc,blowfish-cbc,aes192-cbc,aes256-cbc,aes128-ctr,aes192-ctr,aes256-ctr"
      mac_algorithms = "hmac-md5,hmac-sha1,hmac-ripemd160"
      compression_algorithms = "none"
      languages = ""

      local payload = bin.pack( ">cAaa", 20, cookie, kex_algorithms, host_key_algorithms )
      payload = payload .. bin.pack( ">aa", encryption_algorithms, encryption_algorithms )
      payload = payload .. bin.pack( ">aa", mac_algorithms, mac_algorithms )
      payload = payload .. bin.pack( ">aa", compression_algorithms, compression_algorithms )
      payload = payload .. bin.pack( ">aa", languages, languages )
      payload = payload .. bin.pack( ">cI", 0, 0 )

      return payload
    end
  },
  fetch_host_key = function( host, port, key_type )
    local socket = nmap.new_socket()
    local catch = function() socket:close() end
    local try = nmap.new_try(catch)
    -- oakley group 2 prime taken from rfc 2409
    local prime = 
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF"

    try(socket:connect(host.ip, port.number))
    -- fetch banner
    try(socket:receive_lines(1))
    -- send our banner
    try(socket:send("SSH-2.0-Nmap-SSH2-Hostkey\r\n"))

    local cookie = openssl.rand_bytes( 16 )
    local packet = ssh2.transport.build( ssh2.transport.kex_init( cookie, {host_key_algorithms=key_type} ) )
    try(socket:send( packet ))

    local kex_init = try(socket:receive_bytes(1))
    kex_init = ssh2.transport.payload( kex_init )
    -- check for proper msg code
    if kex_init:byte(1) ~= 20 then
      return
    end

    local e, g, x, p
    -- e = g^x mod p
    g = openssl.bignum_dec2bn( "2" )
    p = openssl.bignum_hex2bn( prime )
    x = openssl.bignum_pseudo_rand( 1024 )
    e = openssl.bignum_mod_exp( g, p, x )

    packet = ssh2.transport.build( ssh2.transport.kexdh_init( e ) )
    try(socket:send( packet ))

    local kexdh_reply = try(socket:receive_bytes(1))
    kexdh_reply = ssh2.transport.payload( kexdh_reply )
    -- check for proper msg code
    if kexdh_reply:byte(1) ~= 31 then
      return
    end

    local public_host_key
    _, _, public_host_key = bin.unpack( ">ca", kexdh_reply )

    return public_host_key
  end
}

local format_fingerprint = function( fp )
  local s = fp:sub( 1, 2 )
  for i = 3, #fp, 2 do
    s = s .. ':' .. fp:sub( i, i + 1 )
  end
  return s
end

action = function(host, port)
  local output = ""

  local rsa_key = ssh2.fetch_host_key( host, port, "ssh-rsa" )
  if rsa_key then 
    local key_type, e, n
    _, key_type, e, n = bin.unpack( ">aaa", rsa_key )
    output = output .. "ssh-rsa " .. openssl.bignum_bin2bn( n ):num_bits() .. " " .. format_fingerprint( hash.md5( 
rsa_key ) )
    if nmap.verbosity() > 1 then
      output = output .. ' ' .. base64.enc( rsa_key )
    end
    output = output .. '\n'
  end

  local dsa_key = ssh2.fetch_host_key( host, port, "ssh-dss" )
  if dsa_key then 
    local key_type,p,q,g,y
    _, key_type, p, q, g, y = bin.unpack( ">aaaaaa", dsa_key )
    output = output .. "ssh-dsa " .. openssl.bignum_bin2bn( p ):num_bits() .. " " .. format_fingerprint( hash.md5( 
dsa_key ) )
    if nmap.verbosity() > 1 then
      output = output .. ' ' .. base64.enc( dsa_key )
    end
  end

  return output

end


_______________________________________________
Sent through the nmap-dev mailing list
http://cgi.insecure.org/mailman/listinfo/nmap-dev
Archived at http://SecLists.Org

Current thread: