description = [[ A more accurate version of the original apache-default.nse script. Instead of basing this on the title only, this will also key on the body to detect the Ubuntu default page. Testing with the ubuntu default apache2 install and the OpenBSD default apache1.3 install. I was inspired to do this by fyodor and David Fifield's DC18 talk that showed how easy and doable writing nmap scripts is. It was Brian Orlick who gave me a quick crashcourse in lua on IRC (on my blackberry during another less engaging DC talk) that got me most of the way through this. Martin Heck kindly lent me permission to scan one of his machines to assist in verifying the functionality. TODO: Make this generic to several http servers. Specifically, I'd like to support IIS. I'm not sure at this point if lighttpd will prove doable, but that will be looked into. ]] author = "Kyle Isom " license = "BSD license" ---@usage -- nmap -r -n -T4 --script=default-apache localhost ---@output --80/tcp open http Apache httpd 2.2.14 ((Ubuntu)) --|_default-apache: *** default Apache install detected -- killer coding ninja monkeys exist -- ...too bad I am not one categories = { "safe", "discovery" } require "http" require "stdnse" require "pcre" portrule = function(host, port) local match = 0 local svc = { list = { ["http"] = 1, ["http-alt"] = 1, ["https"] = 1, ["https-alt"] = 1 }, std = { "http", "http-alt" }, ssl = { "https", "https-alt" } } if port.protocol ~= "tcp" or port.state == "closed" then return false end -- match only on the right service for k,v in pairs(svc.list) do if port.service == k then match = match + 1 end end -- sanity check... if match ~= 1 then return nil end -- abort if we're using SSL and we don't have SSL support for k,v in pairs(svc.ssl) do if port.service == k and not nmap.have_ssl() then return false end end -- congratulations, you have passed the gauntlet return true end action = function(host, port) -- set up body dictionary body = {} body.rst = 0 body.rend = 0 body.value = 0 -- set up title dictionary title = {} title.rst = 0 title.rend = 0 title.value = "" data = "" match = 0 target = {} default = {} default.ubuntu = "

It works!

This is the default " .. "web page for this server.

The web server " .. "software is running but no content has been added, " .. "yet.

" default.title = "Test Page for Apache Installation" connector = nmap.new_socket() local catch = function() print("error setting up sockets...") connector:close() end local try = nmap.new_try(catch) data = http.get(host, port, '/') -- debug print to check http values -- print("http returned ", data.status) if not data or data.status ~= 200 then print("ABRT") return nil end -- strip newlines data.body = data.body:gsub('\n', " ") data.body = data.body:gsub("\r", " ") titlere = pcre.new(".*<\/title>", 0, "C") title.rst, title.rend = titlere:match(data.body, 0, 0) if title.rst and title.rend then title.value = data.body:sub(title.rst, title.rend) target["title"] = title.value end bodyre = pcre.new(".*", 2, "C") body.rst, body.rend = bodyre:match(data.body, 0, 0) if body.rst and body.rend then body.value = data.body:sub(body.rst, body.rend) target["body"] = body.value end if target.body and string.match(target.body, default.ubuntu) then match = match + 1 end if target.title and string.match(target.title, default.title) then match = match + 1 end if match == 1 then return "*** default Apache install detected" else return nil end end