nmap script to try and detect login pages
April 7, 2010 1 Comment
The title sort of explains it.
description = [[
Attempts to check if a login page exists on the port.
]]
---
-- @output
-- 80/tcp open http
-- |_ http-login-form: HTTP login detected
-- HTTP authentication information gathering script
-- rev 1.0 (2010-02-06)
author = "Rich Lundeen <mopey@webstersprodigy.net>"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"ioactive"}
require("shortport")
require("http")
require("pcre")
portrule = shortport.port_or_service({80, 443, 8080}, {"http","https"})
parse_url = function(url)
local re = pcre.new("^([^:]*):[/]*([^/]*)", 0, "C")
local s, e, t = re:exec(url, 0, 0)
local proto = string.sub(url, t[1], t[2])
local host = string.sub(url, t[3], t[4])
local path = string.sub(url, t[4] + 1)
local port = string.find(host, ":")
if port ~= nil then
--TODO check bounds, sanity, cast port to an int
local thost = string.sub(host, 0, port-1)
port = string.sub(host, port+1)
host = thost
else
if proto == "http" then
port = 80
elseif proto == "https" then
port = 443
end
end
return host, port, path
end
--attempting to be compatible with nessus function in http.inc
--in this case, host is a url - it should use get_http_page
--get_http_page = function(port, host, redirect)
--port and url are objects passed to the action function
--redirect an integer to prohibit loops
get_http_page_nmap = function(port, host, redirect, path)
if path == nil then
path = "/"
end
if redirect == nil then
redirect = 2
end
local answer = http.get(host, port, path)
if ((answer.header.location ~= nil) and (redirect > 0) and
(answer.status >=300) and (answer.status < 400)) then
nhost, nport, npath = parse_url(answer.header.location)
if (((nhost ~= host.targetname) and (nhost ~= host.ip) and
(nhost ~= host.name)) or nport ~= port.number ) then
--cannot redirect more, different service
return answer, path
else
return get_http_page_nmap(port, host, redirect-1, npath)
end
end
return answer, path
end
action = function(host, port)
local result, path = get_http_page_nmap(port, host, 3)
--seems to be a bug in the matching
local loginflags = pcre.flags().CASELESS + pcre.flags().MULTILINE
local loginre = {
pcre.new("<script>[^>]*login" , loginflags, "C"),
pcre.new("<[^>]*login" , loginflags, "C"),
pcre.new("<script>[^>]*password" , loginflags, "C"),
pcre.new("<script>[^>]*user" , loginflags, "C"),
pcre.new("<input[^>)]*user" , loginflags, "C"),
pcre.new("<input[^>)]*pass" , loginflags, "C"),
pcre.new("<input[^>)]*pwd" , loginflags, "C") }
local loginform = false
for i,v in ipairs(loginre) do
local ismatch, j = v:match(result.body, 0)
if ismatch then
loginform = true
break
end
end
if loginform then
return "Login Form Detected at " .. path
end
end