diff --git a/scripts/http-favicon.nse b/scripts/http-favicon.nse index aa5722a34..c645cca29 100644 --- a/scripts/http-favicon.nse +++ b/scripts/http-favicon.nse @@ -27,7 +27,7 @@ a favicon points to a different host or port, it is ignored. -- -- @usage -- nmap --script=http-favicon.nse \ --- --script-args favicon.root=,favicon.uri= +-- --script-args favicon.root=,favicon.uri= -- @output -- |_ http-favicon: Socialtext @@ -56,124 +56,124 @@ action = function(host, port) status, favicondb = datafiles.parse_file( favicondbfile, {["^%s*([^%s#:]+)[%s:]+"] = "^%s*[^%s#:]+[%s:]+(.*)"}) if not status then - stdnse.print_debug( 1, "Could not open file: %s", favicondbfile ) - return + stdnse.print_debug( 1, "Could not open file: %s", favicondbfile ) + return end if(stdnse.get_script_args('favicon.root')) then - root = stdnse.get_script_args('favicon.root') + root = stdnse.get_script_args('favicon.root') end local favicon_uri = stdnse.get_script_args("favicon.uri") if(favicon_uri) then - -- If we got a script arg URI, always use that. - answer = http.get( host, port, root .. "/" .. favicon_uri) - stdnse.print_debug( 4, "Using URI %s", favicon_uri) + -- If we got a script arg URI, always use that. + answer = http.get( host, port, root .. "/" .. favicon_uri) + stdnse.print_debug( 4, "Using URI %s", favicon_uri) else - -- Otherwise, first try parsing the home page. - index = http.get( host, port, root .. "/" ) - if index.status == 200 or index.status == 503 then - -- find the favicon pattern - icon = parseIcon( index.body ) - -- if we find a pattern - if icon then - local hostname = host.targetname or (host.name ~= "" and host.name) or host.ip - stdnse.print_debug(1, "Got icon URL %s.", icon) - local icon_host, icon_port, icon_path = parse_url_relative(icon, hostname, port.number, root) - if (icon_host == host.ip or - icon_host == host.targetname or - icon_host == (host.name ~= '' and host.name)) and - icon_port == port.number then - -- request the favicon - answer = http.get( icon_host, icon_port, icon_path ) - else - answer = nil - end - else - answer = nil - end - end + -- Otherwise, first try parsing the home page. + index = http.get( host, port, root .. "/" ) + if index.status == 200 or index.status == 503 then + -- find the favicon pattern + icon = parseIcon( index.body ) + -- if we find a pattern + if icon then + local hostname = host.targetname or (host.name ~= "" and host.name) or host.ip + stdnse.print_debug(1, "Got icon URL %s.", icon) + local icon_host, icon_port, icon_path = parse_url_relative(icon, hostname, port.number, root) + if (icon_host == host.ip or + icon_host == host.targetname or + icon_host == (host.name ~= '' and host.name)) and + icon_port == port.number then + -- request the favicon + answer = http.get( icon_host, icon_port, icon_path ) + else + answer = nil + end + else + answer = nil + end + end - -- If that didn't work, try /favicon.ico. - if not answer or answer.status ~= 200 then - answer = http.get( host, port, root .. "/favicon.ico" ) - stdnse.print_debug( 4, "Using default URI.") - end + -- If that didn't work, try /favicon.ico. + if not answer or answer.status ~= 200 then + answer = http.get( host, port, root .. "/favicon.ico" ) + stdnse.print_debug( 4, "Using default URI.") + end end --- check for 200 response code if answer and answer.status == 200 then - md5sum=string.upper(stdnse.tohex(openssl.md5(answer.body))) - match=favicondb[md5sum] - if match then - result = match - else - if nmap.verbosity() > 0 then - result = "Unknown favicon MD5: " .. md5sum - end - end - else - stdnse.print_debug( 1, "No favicon found.") - return + md5sum=string.upper(stdnse.tohex(openssl.md5(answer.body))) + match=favicondb[md5sum] + if match then + result = match + else + if nmap.verbosity() > 0 then + result = "Unknown favicon MD5: " .. md5sum + end + end + else + stdnse.print_debug( 1, "No favicon found.") + return end --- status == 200 return result end local function dirname(path) - local dir - dir = string.match(path, "^(.*)/") - return dir or "" + local dir + dir = string.match(path, "^(.*)/") + return dir or "" end -- Return a URL's host, port, and path, filling in the results with the given -- host, port, and path if the URL is relative. Return nil if the scheme is not -- "http" or "https". function parse_url_relative(u, host, port, path) - local defaultport, scheme, abspath - u = url.parse(u) - scheme = u.scheme or "http" - if scheme == "http" then - defaultport = 80 - elseif scheme == "https" then - defaultport = 443 - else - return nil - end - abspath = u.path or "" - if not string.find(abspath, "^/") then - abspath = dirname(path) .. "/" .. abspath - end - return u.host or host, u.port or defaultport, abspath + local defaultport, scheme, abspath + u = url.parse(u) + scheme = u.scheme or "http" + if scheme == "http" then + defaultport = 80 + elseif scheme == "https" then + defaultport = 443 + else + return nil + end + abspath = u.path or "" + if not string.find(abspath, "^/") then + abspath = dirname(path) .. "/" .. abspath + end + return u.host or host, u.port or defaultport, abspath end function parseIcon( body ) - local _, i, j - local rel, href, word + local _, i, j + local rel, href, word - -- Loop through link elements. - i = 0 - while i do - _, i = string.find(body, "<%s*[Ll][Ii][Nn][Kk]%s", i + 1) - if not i then - return nil - end - -- Loop through attributes. - j = i - while true do - local name, quote, value - _, j, name, quote, value = string.find(body, "^%s*(%w+)%s*=%s*([\"'])(.-)%2", j + 1) - if not j then - break - end - if string.lower(name) == "rel" then - rel = value - elseif string.lower(name) == "href" then - href = value - end - end - for word in string.gmatch(rel or "", "%S+") do - if string.lower(word) == "icon" then - return href - end - end - end + -- Loop through link elements. + i = 0 + while i do + _, i = string.find(body, "<%s*[Ll][Ii][Nn][Kk]%s", i + 1) + if not i then + return nil + end + -- Loop through attributes. + j = i + while true do + local name, quote, value + _, j, name, quote, value = string.find(body, "^%s*(%w+)%s*=%s*([\"'])(.-)%2", j + 1) + if not j then + break + end + if string.lower(name) == "rel" then + rel = value + elseif string.lower(name) == "href" then + href = value + end + end + for word in string.gmatch(rel or "", "%S+") do + if string.lower(word) == "icon" then + return href + end + end + end end