nmap script to try and detect login pages

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"}


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
    if proto == "http" then
      port = 80
    elseif proto == "https" then
      port = 443
  return host, port, path

--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 = "/"
  if redirect == nil then
    redirect = 2
  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
      return get_http_page_nmap(port, host, redirect-1, npath)
  return answer, path

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
  if loginform then
    return "Login Form Detected at " .. path

One Response to nmap script to try and detect login pages

  1. Mike says:

    Just stumbled on your blog. Great time saving stuff. Keep up the good work. I wish I can help but I’m a n00b. I will post questions if I have a problem or need help with make mod’s.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: