--- http-favicon.nse 2009-08-11 01:22:23.000000000 -0300 +++ http-favicon-parsing.nse 2009-08-11 01:33:22.000000000 -0300 @@ -31,6 +31,8 @@ local status, favicondb local result= "" local favicondbfile="favicon-db" + local index, icon + local root = "" status, favicondb = datafiles.parse_file( favicondbfile, {["^%s*([^%s#:]+)[%s:]+"] = "^%s*[^%s#:]+[%s:]+(.*)"}) if not status then @@ -43,16 +45,43 @@ return end - if(nmap.registry.args.favicon and nmap.registry.args.favicon.uri) then - answer = http.get( host, port, "/"..nmap.registry.args.favicon.uri) - stdnse.print_debug( 4, "Using URI %s", nmap.registry.args.favicon.uri) + if(nmap.registry.args['favicon.root']) then + root = nmap.registry.args['favicon.root'] + end + + if(nmap.registry.args['favicon.name']) then + answer = http.get( host, port, root .. "/" .. nmap.registry.args['favicon.name']) + stdnse.print_debug( 4, "Using URI %s", root .. "/" .. nmap.registry.args['favicon.name']) else - answer = http.get( host, port, "/favicon.ico" ) + answer = http.get( host, port, root .. "/favicon.ico" ) stdnse.print_debug( 4, "Using default URI.") end + -- if we didn't find a correct favicon, let's parse the first page and search for one! + if answer.status ~= 200 then + stdnse.print_debug( 1, "No favicon found on root of web server, parsing initial page for favicon.") + index = http.get( host, port, root .. "/" ) + -- if we get the first page + if index.status == 200 then + -- find the favicon pattern + icon = parseIcon( index.body ) + -- if we find a pattern + if icon then + -- check if the path is in './' format, what means that we must replace it by the root directory + if string.match(icon, "^%.") then + icon = string.gsub(icon, "^%.", root, 1) + end + -- request the favicon + answer = http.get( host, port, icon ) + else + answer = nil + end + end + end + + --- check for 200 response code - if answer.status == 200 then + if answer and answer.status == 200 then md5sum=stdnse.tohex(openssl.md5(answer.body)) match=favicondb[md5sum] if match then @@ -61,9 +90,22 @@ result="Unknown favicon MD5: " .. md5sum end else - stdnse.print_debug( 1, "No favicon found on root of web server.") + stdnse.print_debug( 1, "No favicon found.") return end --- status == 200 return result end +function parseIcon( body ) + local icon, absolute_icon, parsed_icon + icon = string.match( body, '<%s*link.-rel%s*=%s*".-icon".-href%s*=%s*"(.-)".-%/?>') + if icon then + -- if favicon is in absolute format, we need to parse it! + absolute_icon = string.match(icon, '^http://') + if absolute_icon then + parsed_icon = url.parse(icon) + icon = parsed_icon.path + end + end + return icon +end