mirror of
https://github.com/nmap/nmap.git
synced 2025-12-09 06:01:28 +00:00
[NSE] Added a feature that integrates Nikto's large db to our http-fingerprint file on runtime. http://seclists.org/nmap-dev/2013/q4/292
This commit is contained in:
@@ -12,6 +12,18 @@ local table = require "table"
|
||||
-- This file is released under the Nmap license; see:
|
||||
-- http://nmap.org/book/man-legal.html
|
||||
--
|
||||
-- @args http-fingerprints.nikto-db-path Looks at the given path for nikto database.
|
||||
-- It then converts the records in nikto's database into our Lua table format
|
||||
-- and adds them to our current fingerprints if they don't exist already.
|
||||
-- Unfortunately, our current implementation has some limitations:
|
||||
-- * It doesn't support records with more than one 'dontmatch' patterns for
|
||||
-- a probe.
|
||||
-- * It doesn't support logical AND for the 'match' patterns.
|
||||
-- * It doesn't support sending additional headers for a probe.
|
||||
-- That means, if a nikto fingerprint needs one of the above features, it
|
||||
-- won't be loaded. At the time of writing this, 6546 out of the 6573 Nikto
|
||||
-- fingerprints are being loaded successfully.
|
||||
--
|
||||
-- Although this format was originally modeled after the Nikto format, that ended
|
||||
-- up being too restrictive. The current format is a simple Lua table. There are many
|
||||
-- advantages to this technique; it's powerful, we don't need to write custom parsing
|
||||
@@ -63,11 +75,11 @@ local table = require "table"
|
||||
-- The text to output if this match happens. If the 'match' field contains captures, these
|
||||
-- captures can be used with \1, \2, etc.
|
||||
--
|
||||
--
|
||||
-- If you have any questions, feel free to email dev@nmap.org or contact Ron Bowes!
|
||||
--
|
||||
-- CHANGELOG:
|
||||
-- Added 120 new signatures taken from exploit-db.com archives from July 2009 to July 2011 [Paulino Calderon]
|
||||
-- Added the option to read nikto's database and make use of its fingerprints. [George Chatzisofroniou]
|
||||
--
|
||||
|
||||
fingerprints = {};
|
||||
@@ -11830,3 +11842,99 @@ table.insert(fingerprints, {
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
local stdnse = require "stdnse"
|
||||
local nmap = require "nmap"
|
||||
|
||||
nikto_db_path = stdnse.get_script_args("http-fingerprints.nikto-db-path") or "db_tests"
|
||||
local f = nmap.fetchfile(nikto_db_path) or io.open(nikto_db_path, "r")
|
||||
|
||||
if f then
|
||||
|
||||
stdnse.print_debug(1, "Found nikto db.")
|
||||
|
||||
local nikto_db = {}
|
||||
for l in io.lines(nikto_db_path) do
|
||||
|
||||
-- Skip comments.
|
||||
if not string.match(l, "^#.*") then
|
||||
|
||||
record = {}
|
||||
|
||||
for field in string.gmatch(l, "\"(.-)\",") do
|
||||
|
||||
-- Grab every attribute and create a record.
|
||||
if field then
|
||||
string.gsub(field, '%%', '%%%%')
|
||||
table.insert(record, field)
|
||||
end
|
||||
end
|
||||
|
||||
-- Make sure this record doesn't exists already.
|
||||
local exists = false
|
||||
for _, f in pairs(fingerprints) do
|
||||
if f.probes then
|
||||
for __, p in pairs(f.probes) do
|
||||
if p.path then
|
||||
if p.path == record[4] then
|
||||
exists = true
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- What we have right now, is the following record:
|
||||
-- record[1]: Nikto test ID
|
||||
-- record[2]: OSVDB-ID
|
||||
-- record[3]: Server Type
|
||||
-- record[4]: URI
|
||||
-- record[5]: HTTP Method
|
||||
-- record[6]: Match 1
|
||||
-- record[7]: Match 1 (Or)
|
||||
-- record[8]: Match1 (And)
|
||||
-- record[9]: Fail 1
|
||||
-- record[10]: Fail 2
|
||||
-- record[11]: Summary
|
||||
-- record[12]: HTTP Data
|
||||
-- record[13]: Headers
|
||||
|
||||
-- Is this a valid record? Atm, with our current format we need
|
||||
-- to skip some nikto records. See NSEDoc for more info.
|
||||
|
||||
if not exists
|
||||
and record[4]
|
||||
and record[8] == "" and record[10] == "" and record[12] == ""
|
||||
and (tonumber(record[4]) == nil or (tonumber(record[4]) and record[4] == "200")) then
|
||||
|
||||
-- Our current format does not support HTTP code matching.
|
||||
if record[6] == "200" then record[6] = "" end
|
||||
|
||||
nikto_fingerprint = { category = "nikto",
|
||||
probes = {
|
||||
{
|
||||
path = record[4],
|
||||
method = record[5]
|
||||
}
|
||||
},
|
||||
matches = {
|
||||
{
|
||||
dontmatch = record[9],
|
||||
match = record[6],
|
||||
output = record[11]
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
-- If there is a second match, add it.
|
||||
if record[7] and record[7] ~= "" then
|
||||
table.insert(nikto_fingerprint.matches, { match = record[7], output = record[11] })
|
||||
end
|
||||
|
||||
table.insert(fingerprints, nikto_fingerprint)
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -13,6 +13,10 @@ This parses a fingerprint file that's formatted in a way that's compatible with
|
||||
scanner. This script, however, takes it one step further by building in advanced pattern matching as well
|
||||
as having the ability to identify specific versions of Web applications.
|
||||
|
||||
You can, however, parse the nikto database using http-fingerprints.nikto-db-path. This will try to parse
|
||||
most of the fingerprints defined in nikto's database in real time. More documentation about this in the
|
||||
nselib/data/http-fingerprints file.
|
||||
|
||||
Currently, the database can be found under Nmap's directory in the nselib/data folder. The file is called
|
||||
http-fingerprints and has a long description of its functionality in the file header.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user