Nmap Development mailing list archives

[NSE script] SSH weak hostkey


From: Sven Klemm <sven () c3d2 de>
Date: Sun, 17 Aug 2008 11:11:27 +0200

Hi,

i've written a NSE script which checks the keys found by the SSH hostkey script for weak keys (CVE-2008-0166). Currently it uses the blacklists from the openssh-blacklist package but I am thinking about replacing it with something else as the lists only contains the last 10 bytes of the 16 byte fingerprint. Those lists are nevertheless quite big (8MB total) and I wonder what the policy for external data files for nmap is. Should a script include necessary data files or can it rely on other packages to supply them?

Example output:

./nmap --script SSH-hostkey,SSH-weak_key localhost

Starting Nmap 4.68 ( http://nmap.org ) at 2008-08-17 11:07 CEST
Interesting ports on localhost (127.0.0.1):
Not shown: 1714 closed ports
PORT     STATE SERVICE
22/tcp   open  ssh
|  SSH Hostkey: rsa1 1024 89:7c:8b:2e:ee:5c:3d:ab:20:bd:d7:b3:a4:5a:a8:80
|  ssh-dss 1024 23:23:8c:73:26:22:4a:63:d8:5d:41:eb:86:cf:a0:58
|_ ssh-rsa 2048 f0:58:ce:f4:aa:a4:59:1c:8e:dd:4d:07:44:c8:25:11
53/tcp   open  domain
5432/tcp open  postgresql

Host script results:
|_ SSH weak keys: ssh-rsa 2048 f0:58:ce:f4:aa:a4:59:1c:8e:dd:4d:07:44:c8:25:11

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


Cheers,
Sven

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

--- checks SSH hostkeys for weak keys. Uses blacklists from openssh-blacklist 
-- package located under /usr/share/ssh.
--
--@output
--|_ SSH weak keys: ssh-rsa 2048 f0:58:ce:f4:aa:a4:59:1c:8e:dd:4d:07:44:c8:25:11

require("stdnse")
require("shortport")

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

hostrule = function( host ) return true end

local weak_keys = {}

--- read list of weak ssh key fingerprints
local read_db = function( db )
  if not weak_keys[db] then
    weak_keys[db] = {}

    local path = '/usr/share/ssh/blacklist.' .. db
          local file = io.open(path, "r")
    if not file then
      stdnse.print_debug( "No list of weak keys found for " .. db )
      return
    end
          while true do
                local l = file:read()

                if not l then break end

                l = l:gsub("%s*#.*", "")
                if #l == 20 then
        weak_keys[db][l] = l
                end
          end
          file:close()
  end
end

--- format fingerprint for displaying
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

--- check whether this is a known weak key for a specific algorithm
local check_key = function( db, fp )
  fp = fp:sub( 13, 32 )
  read_db( db )
  if weak_keys[db][fp] then
    return true
  else
    return false
  end
end

--- lookup whether key is a known weak key
local known_weak_key = function( key )
  local check_fp, db
  if key.key_type == 'ssh-dss' then
    db = ("DSA-%d"):format( key.bits )
  elseif key.key_type == 'ssh-rsa' then
    db = ("RSA-%d"):format( key.bits )
  else
    stdnse.print_debug( "Unsupported key type: " .. key.key_type )
    return false
  end
  return check_key( db, key.fingerprint )
end

action = function(host, port)
  if not nmap.registry['SSH Hostkey'] then return end
  local output = {}
  local keys = nmap.registry['SSH Hostkey'][host.ip]

  local _,key
  for _, key in ipairs( keys ) do
    if known_weak_key( key ) then
      table.insert(output,("%s %d %s"):format(key.key_type,key.bits,format_fingerprint(key.fingerprint)))
    end
  end

  if #output > 0 then
    return table.concat( output, '\n' )
  else
    return nil
  end
end


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

Current thread: