1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-07 13:11:28 +00:00
Files
nmap/scripts/ssl-known-key.nse

138 lines
3.6 KiB
Lua

-- -*- 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 = {"safe", "discovery", "vuln"}
require("bin")
require("nmap")
require("shortport")
require("stdnse")
local FINGERPRINT_FILE = "ssl-fingerprints"
local get_fingerprints = function(path)
local pretty = function(key)
local s = key:sub(1, 2)
for i = 3, 40, 2 do
s = s .. ":" .. key:sub(i, i + 1)
end
return s:upper()
end
-- Check registry for cached fingerprints.
if nmap.registry.ssl_fingerprints then
stdnse.print_debug(2, "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(2, "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 section = nil
local fingerprints = {}
for line in file:lines() do
line = line:gsub("#.*", "")
line = line:gsub("^%s*", "")
line = line:gsub("%s*$", "")
if line ~= "" then
if line:sub(1,1) == "[" then
-- Start a new section.
line = line:sub(2, #line - 1)
stdnse.print_debug(4, "Starting new section %s.", line)
section = line
elseif section ~= nil then
-- Add fingerprint to section.
line = pretty(line)
stdnse.print_debug(4, "Added key %s to database.", line)
fingerprints[line] = section
else
-- Key found outside of section.
stdnse.print_debug(1, "Key %s is not in a section.", pretty(line))
end
end
end
-- Close database.
file:close()
-- Cache fingerprints in registry for future runs.
nmap.registry.ssl_fingerprints = fingerprints
return true, fingerprints
end
portrule = shortport.ssl
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 section = fingerprints[fingerprint]
if not section then
stdnse.print_debug(2, "%s was not in the database.", fingerprint)
return
end
return "Found in " .. section .. " (certificate hash: " .. fingerprint .. ")"
end