mirror of
https://github.com/nmap/nmap.git
synced 2025-12-07 21:21:31 +00:00
Converted http-userdir-enum.nse to use my http-enum.nse logic (from http.lua). Also moved the 'displayall' script-arg back into the script, not http.lua, because http-userdir-enum.nse actually wants to find non-200 pages (403 Access Denied, for instance).
This commit is contained in:
@@ -15,10 +15,6 @@
|
|||||||
-- containing the body of the HTTP response.
|
-- containing the body of the HTTP response.
|
||||||
-- @copyright Same as Nmap--See http://nmap.org/book/man-legal.html
|
-- @copyright Same as Nmap--See http://nmap.org/book/man-legal.html
|
||||||
--
|
--
|
||||||
--@args displayall Set to '1' or 'true' to treat status codes other than 200 OK and
|
|
||||||
-- 401 Authentication Required as valid pages. This is generally honoured
|
|
||||||
-- by scripts that search for valid pages, such as http-enum.nse and
|
|
||||||
-- http-userdir-enum.nse. Enabling this will create a lot of false positives.
|
|
||||||
|
|
||||||
|
|
||||||
module(... or "http",package.seeall)
|
module(... or "http",package.seeall)
|
||||||
@@ -1197,8 +1193,10 @@ end
|
|||||||
-- else, this parameter is ignored and can be set to <code>nil</code>. This is returned by
|
-- else, this parameter is ignored and can be set to <code>nil</code>. This is returned by
|
||||||
-- <code>identfy_404</code>.
|
-- <code>identfy_404</code>.
|
||||||
--@param page The page being requested (used in error messages).
|
--@param page The page being requested (used in error messages).
|
||||||
|
--@param displayall [optional] If set to true, "true", or "1", displays all error codes that don't look like a 404 instead
|
||||||
|
-- of just 200 OK and 401 Authentication Required.
|
||||||
--@return A boolean value: true if the page appears to exist, and false if it does not.
|
--@return A boolean value: true if the page appears to exist, and false if it does not.
|
||||||
function page_exists(data, result_404, known_404, page)
|
function page_exists(data, result_404, known_404, page, displayall)
|
||||||
if(data and data.status) then
|
if(data and data.status) then
|
||||||
-- Handle the most complicated case first: the "200 Ok" response
|
-- Handle the most complicated case first: the "200 Ok" response
|
||||||
if(data.status == 200) then
|
if(data.status == 200) then
|
||||||
@@ -1224,11 +1222,9 @@ function page_exists(data, result_404, known_404, page)
|
|||||||
|
|
||||||
if(data.status == 401) then -- "Authentication Required"
|
if(data.status == 401) then -- "Authentication Required"
|
||||||
return true
|
return true
|
||||||
else
|
elseif(displayall == true or displayall == '1' or displayall == "true") then
|
||||||
if(nmap.registry.args.displayall == '1' or nmap.registry.args.displayall == "true") then
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
return false
|
return false
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -31,6 +31,9 @@ for 404 Not Found and the status code returned by the random files).
|
|||||||
-- |_ /x_logo.gif Xerox Phaser Printer
|
-- |_ /x_logo.gif Xerox Phaser Printer
|
||||||
--
|
--
|
||||||
--
|
--
|
||||||
|
--@args displayall Set to '1' or 'true' to display all status codes that may indicate a valid page, not just
|
||||||
|
-- "200 OK" and "401 Authentication Required" pages. Although this is more likely to find certain
|
||||||
|
-- hidden folders, it also generates far more false positives.
|
||||||
--@args limit Limit the number of folders to check. This option is useful if using a list from, for example,
|
--@args limit Limit the number of folders to check. This option is useful if using a list from, for example,
|
||||||
-- the DirBuster projects which can have 80,000+ entries.
|
-- the DirBuster projects which can have 80,000+ entries.
|
||||||
|
|
||||||
@@ -169,7 +172,7 @@ action = function(host, port)
|
|||||||
end
|
end
|
||||||
|
|
||||||
for i, data in pairs(results) do
|
for i, data in pairs(results) do
|
||||||
if(http.page_exists(data, result_404, known_404, URLs[i].checkdir)) then
|
if(http.page_exists(data, result_404, known_404, URLs[i].checkdir, nmap.registry.args.displayall)) then
|
||||||
if(URLs[i].checkdesc) then
|
if(URLs[i].checkdesc) then
|
||||||
stdnse.print_debug(1, "http-enum.nse: Found a valid page! (%s: %s)", URLs[i].checkdir, URLs[i].checkdesc)
|
stdnse.print_debug(1, "http-enum.nse: Found a valid page! (%s: %s)", URLs[i].checkdir, URLs[i].checkdesc)
|
||||||
response = response .. URLs[i].checkdir .. " " .. URLs[i].checkdesc .. "\n"
|
response = response .. URLs[i].checkdir .. " " .. URLs[i].checkdesc .. "\n"
|
||||||
|
|||||||
@@ -22,6 +22,9 @@ Ref: CVE-2001-1013 http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2001-1013
|
|||||||
-- @args
|
-- @args
|
||||||
-- users=path/to/custom/usernames.list or
|
-- users=path/to/custom/usernames.list or
|
||||||
-- userdir.users=path/to/custom/usernames.list
|
-- userdir.users=path/to/custom/usernames.list
|
||||||
|
--@args limit Limit the number of users to check. This option is useful if using a list from, for example,
|
||||||
|
-- the DirBuster projects which can have 80,000+ entries.
|
||||||
|
|
||||||
--
|
--
|
||||||
-- @output
|
-- @output
|
||||||
-- 80/tcp open http syn-ack Apache httpd 2.2.9
|
-- 80/tcp open http syn-ack Apache httpd 2.2.9
|
||||||
@@ -56,43 +59,88 @@ end
|
|||||||
|
|
||||||
action = function(host, port)
|
action = function(host, port)
|
||||||
|
|
||||||
if not nmap.registry.userdir then init() end
|
if(not nmap.registry.userdir) then
|
||||||
|
init()
|
||||||
|
end
|
||||||
local usernames = nmap.registry.userdir
|
local usernames = nmap.registry.userdir
|
||||||
if #usernames == 0 then return nil end -- speedy exit if no usernames
|
|
||||||
|
|
||||||
local filename = filename:match( "[\\/]([^\\/]+)\.nse$" )
|
-- speedy exit if no usernames
|
||||||
local hname = host.targetname or ( host.name ~= '' and host.name ) or host.ip
|
if(#usernames == 0) then
|
||||||
local found = {}
|
if(nmap.debugging() > 0) then
|
||||||
|
return "Didn't find any users to test (should be in nselib/data/usernames.lst)"
|
||||||
for i, uname in ipairs(usernames) do
|
|
||||||
|
|
||||||
local data = http.get( host, port, ("/~%s/"):format(uname) )
|
|
||||||
if data and type(data.status) == 'number' then
|
|
||||||
if (data.status == 403 or data.status == 200) and i == 1 then
|
|
||||||
-- This server is unlikely to yield useful information since it returned
|
|
||||||
-- 200 or 403 to a request for a directory which is highly unlikely to exist.
|
|
||||||
stdnse.print_debug(1, "%s detected false positives at %s:%d - status was %d",
|
|
||||||
filename, hname, port.number, data.status)
|
|
||||||
break
|
|
||||||
elseif data.status == 403 or data.status == 200 then
|
|
||||||
found[#found+1] = ("%s (%d)"):format(uname, data.status)
|
|
||||||
-- else we didn't get an interesting status code
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
stdnse.print_debug(2, "%s got a bad or zero response from %s:%d",
|
|
||||||
filename, hname, port.number)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
if #found == 0 then
|
|
||||||
stdnse.print_debug(2, "%s found Zero users at %s:%d",
|
|
||||||
filename, hname, port.number)
|
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
return ("Potential Users: %s"):format(table.concat(found, ", "))
|
-- Check what response we get for a 404
|
||||||
|
local result, result_404, known_404 = http.identify_404(host, port)
|
||||||
|
if(result == false) then
|
||||||
|
if(nmap.debugging() > 0) then
|
||||||
|
return "ERROR: " .. result_404
|
||||||
|
else
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check if we can use HEAD requests
|
||||||
|
local use_head = http.can_use_head(host, port, result_404)
|
||||||
|
|
||||||
|
-- If we can't use HEAD, make sure we can use GET requests
|
||||||
|
if(use_head == false) then
|
||||||
|
local result, err = http.can_use_get(host, port)
|
||||||
|
if(result == false) then
|
||||||
|
if(nmap.debugging() > 0) then
|
||||||
|
return "ERROR: " .. err
|
||||||
|
else
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Queue up the checks
|
||||||
|
local all = {}
|
||||||
|
local i
|
||||||
|
for i = 1, #usernames, 1 do
|
||||||
|
if(nmap.registry.args.limit and i > tonumber(nmap.registry.args.limit)) then
|
||||||
|
stdnse.print_debug(1, "http-userdir-enum.nse: Reached the limit (%d), stopping", nmap.registry.args.limit)
|
||||||
|
break;
|
||||||
|
end
|
||||||
|
|
||||||
|
if(use_head) then
|
||||||
|
all = http.pHead(host, port, "/~" .. usernames[i], nil, nil, all)
|
||||||
|
else
|
||||||
|
all = http.pGet(host, port, "/~" .. usernames[i], nil, nil, all)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local results = http.pipeline(host, port, all, nil)
|
||||||
|
|
||||||
|
-- Check for http.pipeline error
|
||||||
|
if(results == nil) then
|
||||||
|
stdnse.print_debug(1, "http-userdir-enum.nse: http.pipeline returned nil")
|
||||||
|
if(nmap.debugging() > 0) then
|
||||||
|
return "ERROR: http.pipeline returned nil"
|
||||||
|
else
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local found = {}
|
||||||
|
for i, data in pairs(results) do
|
||||||
|
if(http.page_exists(data, result_404, known_404, "/~" .. usernames[i], true)) then
|
||||||
|
stdnse.print_debug(1, "http-userdir-enum.nse: Found a valid user: %s", usernames[i])
|
||||||
|
table.insert(found, usernames[i])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if(#found > 0) then
|
||||||
|
return string.format("Potential Users: %s", table.concat(found, ", "))
|
||||||
|
elseif(nmap.debugging() > 0) then
|
||||||
|
return "Didn't find any users!"
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -117,8 +165,8 @@ function init()
|
|||||||
nmap.registry.userdir = {}
|
nmap.registry.userdir = {}
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
-- random dummy username to catch false positives
|
-- random dummy username to catch false positives (not necessary)
|
||||||
if #usernames > 0 then table.insert(usernames, 1, randomstring()) end
|
-- if #usernames > 0 then table.insert(usernames, 1, randomstring()) end
|
||||||
nmap.registry.userdir = usernames
|
nmap.registry.userdir = usernames
|
||||||
stdnse.print_debug(1, "%s Testing %d usernames.", filename, #usernames)
|
stdnse.print_debug(1, "%s Testing %d usernames.", filename, #usernames)
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
Reference in New Issue
Block a user