o [NSE] Added ssl-known-key.nse, which checks SSL certificates against a

list of certificates with known keys that have been extracted from
  firmware files. [Mak Kolybabi]
This commit is contained in:
david 2011-03-22 19:44:40 +00:00
parent ce23a35715
commit 47557a108b
4 changed files with 2166 additions and 0 deletions

View file

@ -1,5 +1,9 @@
# Nmap Changelog ($Id$); -*-text-*-
o [NSE] Added ssl-known-key.nse, which checks SSL certificates against a
list of certificates with known keys that have been extracted from
firmware files. [Mak Kolybabi]
o [Ndiff] The Nmap banner (with the version number and date of the scan)
is not printed unless there were other differences. This makes Nidff
produce no output when there wre no differences other than the version

File diff suppressed because it is too large Load diff

View file

@ -170,6 +170,7 @@ Entry { filename = "ssh2-enum-algos.nse", categories = { "discovery", "safe", }
Entry { filename = "sshv1.nse", categories = { "default", "safe", } }
Entry { filename = "ssl-cert.nse", categories = { "discovery", "safe", } }
Entry { filename = "ssl-enum-ciphers.nse", categories = { "discovery", "intrusive", } }
Entry { filename = "ssl-known-key.nse", categories = { "discovery", } }
Entry { filename = "sslv2.nse", categories = { "default", "safe", } }
Entry { filename = "stuxnet-detect.nse", categories = { "discovery", "intrusive", } }
Entry { filename = "svn-brute.nse", categories = { "auth", "intrusive", } }

151
scripts/ssl-known-key.nse Normal file
View file

@ -0,0 +1,151 @@
-- -*- mode: lua -*-
-- vim: set filetype=lua :
description = [[
This script checks whether the SSL certificate used by a host has a fingerprint
that matches the ones in a database.
The database checked is currently from LittleBlackBox 0.1, but any file of
fingerprints will serve just as well. One suggestion is the list of the weak
Debian OpenSSL keys.
]]
---
-- @usage
-- nmap --script ssl-known-key -p 443 <host>
--
-- @args ssl-known-key.fingerprintfile Specify a different file to read
-- fingerprints from.
--
-- @output
-- PORT STATE SERVICE REASON
-- 443/tcp open https syn-ack
-- |_ssl-known-key: 00:28:E7:D4:9C:FA:4A:A5:98:4F:E4:97:EB:73:48:56:07:87:E4:96 is in the database with reason Little Black Box 0.1.
author = "Mak Kolybabi"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"discovery"}
require("bin")
require("nmap")
require("shortport")
require("stdnse")
local FINGERPRINT_FILE = "ssl-fingerprints.txt"
local SSL_PORTS = {
443,
465,
587,
636,
989,
990,
992,
993,
994,
995,
5061,
6679,
6697,
8443
}
local SSL_SERVICES = {
"ftps",
"ftps-data",
"https",
"https-alt",
"imaps",
"ircs",
"ldapssl",
"pop3s",
"sip-tls",
"smtps",
"telnets"
}
local get_fingerprints = function(path)
-- Check registry for cached fingerprints.
if nmap.registry.ssl_fingerprints then
stdnse.print_debug(1, "Using cached SSL fingerprints.")
return true, nmap.registry.ssl_fingerprints
end
-- Attempt to resolve path if it is relative.
local full_path = nmap.fetchfile("nselib/data/" .. path)
if not full_path then
full_path = path
end
stdnse.print_debug("Loading SSL fingerprints from %s.", full_path)
-- Open database.
local file = io.open(full_path, "r")
if not file then
return false, "Failed to open file " .. full_path
end
-- Parse database.
local fingerprints = {}
while true do
local line = file:read("*line")
if not line then
break
end
line = line:gsub("\n", "")
if line == "" then
break
end
local fields = stdnse.strsplit(",", line)
stdnse.print_debug(3, "Added %s to database with reason %s.", fields[1], fields[2])
fingerprints[fields[1]] = fields[2]
end
-- Close database.
file:close()
-- Cache fingerprints in registry for future runs.
nmap.registry.ssl_fingerprints = fingerprints
return true, fingerprints
end
portrule = shortport.port_or_service(SSL_PORTS, SSL_SERVICES)
action = function(host, port)
-- Get script arguments.
local path = stdnse.get_script_args("ssl-known-key.fingerprintfile") or FINGERPRINT_FILE
local status, result = get_fingerprints(path)
if not status then
stdnse.print_debug(1, result)
return
end
local fingerprints = result
-- Connect to host.
local sock = nmap.new_socket()
local status, err = sock:connect(host, port, "ssl")
if not status then
stdnse.print_debug(1, "Failed to connect: %s", err)
return
end
-- Get SSL certificate.
local cert = sock:get_ssl_certificate()
sock:close()
if not cert:digest("sha1") then
stdnse.print_debug(2, "Certificate does not have a SHA-1 fingerprint.")
return
end
-- Check SSL fingerprint against database.
local fingerprint = stdnse.tohex(cert:digest("sha1"), {separator=":", group=2}):upper()
local reason = fingerprints[fingerprint]
if not reason then
stdnse.print_debug(2, "%s was not in the database.", fingerprint)
return
end
return fingerprint .. " is in the database with the reason " .. reason
end