diff options
Diffstat (limited to 'scripts/broadcast-jenkins-discover.nse')
-rw-r--r-- | scripts/broadcast-jenkins-discover.nse | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/scripts/broadcast-jenkins-discover.nse b/scripts/broadcast-jenkins-discover.nse new file mode 100644 index 0000000..be9ae06 --- /dev/null +++ b/scripts/broadcast-jenkins-discover.nse @@ -0,0 +1,94 @@ +local nmap = require "nmap" +local stdnse = require "stdnse" +local string = require "string" +local os = require "os" +local table = require "table" +local rand = require "rand" + +description = [[ +Discovers Jenkins servers on a LAN by sending a discovery broadcast probe. + +For more information about Jenkins auto discovery, see: +* https://wiki.jenkins.io/display/JENKINS/Auto-discovering+Jenkins+on+the+network +]] + +--- +-- @usage nmap --script broadcast-jenkins-discover +-- @usage nmap --script broadcast-jenkins-discover --script-args timeout=15s +-- +-- @output +-- Pre-scan script results: +-- | broadcast-jenkins: +-- | Version: 2.60.2; Server ID: d5e31b7a9d69cf3c89cc799c23199760; Slave Port: 35928 +-- |_ Version: 2.60.2; Server ID: b98e8e1b862c3eecb14e8be0028cf4ee; Slave Port: 45435 +-- +-- @args broadcast-jenkins.address +-- address to which the probe packet is sent. (default: 255.255.255.255) +-- @args broadcast-jenkins.timeout +-- socket timeout (default: 5s) +--- + +author = "Brendan Coles" +license = "Same as Nmap--See https://nmap.org/book/man-legal.html" +categories = {"discovery", "broadcast", "safe"} + +prerule = function() return ( nmap.address_family() == "inet") end + +local arg_address = stdnse.get_script_args(SCRIPT_NAME .. ".address") +local arg_timeout = stdnse.parse_timespec(stdnse.get_script_args(SCRIPT_NAME .. ".timeout")) + +action = function() + + local host = { ip = arg_address or "255.255.255.255" } -- broadcast + -- local host = { ip = arg_address or "239.77.124.213" } -- multicast + local port = { number = 33848, protocol = "udp" } + local socket = nmap.new_socket("udp") + + socket:set_timeout(500) + + -- send two packets, just in case + local probe = rand.random_string(10) + for i=1,2 do + local status = socket:sendto(host, port, probe) + if ( not(status) ) then + return stdnse.format_output(false, "Failed to send broadcast probe") + end + end + + local timeout = tonumber(arg_timeout) or ( 20 / ( nmap.timing_level() + 1 ) ) + local results = {} + local stime = os.time() + + -- listen until timeout + repeat + local status, data = socket:receive() + if ( status ) then + local jenkins_pkt = data:match("^<hudson>(.+)</hudson>") + if ( jenkins_pkt ) then + local status, _, _, rhost, _ = socket:get_info() + local version = jenkins_pkt:match("<version>(.*)</version>") + local server_id = jenkins_pkt:match("<server%-id>(.*)</server%-id>") + local slave_port = jenkins_pkt:match("<slave%-port>(.*)</slave%-port>") + if version and server_id and slave_port then + stdnse.print_debug(2, "Received Jenkins discovery response from %s (%s bytes)", rhost, string.len(jenkins_pkt)) + local str = ("Version: %s; Server ID: %s; Slave Port: %s"):format(version, server_id, slave_port) + table.insert( results, str ) + end + end + end + until( os.time() - stime > timeout ) + socket:close() + + local response = stdnse.output_table() + if #results > 0 then + -- remove duplicates + local hash = {} + for _,v in ipairs(results) do + if (not hash[v]) then + table.insert( response, v ) + hash[v] = true + end + end + return response + end +end |