1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-24 16:39:03 +00:00

o Added a new NSE Comm library for common network discovery tasks such

as banner-grabbing (get_banner()) and making a quick exchange of data
  (exchange()).  16 scripts were updated to use this library. [Kris]

I have *not* been able to test all of these scripts; however, I have
reviewed them and they should all work properly.  I would really like
some more testing, though :)

This commit includes scripting.xml documentation.
This commit is contained in:
kris
2008-06-12 14:32:25 +00:00
parent cede9ab542
commit 2f9321360f
19 changed files with 297 additions and 268 deletions

View File

@@ -8,6 +8,7 @@
id="Open Proxy Test"
description="Test if a discovered proxy is open to us by connecting to www.google.com and checking for the 'Server: GWS/' header response."
categories = {"default", "intrusive"}
require "comm"
-- I found a nice explode() function in lua-users' wiki. I had to fix it, though.
-- http://lua-users.org/wiki/LuaRecipes
@@ -39,29 +40,22 @@ portrule = function(host, port)
end
action = function(host, port)
local socket = nmap.new_socket()
local result
local status = true
local response
local i
-- We will return this if we don't find "^Server: GWS" in response headers
local retval
socket:set_timeout(10000);
socket:connect(host.ip, port.number, port.protocol)
-- Ask proxy to open www.google.com
socket:send("GET http://www.google.com HTTP/1.0\r\nHost: www.google.com\r\n\r\n")
-- read the response, if any
status, result = socket:receive_lines(1)
local req = "GET http://www.google.com HTTP/1.0\r\nHost: www.google.com\r\n\r\n"
local status, result = comm.exchange(host, port, req, {proto=port.protocol, timeout=10000})
-- Explode result into the response table
if (status == false) or (result == "TIMEOUT") then
else
response = explode("\n",result)
if not status then
return
end
-- Explode result into the response table
response = explode("\n",result)
-- Now, search for Server: GWS until headers (or table) end.
i = 0
while true do
@@ -74,7 +68,5 @@ action = function(host, port)
end
end
-- close the socket and exit, returning the retval string.
socket:close()
return retval
end

View File

@@ -18,6 +18,7 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"discovery"}
require "comm"
require "shortport"
require "stdnse"
@@ -76,31 +77,14 @@ end
portrule = shortport.port_or_service({80, 8080}, "http")
action = function(host, port)
local cmd, response
local socket
local cmd = "TRACE / HTTP/1.0\r\n\r\n"
socket = nmap.new_socket()
local status, response = comm.exchange(host, port, cmd, {timeout=5000})
socket:connect(host.ip, port.number)
cmd = "TRACE / HTTP/1.0\r\n\r\n"
socket:send(cmd)
response = ""
while true do
local status, lines = socket:receive_lines(1)
if not status then
break
end
response = response .. lines
if not status then
return
end
socket:close()
return validate(response, cmd)
end

View File

@@ -18,6 +18,7 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = { "default", "discovery", "safe" }
require 'bit'
require 'comm'
-- Grabs NUL-terminated string
local getstring = function(orig)
@@ -105,28 +106,14 @@ portrule = function(host, port)
end
action = function(host, port)
local sock
local response = ""
local output = ""
sock = nmap.new_socket()
local status, response = comm.get_banner(host, port, {timeout=5000})
sock:set_timeout(5000)
sock:connect(host.ip, port.number)
while true do
local status, line = sock:receive_lines(1)
if not status then
break
end
response = response .. line
if not status then
return
end
sock:close()
local length = ntoh3(response:sub(1, 3))
if length ~= response:len() - 4 then

View File

@@ -11,6 +11,8 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"version"}
require "comm"
portrule = function(host, port)
if
port.number == 1723
@@ -24,23 +26,6 @@ portrule = function(host, port)
end
action = function(host, port)
-- create the socket used for our connection
local socket = nmap.new_socket()
-- set a reasonable timeout value
socket:set_timeout(5000)
-- do some exception handling / cleanup
local catch = function()
socket:close()
end
local try = nmap.new_try(catch)
-- connect to the potential PPTP service
try(socket:connect(host.ip, port.number, "tcp"))
local payload
-- build a PPTP Start-Control-Connection-Request packet
@@ -67,24 +52,9 @@ action = function(host, port)
payload = payload .. "\000\000\000\000\000\000\000\000" -- padding for vendor name
payload = payload .. "\000\000\000\000" -- padding for vendor name
try(socket:send(payload))
local status
local response
-- read in any response we might get
status, response = socket:receive_bytes(1)
local try = nmap.new_try()
local response = try(comm.exchange(host, port, payload, {bytes=1, timeout=5000}))
if (not status) then
return
end
if (response == "TIMEOUT") then
return
end
try(socket:close())
local result
-- check to see if the packet we got back matches the beginning of a PPTP Start-Control-Connection-Reply packet

View File

@@ -8,20 +8,15 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"demo"}
require "comm"
require "shortport"
portrule = shortport.port_or_service(19, "chargen", "udp")
action = function(host, port)
local socket = nmap.new_socket()
socket:connect(host.ip, port.number, "udp")
socket:send("dummy")
local status, result = socket:receive_lines(1);
socket:close()
local status, result = comm.exchange(host, port, "dummy", {lines=1, proto="udp"})
if (result ~= nil) then
if status then
return "Chargen: success"
else
return "Chargen: something went wrong"
end
end

View File

@@ -8,18 +8,15 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"demo"}
require "comm"
require "shortport"
portrule = shortport.port_or_service(13, "daytime", "udp")
action = function(host, port)
local socket = nmap.new_socket()
socket:connect(host.ip, port.number, "udp")
socket:send("dummy")
local status, result = socket:receive_lines(1);
socket:close()
local status, result = comm.exchange(host, port, "dummy", {lines=1, proto="udp"})
if (result ~= nil) then
if status then
return "Daytime: " .. result
end
end

View File

@@ -9,6 +9,7 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"default", "intrusive"}
require "bit"
require "comm"
require "shortport"
portrule = shortport.portnumber(53, "udp")
@@ -18,12 +19,11 @@ action = function(host, port)
-- generate dns query, Transaction-ID 0xdead, www.wikipedia.org (type A, class IN)
local request = string.char(0xde, 0xad, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03) .. "www" .. string.char(0x09) .. "wikipedia" .. string.char(0x03) .. "org" .. string.char(0x00, 0x00, 0x01, 0x00, 0x01)
local socket = nmap.new_socket()
socket:connect(host.ip, port.number, "udp")
socket:send(request)
local status, result = comm.exchange(host, port, request, {proto="udp"})
local status, result = socket:receive();
socket:close()
if not status then
return
end
-- parse response for dns flags
if (bit.band(string.byte(result,3), 0x80) == 0x80

View File

@@ -9,21 +9,17 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"demo"}
require "comm"
require "shortport"
portrule = shortport.port_or_service(7, "echo", "udp")
action = function(host, port)
local echostr = "hello there"
local socket = nmap.new_socket()
socket:connect(host.ip, port.number, "udp")
socket:send(echostr)
local status, result = socket:receive_lines(1);
socket:close()
local status, result = comm.exchange(host, port, echostr, {lines=1, proto="udp"})
if (result == echostr) then
return "UDP Echo: correct response"
end
return
end

View File

@@ -8,29 +8,13 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"default", "discovery"}
require "comm"
require "shortport"
portrule = shortport.port_or_service(79, "finger")
action = function(host, port)
local socket = nmap.new_socket()
local results = ""
local status = true
local try = nmap.new_try()
local err_catch = function()
socket:close()
end
local try = nmap.new_try(err_catch())
socket:set_timeout(5000)
try(socket:connect(host.ip, port.number, port.protocol))
try(socket:send("\r\n"))
status, results = socket:receive_lines(100)
socket:close()
if not(status) then
return results
end
return try(comm.exchange(host, port, "\r\n", {lines=100, proto=port.protocol, timeout=5000}))
end

View File

@@ -9,43 +9,36 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"version"}
require "comm"
require "shortport"
portrule = shortport.portnumber(4569, "udp")
action = function(host, port)
local soc = nmap.new_socket()
soc:set_timeout(10000)
local conn = soc:connect(host.ip, port.number, port.protocol)
-- see http://www.cornfed.com/iax.pdf for all options.
local poke = string.char(0x80, 0x00, 0x00, 0x00)
poke = poke .. string.char(0x00, 0x00, 0x00, 0x00)
poke = poke .. string.char(0x00, 0x00, 0x06, 0x1e)
if (conn) then
-- see http://www.cornfed.com/iax.pdf for all options.
local poke = string.char(0x80, 0x00, 0x00, 0x00)
poke = poke .. string.char(0x00, 0x00, 0x00, 0x00)
poke = poke .. string.char(0x00, 0x00, 0x06, 0x1e)
soc:send(poke)
local status, recv
status, recv = soc:receive_bytes(1)
if (string.len(recv)) == 12 then
local byte11 = string.format("%02X", string.byte(recv, 11))
local byte12 = string.format("%02X", string.byte(recv, 12))
-- byte11 must be \x06 IAX Control Frame
-- and byte12 must be \x03 or \x04
if ((byte11 == "06") and
(byte12 == ("03" or "04")))
then
nmap.set_port_state(host, port, "open")
port.version.name = "iax2"
nmap.set_port_version(host, port, "hardmatched")
end
end
soc:close()
local status, recv = comm.exchange(host, port, poke, {bytes=1,proto=port.protocol,timeout=10000})
if not status then
return
end
if (string.len(recv)) == 12 then
local byte11 = string.format("%02X", string.byte(recv, 11))
local byte12 = string.format("%02X", string.byte(recv, 12))
-- byte11 must be \x06 IAX Control Frame
-- and byte12 must be \x03 or \x04
if ((byte11 == "06") and
(byte12 == ("03" or "04")))
then
nmap.set_port_state(host, port, "open")
port.version.name = "iax2"
nmap.set_port_version(host, port, "hardmatched")
end
end
end

View File

@@ -9,23 +9,15 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"malware"}
require "comm"
require "shortport"
portrule = shortport.port_or_service(113, "auth")
action = function(host, port)
local status = 0
local owner = ""
local status, owner = comm.get_banner(host, port, {lines=1})
local client_ident = nmap.new_socket()
client_ident:connect(host.ip, port.number)
status, owner = client_ident:receive_lines(1)
client_ident:close()
if owner == "TIMEOUT" then
if not status then
return
end

View File

@@ -11,6 +11,8 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"default", "discovery", "safe"}
require "comm"
-- I have excluded the port function param because it doesn't make much sense
-- for a hostrule. It works without warning. The NSE documentation is
-- not explicit enough in this regard.
@@ -49,51 +51,23 @@ end
-- Again, I have excluded the port param. Is this okay on a hostrule?
action = function(host)
local socket = nmap.new_socket()
socket:set_timeout(5000)
local result
local status = true
status, result = socket:connect(host.ip, 137, "udp")
if (not status) then
-- Can a UDP connect ever fail?
return
end
-- This is the UDP NetBIOS request packet. I didn't feel like
-- actually generating a new one each time so this has been shamelessly
-- copied from a packet dump of nbtscan.
-- See http://www.unixwiz.net/tools/nbtscan.html for code.
-- The magic number in this code is \003\097.
status, result = socket:send(
local data =
"\003\097\000\016\000\001\000\000" ..
"\000\000\000\000\032\067\075\065" ..
"\065\065\065\065\065\065\065\065" ..
"\065\065\065\065\065\065\065\065" ..
"\065\065\065\065\065\065\065\065" ..
"\065\065\065\065\065\000\000\033" ..
"\000\001")
"\000\001"
local status, result = comm.exchange(host, 137, data, {bytes=1, proto="udp", timeout=5000})
if (not status) then
-- Can the first UDP send ever fail?
return
end
-- this receive_bytes will consume all the input available
-- with a minimum of 1 byte.
status, result = socket:receive_bytes(1);
-- We don't need this socket anymore
socket:close()
if (not status) then
return
end
if (result == "TIMEOUT") then
return
end

View File

@@ -1,3 +1,4 @@
require "comm"
require "ipOps"
id = "RIPE query"
@@ -12,24 +13,11 @@ hostrule = function(host, port)
end
action = function(host, port)
local socket = nmap.new_socket()
local status, line
local result = ""
local status, result = comm.exchange("whois.ripe.net", 43, host.ip .. "\n")
socket:connect("whois.ripe.net", 43)
-- socket:connect("193.0.0.135", 43)
socket:send(host.ip .. "\n")
while true do
local status, lines = socket:receive_lines(1)
if not status then
break
else
result = result .. lines
end
if not status then
return
end
socket:close()
local value = string.match(result, "role:(.-)\n")

View File

@@ -5,6 +5,7 @@ author = "Sven Klemm <sven@c3d2.de>"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"default","safe","discovery"}
require "comm"
require "shortport"
require "packet"
require "datafiles"
@@ -12,14 +13,12 @@ require "datafiles"
portrule = shortport.port_or_service(111, "rpcbind")
action = function(host, port)
local try, catch
local try
local transaction_id = "nmap"
local socket = nmap.new_socket()
local result = " \n"
local rpc_numbers
catch = function() socket:close() end
try = nmap.new_try( catch )
try = nmap.new_try()
rpc_numbers = try(datafiles.parse_rpc())
local request = string.char(0x80,0,0,40) -- fragment header
@@ -29,16 +28,8 @@ action = function(host, port)
request = request .. "\0\0\0\2\0\0\0\4" -- programm version (2) procedure dump(4)
request = request .. "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"-- Credentials and verifier
socket:set_timeout(1000)
try( socket:connect(host.ip, port.number) )
try( socket:send( request ) )
local status, answer, answer_part
status, answer = socket:receive_bytes( 1 )
while status do
status, answer_part = socket:receive_bytes( 1 )
if status then answer = answer .. answer_part end
end
socket:close()
local answer = try(comm.exchange(host, port, request, {timeout=1000}))
local answer_part
local fragment_length = answer:byte(4) + answer:byte(3) * 256 + answer:byte(2) * 65536
if answer:sub(5,8) == transaction_id and answer:byte(12) == 1 and answer:byte(16) == 0 and answer:byte(28) == 0 then

View File

@@ -8,24 +8,18 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"demo"}
require "comm"
require "shortport"
portrule = shortport.port_or_service(25, "smtp")
action = function(host, port)
local client = nmap.new_socket()
local status, result = comm.get_banner(host, port, {lines=1})
client:connect(host.ip, port.number)
local status, result = client:receive_lines(1);
client:close()
if result ~= nil then
result = string.gsub(result, "\n", "")
if not status then
return
end
return result
return string.gsub(result, "\n", "")
end

View File

@@ -3,6 +3,7 @@ description="Determines if remote service is Skype protocol version 2"
author = "Brandon Enright <bmenrigh@ucsd.edu>"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"version"}
require "comm"
portrule = function(host, port)
if (port.number == 80 or
@@ -22,42 +23,25 @@ portrule = function(host, port)
end
action = function(host, port)
local socket = nmap.new_socket()
local result;
local status = true
socket:connect(host.ip, port.number, port.protocol)
socket:send("GET / HTTP/1.0\r\n\r\n")
status, result = socket:receive_bytes(26);
local status, result = comm.exchange(host, port, "GET / HTTP/1.0\r\n\r\n", {bytes=26, proto=port.protocol})
if (not status) then
socket:close()
return
end
if (result ~= "HTTP/1.0 404 Not Found\r\n\r\n") then
socket:close()
return
end
socket:close();
-- So far so good, now see if we get random data for another request
socket:connect(host.ip, port.number, port.protocol)
socket:send("random data\r\n\r\n")
status, result = socket:receive_bytes(15);
status, result = comm.exchange(host, port, "random data\r\n\r\n", {bytes=15, proto=port.protocol})
if (not status) then
socket:close()
return
end
if string.match(result, "[^%s!-~].*[^%s!-~].*[^%s!-~]") then
socket:close()
port.version.name = "skype2"
port.version.product = "Skype"
port.version.confidence = 10
@@ -67,7 +51,5 @@ action = function(host, port)
-- return "Skype v2 server detected"
end
socket:close();
return
end