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

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

Unintended consequences of half open scans

Short analysis of the nmap half open scans (also called syn scans).

These scans are distinguished from the default operation of full connection scans, which completes the full tcp handshake. i.e.

SYN –>
<—SYN+ACK
ACK–>

A half open scan just does

SYN–>
<–SYN+ACK

The scanner determines weather the port is up or not based on if the SYN+ACK comes back.  Obviously, the final ack is never sent back.  This can be performed by

$ nmap -P0 -sS target

This was a popular method due to it being ‘stealthy’ though it’s not so much stealthy anymore and because it’s fast – though it doesn’t seem to be faster than a full connection scan in practice.

Anyways, now to something everyone doesn’t already know (maybe, at least I didn’t).

nmap uses raw sockets to craft these packets, which is why syn scans must be run as root.  What’s interesting is that if the remote host responds with a SYN+ACK – the local stack receives this packet, which did not come from the local stack (because again, it was crafted with a raw socket by nmap).  As far as the scanning computer knows, the SYN+ACK is not part of a handshake and appears to have come out of nowhere, so the scanner sends a RST back to the target system.  Nuts.

You can stop this by using simple iptables, on INPUT or OUTPUT, by having a default drop policy (only allowing ESTABLISHED,RELATED and known services through is probably a good rule of thumb).

scanrand

scanrand is a cool tool for network scanning written by Dan Kaminski.  The big advantage to this tool as a network scanner is that it can scan very large networks very very fast.

It works by splitting into two completely independent processes, one for sending packets and one for receiving them.  The sending process fires off syn packets and doesn’t try to retain state information.  Also, the receiving process doesn’t retain state.  It works by using a stateful protocol in a stateless way.

How does this prevent a smart router or something from just sending weird information in response to  a detected scan?

Normally, an ISN of a syn packet is meant to be basically random.  scanrand builds a deterministic iSN by running the source ip source port destination ip and destination port concatinated with a secret key and run through a one way hashing function – meaning these “random” isns can be calculated. this is called an “inverse syn cookie”.

Awesome.

Again, to reiterate the advantages:a class C network has been known to be scanned in as little as four seconds with this tool.

Here is how I tried it on my local network:

scanrand -d eth1 -b10M 192.168.1.1-254:quick

pretty simple.  the 10M limits the scan to 10 mbps.  One thing with scanrand is you probably ususally want to throttle the traffic -or else your network could easily become overloaded.  the -d eth1 is just specifying my wireless card.  the 192.168.1.1-254:quick is specifying which IPs and ports to scan.  quick is a shortcut meaning ports

80,443,445,53,20-23,25,135,139,8080, 110,111,143,1025,5000,465,993,31337, 79,8010,8000,6667,2049,3306

the biggest disadvantage might be how noisy it is.  But it’s not meant to be quiet.

Anyway, this is a pretty innovative “why didn’t I think of that” tools.  Give it a try.

Follow

Get every new post delivered to your Inbox.