1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-11 02:09:03 +00:00

Added a 'path' script-arg to http-headers.nse. Changed it to use 'HEAD' by default, and fail to using 'GET' the same way other scripts do (also added a 'useget' script-arg to turn it off). Also fixed some print_debugs in http.lua that were prefixed with 'http-enum.nse:'.

This commit is contained in:
ron
2009-08-27 15:39:17 +00:00
parent fc2b575fba
commit 62dedb9dc1
2 changed files with 63 additions and 33 deletions

View File

@@ -1128,39 +1128,48 @@ end
--
--@param host The host object.
--@param port The port to use -- note that SSL will automatically be used, if necessary.
--@param result_404 [optional] The result when an unknown page is requested. This is returned by <code>identify_404</code>.
-- If the 404 page returns a '200' code, then we disable HEAD requests.
--@param result_404 [optional] The result when an unknown page is requested. This is returned by
-- <code>identify_404</code>. If the 404 page returns a '200' code, then we
-- disable HEAD requests.
--@param path [optional] The path to request; by default, '/' is used.
--@return A boolean value: true if HEAD is usable, false otherwise.
function can_use_head(host, port, result_404)
--@return If HEAD is usable, the result of the HEAD request is returned (so potentially, a script can
-- avoid an extra call to HEAD
function can_use_head(host, port, result_404, path)
-- If the 404 result is 200, don't use HEAD.
if(result_404 == 200) then
return false
end
-- Default path
if(path == nil) then
path = '/'
end
-- Perform a HEAD request and see what happens.
local data = http.head( host, port, '/' )
local data = http.head( host, port, path )
if data then
if data.status and data.status == 302 and data.header and data.header.location then
stdnse.print_debug(1, "http-enum.nse: Warning: Host returned 302 and not 200 when performing HEAD.")
stdnse.print_debug(1, "HTTP: Warning: Host returned 302 and not 200 when performing HEAD.")
return false
end
if data.status and data.status == 200 and data.header then
-- check that a body wasn't returned
if string.len(data.body) > 0 then
stdnse.print_debug(1, "http-enum.nse: Warning: Host returned data when performing HEAD.")
stdnse.print_debug(1, "HTTP: Warning: Host returned data when performing HEAD.")
return false
end
stdnse.print_debug(1, "http-enum.nse: Host supports HEAD.")
return true
stdnse.print_debug(1, "HTTP: Host supports HEAD.")
return true, data
end
stdnse.print_debug(1, "http-enum.nse: Didn't receive expected response to HEAD request (got %s).", get_status_string(data))
stdnse.print_debug(1, "HTTP: Didn't receive expected response to HEAD request (got %s).", get_status_string(data))
return false
end
stdnse.print_debug(1, "http-enum.nse: HEAD request completely failed.")
stdnse.print_debug(1, "HTTP: HEAD request completely failed.")
return false
end
@@ -1278,17 +1287,17 @@ function identify_404(host, port)
data = http.get(host, port, URL_404_1)
if(data == nil) then
stdnse.print_debug(1, "http-enum.nse: Failed while testing for 404 status code")
stdnse.print_debug(1, "HTTP: Failed while testing for 404 status code")
return false, "Failed while testing for 404 error message"
end
if(data.status and data.status == 404) then
stdnse.print_debug(1, "http-enum.nse: Host returns proper 404 result.")
stdnse.print_debug(1, "HTTP: Host returns proper 404 result.")
return true, 404
end
if(data.status and data.status == 200) then
stdnse.print_debug(1, "http-enum.nse: Host returns 200 instead of 404.")
stdnse.print_debug(1, "HTTP: Host returns 200 instead of 404.")
-- Clean up the body (for example, remove the URI). This makes it easier to validate later
if(data.body) then
@@ -1296,7 +1305,7 @@ function identify_404(host, port)
local data2 = http.get(host, port, URL_404_2)
local data3 = http.get(host, port, URL_404_3)
if(data2 == nil or data3 == nil) then
stdnse.print_debug(1, "http-enum.nse: Failed while testing for extra 404 error messages")
stdnse.print_debug(1, "HTTP: Failed while testing for extra 404 error messages")
return false, "Failed while testing for extra 404 error messages"
end
@@ -1305,7 +1314,7 @@ function identify_404(host, port)
if(data2.status == nil) then
data2.status = "<unknown>"
end
stdnse.print_debug(1, "http-enum.nse: HTTP 404 status changed for second request (became %d).", data2.status)
stdnse.print_debug(1, "HTTP: HTTP 404 status changed for second request (became %d).", data2.status)
return false, string.format("HTTP 404 status changed for second request (became %d).", data2.status)
end
@@ -1314,7 +1323,7 @@ function identify_404(host, port)
if(data3.status == nil) then
data3.status = "<unknown>"
end
stdnse.print_debug(1, "http-enum.nse: HTTP 404 status changed for third request (became %d).", data3.status)
stdnse.print_debug(1, "HTTP: HTTP 404 status changed for third request (became %d).", data3.status)
return false, string.format("HTTP 404 status changed for third request (became %d).", data3.status)
end
@@ -1323,28 +1332,28 @@ function identify_404(host, port)
local clean_body2 = clean_404(data2.body)
local clean_body3 = clean_404(data3.body)
if(clean_body ~= clean_body2) then
stdnse.print_debug(1, "http-enum.nse: Two known 404 pages returned valid and different pages; unable to identify valid response.")
stdnse.print_debug(1, "http-enum.nse: If you investigate the server and it's possible to clean up the pages, please post to nmap-dev mailing list.")
stdnse.print_debug(1, "HTTP: Two known 404 pages returned valid and different pages; unable to identify valid response.")
stdnse.print_debug(1, "HTTP: If you investigate the server and it's possible to clean up the pages, please post to nmap-dev mailing list.")
return false, string.format("Two known 404 pages returned valid and different pages; unable to identify valid response.")
end
if(clean_body ~= clean_body3) then
stdnse.print_debug(1, "http-enum.nse: Two known 404 pages returned valid and different pages; unable to identify valid response (happened when checking a folder).")
stdnse.print_debug(1, "http-enum.nse: If you investigate the server and it's possible to clean up the pages, please post to nmap-dev mailing list.")
stdnse.print_debug(1, "HTTP: Two known 404 pages returned valid and different pages; unable to identify valid response (happened when checking a folder).")
stdnse.print_debug(1, "HTTP: If you investigate the server and it's possible to clean up the pages, please post to nmap-dev mailing list.")
return false, string.format("Two known 404 pages returned valid and different pages; unable to identify valid response (happened when checking a folder).")
end
return true, 200, clean_body
end
stdnse.print_debug(1, "http-enum.nse: The 200 response didn't contain a body.")
stdnse.print_debug(1, "HTTP: The 200 response didn't contain a body.")
return true, 200
end
-- Loop through any expected error codes
for _,code in pairs(bad_responses) do
if(data.status and data.status == code) then
stdnse.print_debug(1, "http-enum.nse: Host returns %s instead of 404 File Not Found.", get_status_string(data))
stdnse.print_debug(1, "HTTP: Host returns %s instead of 404 File Not Found.", get_status_string(data))
return true, code
end
end
@@ -1376,17 +1385,17 @@ function page_exists(data, result_404, known_404, page, displayall)
-- If the 404 response is also "200", deal with it (check if the body matches)
if(string.len(data.body) == 0) then
-- I observed one server that returned a blank string instead of an error, on some occasions
stdnse.print_debug(1, "http-enum.nse: Page returned a totally empty body; page likely doesn't exist")
stdnse.print_debug(1, "HTTP: Page returned a totally empty body; page likely doesn't exist")
return false
elseif(clean_404(data.body) ~= known_404) then
stdnse.print_debug(1, "http-enum.nse: Page returned a body that doesn't match known 404 body, therefore it exists (%s)", page)
stdnse.print_debug(1, "HTTP: Page returned a body that doesn't match known 404 body, therefore it exists (%s)", page)
return true
else
return false
end
else
-- If 404s return something other than 200, and we got a 200, we're good to go
stdnse.print_debug(1, "http-enum.nse: Page was '%s', it exists! (%s)", get_status_string(data), page)
stdnse.print_debug(1, "HTTP: Page was '%s', it exists! (%s)", get_status_string(data), page)
return true
end
else
@@ -1394,7 +1403,7 @@ function page_exists(data, result_404, known_404, page, displayall)
if(data.status ~= 404 and data.status ~= result_404) then
-- If this check succeeded, then the page isn't a standard 404 -- it could be a redirect, authentication request, etc. Unless the user
-- asks for everything (with a script argument), only display 401 Authentication Required here.
stdnse.print_debug(1, "http-enum.nse: Page didn't match the 404 response (%s) (%s)", get_status_string(data), page)
stdnse.print_debug(1, "HTTP: Page didn't match the 404 response (%s) (%s)", get_status_string(data), page)
if(data.status == 401) then -- "Authentication Required"
return true
@@ -1409,7 +1418,7 @@ function page_exists(data, result_404, known_404, page, displayall)
end
end
else
stdnse.print_debug(1, "http-enum.nse: HTTP request failed (is the host still up?)")
stdnse.print_debug(1, "HTTP: HTTP request failed (is the host still up?)")
return false
end
end

View File

@@ -17,7 +17,8 @@ Does a GET request for the root folder ("/"), and displays the HTTP headers retu
-- | last-modified: Mon, 19 May 2008 04:49:49 GMT
-- |_ server: Apache/2.2.2 (Fedora)
--
--
--@arg path The path to request, such as '/index.php'. Default: '/'.
--@arg useget Set to force GET requests instead of HEAD.
author = "Ron Bowes <ron@skullsecurity.org>"
@@ -45,25 +46,45 @@ portrule = function(host, port)
end
action = function(host, port)
local result = http.get(host, port, "/")
local path = nmap.registry.args.path
local request_type = "HEAD"
if(path == nil) then
path = '/'
end
local status = false
local result
-- Check if the user didn't want HEAD to be used
if(nmap.registry.args.useget == nil) then
-- Try using HEAD first
status, result = http.can_use_head(host, port, path)
end
-- If head failed, try using GET
if(status == false) then
stdnse.print_debug(1, "http-headers.nse: HEAD request failed, falling back to GET")
result = http.get(host, port, path)
request_type = "GET"
end
if(result == nil) then
if(nmap.debugging() > 0) then
return "ERROR: GET request failed"
return "ERROR: Header request failed"
else
return nil
end
end
if(result.header == nil) then
if(result.rawheader == nil) then
if(nmap.debugging() > 0) then
return "ERROR: GET request didn't return a proper header"
return "ERROR: Header request didn't return a proper header"
else
return nil
end
end
local response = " \n"
local response = "(" .. request_type .. " used)\n"
for _, header in pairs(result.rawheader) do
response = response .. header .. "\n"
end