mirror of
https://github.com/nmap/nmap.git
synced 2025-12-06 12:41:29 +00:00
Load http fingerprints only once
This commit is contained in:
@@ -171,6 +171,13 @@ local function get_variations(filename)
|
|||||||
return variations
|
return variations
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- simplify unlocking the mutex, ensuring we don't try to parse again, and returning an error.
|
||||||
|
local function bad_prints(mutex, err)
|
||||||
|
nmap.registry.http_fingerprints = err
|
||||||
|
mutex "done"
|
||||||
|
return false, err
|
||||||
|
end
|
||||||
|
|
||||||
---Get the list of fingerprints from files. The files are defined in <code>fingerprint_files</code>. If category
|
---Get the list of fingerprints from files. The files are defined in <code>fingerprint_files</code>. If category
|
||||||
-- is non-nil, only choose scripts that are in that category.
|
-- is non-nil, only choose scripts that are in that category.
|
||||||
--
|
--
|
||||||
@@ -181,11 +188,16 @@ local function get_fingerprints(fingerprint_file, category)
|
|||||||
local total_count = 0 -- Used for 'limit'
|
local total_count = 0 -- Used for 'limit'
|
||||||
|
|
||||||
-- Check if we've already read the file
|
-- Check if we've already read the file
|
||||||
-- There might be a race condition here, where multiple scripts will read the file and set this variable, but the impact
|
local mutex = nmap.mutex("http_fingerprints")
|
||||||
-- of that would be minimal (and definitely isn't security)
|
mutex "lock"
|
||||||
if(nmap.registry.http_fingerprints ~= nil) then
|
if nmap.registry.http_fingerprints then
|
||||||
stdnse.debug1("Using cached HTTP fingerprints")
|
if type(nmap.registry.http_fingerprints) == "table" then
|
||||||
return nmap.registry.http_fingerprints
|
stdnse.debug1("Using cached HTTP fingerprints")
|
||||||
|
mutex "done"
|
||||||
|
return true, nmap.registry.http_fingerprints
|
||||||
|
else
|
||||||
|
return bad_prints(mutex, nmap.registry.http_fingerprints)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Try and find the file; if it isn't in Nmap's directories, take it as a direct path
|
-- Try and find the file; if it isn't in Nmap's directories, take it as a direct path
|
||||||
@@ -199,7 +211,7 @@ local function get_fingerprints(fingerprint_file, category)
|
|||||||
local file = loadfile(filename_full, "t", env)
|
local file = loadfile(filename_full, "t", env)
|
||||||
if(not(file)) then
|
if(not(file)) then
|
||||||
stdnse.debug1("Couldn't load configuration file: %s", filename_full)
|
stdnse.debug1("Couldn't load configuration file: %s", filename_full)
|
||||||
return false, "Couldn't load fingerprint file: " .. filename_full
|
return bad_prints(mutex, "Couldn't load fingerprint file: " .. filename_full)
|
||||||
end
|
end
|
||||||
|
|
||||||
file()
|
file()
|
||||||
@@ -211,14 +223,14 @@ local function get_fingerprints(fingerprint_file, category)
|
|||||||
for i, fingerprint in pairs(fingerprints) do
|
for i, fingerprint in pairs(fingerprints) do
|
||||||
-- Make sure we have a valid index
|
-- Make sure we have a valid index
|
||||||
if(type(i) ~= 'number') then
|
if(type(i) ~= 'number') then
|
||||||
return false, "The 'fingerprints' table is an array, not a table; all indexes should be numeric"
|
return bad_prints(mutex, "The 'fingerprints' table is an array, not a table; all indexes should be numeric")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Make sure they have either a string or a table of probes
|
-- Make sure they have either a string or a table of probes
|
||||||
if(not(fingerprint.probes) or
|
if(not(fingerprint.probes) or
|
||||||
(type(fingerprint.probes) ~= 'table' and type(fingerprint.probes) ~= 'string') or
|
(type(fingerprint.probes) ~= 'table' and type(fingerprint.probes) ~= 'string') or
|
||||||
(type(fingerprint.probes) == 'table' and #fingerprint.probes == 0)) then
|
(type(fingerprint.probes) == 'table' and #fingerprint.probes == 0)) then
|
||||||
return false, "Invalid path found for fingerprint " .. i
|
return bad_prints(mutex, "Invalid path found for fingerprint " .. i)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Make sure fingerprint.path is a table
|
-- Make sure fingerprint.path is a table
|
||||||
@@ -230,7 +242,7 @@ local function get_fingerprints(fingerprint_file, category)
|
|||||||
for i, probe in pairs(fingerprint.probes) do
|
for i, probe in pairs(fingerprint.probes) do
|
||||||
-- Make sure we have a valid index
|
-- Make sure we have a valid index
|
||||||
if(type(i) ~= 'number') then
|
if(type(i) ~= 'number') then
|
||||||
return false, "The 'probes' table is an array, not a table; all indexes should be numeric"
|
return bad_prints(mutex, "The 'probes' table is an array, not a table; all indexes should be numeric")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Convert the probe to a table if it's a string
|
-- Convert the probe to a table if it's a string
|
||||||
@@ -241,7 +253,7 @@ local function get_fingerprints(fingerprint_file, category)
|
|||||||
|
|
||||||
-- Make sure the probes table has a 'path'
|
-- Make sure the probes table has a 'path'
|
||||||
if(not(probe['path'])) then
|
if(not(probe['path'])) then
|
||||||
return false, "The 'probes' table requires each element to have a 'path'."
|
return bad_prints(mutex, "The 'probes' table requires each element to have a 'path'.")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- If they didn't set a method, set it to 'GET'
|
-- If they didn't set a method, set it to 'GET'
|
||||||
@@ -251,35 +263,35 @@ local function get_fingerprints(fingerprint_file, category)
|
|||||||
|
|
||||||
-- Make sure the method's a string
|
-- Make sure the method's a string
|
||||||
if(type(probe['method']) ~= 'string') then
|
if(type(probe['method']) ~= 'string') then
|
||||||
return false, "The 'method' in the probes file has to be a string"
|
return bad_prints(mutex, "The 'method' in the probes file has to be a string")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Ensure that matches is an array
|
-- Ensure that matches is an array
|
||||||
if(type(fingerprint.matches) ~= 'table') then
|
if(type(fingerprint.matches) ~= 'table') then
|
||||||
return false, "'matches' field has to be a table"
|
return bad_prints(mutex, "'matches' field has to be a table")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Loop through the matches
|
-- Loop through the matches
|
||||||
for i, match in pairs(fingerprint.matches) do
|
for i, match in pairs(fingerprint.matches) do
|
||||||
-- Make sure we have a valid index
|
-- Make sure we have a valid index
|
||||||
if(type(i) ~= 'number') then
|
if(type(i) ~= 'number') then
|
||||||
return false, "The 'matches' table is an array, not a table; all indexes should be numeric"
|
return bad_prints(mutex, "The 'matches' table is an array, not a table; all indexes should be numeric")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Check that every element in the table is an array
|
-- Check that every element in the table is an array
|
||||||
if(type(match) ~= 'table') then
|
if(type(match) ~= 'table') then
|
||||||
return false, "Every element of 'matches' field has to be a table"
|
return bad_prints(mutex, "Every element of 'matches' field has to be a table")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Check the output field
|
-- Check the output field
|
||||||
if(match['output'] == nil or type(match['output']) ~= 'string') then
|
if(match['output'] == nil or type(match['output']) ~= 'string') then
|
||||||
return false, "The 'output' field in 'matches' has to be present and a string"
|
return bad_prints(mutex, "The 'output' field in 'matches' has to be present and a string")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Check the 'match' and 'dontmatch' fields, if present
|
-- Check the 'match' and 'dontmatch' fields, if present
|
||||||
if((match['match'] and type(match['match']) ~= 'string') or (match['dontmatch'] and type(match['dontmatch']) ~= 'string')) then
|
if((match['match'] and type(match['match']) ~= 'string') or (match['dontmatch'] and type(match['dontmatch']) ~= 'string')) then
|
||||||
return false, "The 'match' and 'dontmatch' fields in 'matches' have to be strings, if they exist"
|
return bad_prints(mutex, "The 'match' and 'dontmatch' fields in 'matches' have to be strings, if they exist")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Change blank 'match' strings to '.*' so they match everything
|
-- Change blank 'match' strings to '.*' so they match everything
|
||||||
@@ -290,22 +302,22 @@ local function get_fingerprints(fingerprint_file, category)
|
|||||||
|
|
||||||
-- Make sure the severity is an integer between 1 and 4. Default it to 1.
|
-- Make sure the severity is an integer between 1 and 4. Default it to 1.
|
||||||
if(fingerprint.severity and (type(fingerprint.severity) ~= 'number' or fingerprint.severity < 1 or fingerprint.severity > 4)) then
|
if(fingerprint.severity and (type(fingerprint.severity) ~= 'number' or fingerprint.severity < 1 or fingerprint.severity > 4)) then
|
||||||
return false, "The 'severity' field has to be an integer between 1 and 4"
|
return bad_prints(mutex, "The 'severity' field has to be an integer between 1 and 4")
|
||||||
else
|
else
|
||||||
fingerprint.severity = 1
|
fingerprint.severity = 1
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Make sure ignore_404 is a boolean. Default it to false.
|
-- Make sure ignore_404 is a boolean. Default it to false.
|
||||||
if(fingerprint.ignore_404 and type(fingerprint.ignore_404) ~= 'boolean') then
|
if(fingerprint.ignore_404 and type(fingerprint.ignore_404) ~= 'boolean') then
|
||||||
return false, "The 'ignore_404' field has to be a boolean"
|
return bad_prints(mutex, "The 'ignore_404' field has to be a boolean")
|
||||||
else
|
else
|
||||||
fingerprint.ignore_404 = false
|
fingerprint.ignore_404 = false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Make sure we have some fingerprints fingerprints
|
-- Make sure we have some fingerprints
|
||||||
if(#fingerprints == 0) then
|
if(#fingerprints == 0) then
|
||||||
return false, "No fingerprints were loaded"
|
return bad_prints(mutex, "No fingerprints were loaded")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- If the user wanted to filter by category, do it
|
-- If the user wanted to filter by category, do it
|
||||||
@@ -321,7 +333,7 @@ local function get_fingerprints(fingerprint_file, category)
|
|||||||
|
|
||||||
-- Make sure we still have fingerprints after the category filter
|
-- Make sure we still have fingerprints after the category filter
|
||||||
if(#fingerprints == 0) then
|
if(#fingerprints == 0) then
|
||||||
return false, "No fingerprints matched the given category (" .. category .. ")"
|
return bad_prints(mutex, "No fingerprints matched the given category (" .. category .. ")")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -345,7 +357,8 @@ local function get_fingerprints(fingerprint_file, category)
|
|||||||
-- end
|
-- end
|
||||||
|
|
||||||
-- Cache the fingerprints for other scripts, so we aren't reading the files every time
|
-- Cache the fingerprints for other scripts, so we aren't reading the files every time
|
||||||
-- nmap.registry.http_fingerprints = fingerprints
|
nmap.registry.http_fingerprints = fingerprints
|
||||||
|
mutex "done"
|
||||||
|
|
||||||
return true, fingerprints
|
return true, fingerprints
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user