mirror of
https://github.com/nmap/nmap.git
synced 2025-12-18 13:39:02 +00:00
o [NSE] Added the scripts xdmcp-discover, broadcast-xdmcp-discover and the
X Display Manager Control Protocol (xdmcp) library. The scripts discover hosts either using unicast or broadcast and try to detect supported authentication and authorization mechanisms. [Patrik]
This commit is contained in:
@@ -1,5 +1,10 @@
|
|||||||
# Nmap Changelog ($Id$); -*-text-*-
|
# Nmap Changelog ($Id$); -*-text-*-
|
||||||
|
|
||||||
|
o [NSE] Added the scripts xdmcp-discover, broadcast-xdmcp-discover and the
|
||||||
|
X Display Manager Control Protocol (xdmcp) library. The scripts discover
|
||||||
|
hosts either using unicast or broadcast and try to detect supported
|
||||||
|
authentication and authorization mechanisms. [Patrik]
|
||||||
|
|
||||||
o Audited the nmap-service-probes database to remove all unused
|
o Audited the nmap-service-probes database to remove all unused
|
||||||
captures, fixing dozens of bugs with captures either being ignored
|
captures, fixing dozens of bugs with captures either being ignored
|
||||||
or two fields erroneously using the same capture. This was done by
|
or two fields erroneously using the same capture. This was done by
|
||||||
|
|||||||
394
nselib/xdmcp.lua
Normal file
394
nselib/xdmcp.lua
Normal file
@@ -0,0 +1,394 @@
|
|||||||
|
---
|
||||||
|
-- Implementation of the XDMCP X-Windows protocol based on:
|
||||||
|
-- x http://www.xfree86.org/current/xdmcp.pdf
|
||||||
|
--
|
||||||
|
-- @author "Patrik Karlsson <patrik@cqure.net>"
|
||||||
|
|
||||||
|
module(... or "xdmcp", package.seeall)
|
||||||
|
|
||||||
|
-- Supported operations
|
||||||
|
OpCode = {
|
||||||
|
BCAST_QUERY = 1,
|
||||||
|
QUERY = 2,
|
||||||
|
WILLING = 5,
|
||||||
|
REQUEST = 7,
|
||||||
|
ACCEPT = 8,
|
||||||
|
MANAGE = 10,
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Packet class
|
||||||
|
Packet = {
|
||||||
|
|
||||||
|
-- The cdmcp header
|
||||||
|
Header = {
|
||||||
|
|
||||||
|
-- Creates a new instance of class
|
||||||
|
-- @param version number containing the protocol version
|
||||||
|
-- @param opcode number containing the opcode type
|
||||||
|
-- @param length number containing the length of the data
|
||||||
|
-- @return o instance of class
|
||||||
|
new = function(self, version, opcode, length)
|
||||||
|
local o = { version = version, opcode = opcode, length = length }
|
||||||
|
setmetatable(o, self)
|
||||||
|
self.__index = self
|
||||||
|
return o
|
||||||
|
end,
|
||||||
|
|
||||||
|
-- Parses data based on which a new object is instantiated
|
||||||
|
-- @param data opaque string containing data received over the wire
|
||||||
|
-- @return hdr instance of class
|
||||||
|
parse = function(data)
|
||||||
|
local pos, hdr = nil, Packet.Header:new()
|
||||||
|
pos, hdr.version, hdr.opcode, hdr.length = bin.unpack(">SSS", data)
|
||||||
|
return hdr
|
||||||
|
end,
|
||||||
|
|
||||||
|
-- Converts the instance to an opaque string
|
||||||
|
-- @return str string containing the instance
|
||||||
|
__tostring = function(self)
|
||||||
|
assert(self.length, "No header length was supplied")
|
||||||
|
return bin.pack(">SSS", self.version, self.opcode, self.length)
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
|
||||||
|
[OpCode.QUERY] = {
|
||||||
|
|
||||||
|
-- Creates a new instance of class
|
||||||
|
-- @param authnames table of strings containing authentication
|
||||||
|
-- mechanism names.
|
||||||
|
-- @return o instance of class
|
||||||
|
new = function(self, authnames)
|
||||||
|
local o = {
|
||||||
|
header = Packet.Header:new(1, OpCode.QUERY),
|
||||||
|
authnames = authnames or {},
|
||||||
|
}
|
||||||
|
o.header.length = #o.authnames + 1
|
||||||
|
setmetatable(o, self)
|
||||||
|
self.__index = self
|
||||||
|
return o
|
||||||
|
end,
|
||||||
|
|
||||||
|
-- Converts the instance to an opaque string
|
||||||
|
-- @return str string containing the instance
|
||||||
|
__tostring = function(self)
|
||||||
|
local data = tostring(self.header)
|
||||||
|
data = data .. bin.pack("C", #self.authnames)
|
||||||
|
for _, name in ipairs(self.authnames) do
|
||||||
|
data = data .. bin.pack("P", name)
|
||||||
|
end
|
||||||
|
return data
|
||||||
|
end,
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
[OpCode.BCAST_QUERY] = {
|
||||||
|
new = function(...)
|
||||||
|
local packet = Packet[OpCode.QUERY]:new(...)
|
||||||
|
packet.header.opcode = OpCode.BCAST_QUERY
|
||||||
|
return packet
|
||||||
|
end,
|
||||||
|
|
||||||
|
__tostring = function(...)
|
||||||
|
return Packet[OpCode.QUERY]:__tostring(...)
|
||||||
|
end
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
[OpCode.WILLING] = {
|
||||||
|
|
||||||
|
-- Creates a new instance of class
|
||||||
|
-- @return o instance of class
|
||||||
|
new = function(self)
|
||||||
|
local o = {
|
||||||
|
header = Packet.Header:new(1, OpCode.WILLING)
|
||||||
|
}
|
||||||
|
setmetatable(o, self)
|
||||||
|
self.__index = self
|
||||||
|
return o
|
||||||
|
end,
|
||||||
|
|
||||||
|
-- Parses data based on which a new object is instantiated
|
||||||
|
-- @param data opaque string containing data received over the wire
|
||||||
|
-- @return hdr instance of class
|
||||||
|
parse = function(data)
|
||||||
|
local willing = Packet[OpCode.WILLING]:new()
|
||||||
|
willing.header = Packet.Header.parse(data)
|
||||||
|
|
||||||
|
local pos = 7
|
||||||
|
pos, willing.authname, willing.hostname,
|
||||||
|
willing.status = bin.unpack("ppp", data, pos)
|
||||||
|
return willing
|
||||||
|
end,
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
[OpCode.REQUEST] = {
|
||||||
|
|
||||||
|
-- The connection class
|
||||||
|
Connection = {
|
||||||
|
|
||||||
|
IpType = {
|
||||||
|
IPv4 = 0,
|
||||||
|
IPv6 = 6,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Creates a new instance of class
|
||||||
|
-- @param iptype number
|
||||||
|
-- @param ip opaque string containing the ip
|
||||||
|
-- @return o instance of class
|
||||||
|
new = function(self, iptype, ip)
|
||||||
|
local o = {
|
||||||
|
iptype = iptype,
|
||||||
|
ip = ip,
|
||||||
|
}
|
||||||
|
setmetatable(o, self)
|
||||||
|
self.__index = self
|
||||||
|
return o
|
||||||
|
end,
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Creates a new instance of class
|
||||||
|
-- @param disp_no number containing the display name
|
||||||
|
-- @param auth_name string containing the authentication name
|
||||||
|
-- @param auth_data string containing additional authentication data
|
||||||
|
-- @param authr_names string containing authorization mechanisms
|
||||||
|
-- @param manf_id string containing the manufacturer id
|
||||||
|
-- @return o instance of class
|
||||||
|
new = function(self, disp_no, conns, auth_name, auth_data, authr_names, manf_id )
|
||||||
|
local o = {
|
||||||
|
header = Packet.Header:new(1, OpCode.REQUEST),
|
||||||
|
disp_no = disp_no or 1,
|
||||||
|
conns = conns or {},
|
||||||
|
auth_name = auth_name or "",
|
||||||
|
auth_data = auth_data or "",
|
||||||
|
authr_names = authr_names or {},
|
||||||
|
manf_id = manf_id or "",
|
||||||
|
}
|
||||||
|
setmetatable(o, self)
|
||||||
|
self.__index = self
|
||||||
|
return o
|
||||||
|
end,
|
||||||
|
|
||||||
|
-- Adds a new connection entry
|
||||||
|
-- @param conn instance of Connections
|
||||||
|
addConnection = function(self, conn)
|
||||||
|
table.insert(self.conns, conn)
|
||||||
|
end,
|
||||||
|
|
||||||
|
-- Adds a new authorization entry
|
||||||
|
-- @param str string containing the name of the authorization mechanism
|
||||||
|
addAuthrName = function(self, str)
|
||||||
|
table.insert(self.authr_names, str)
|
||||||
|
end,
|
||||||
|
|
||||||
|
-- Converts the instance to an opaque string
|
||||||
|
-- @return str string containing the instance
|
||||||
|
__tostring = function(self)
|
||||||
|
local data = bin.pack(">SC", self.disp_no, #self.conns)
|
||||||
|
for _, conn in ipairs(self.conns) do
|
||||||
|
data = data .. bin.pack(">S", conn.iptype)
|
||||||
|
end
|
||||||
|
data = data .. bin.pack("C", #self.conns)
|
||||||
|
for _, conn in ipairs(self.conns) do
|
||||||
|
data = data .. bin.pack(">P", ipOps.ip_to_str(conn.ip))
|
||||||
|
end
|
||||||
|
data = data .. bin.pack(">PP", self.auth_name, self.auth_data)
|
||||||
|
data = data .. bin.pack("C", #self.authr_names)
|
||||||
|
for _, authr in ipairs(self.authr_names) do
|
||||||
|
data = data .. bin.pack(">P", authr)
|
||||||
|
end
|
||||||
|
data = data .. bin.pack(">P", self.manf_id)
|
||||||
|
self.header.length = #data
|
||||||
|
|
||||||
|
return tostring(self.header) .. data
|
||||||
|
end,
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
[OpCode.ACCEPT] = {
|
||||||
|
|
||||||
|
-- Creates a new instance of class
|
||||||
|
-- @param session_id number containing the session id
|
||||||
|
-- @param auth_name string containing the authentication name
|
||||||
|
-- @param auth_data string containing additional authentication data
|
||||||
|
-- @param authr_name string containing the authorization mechanism name
|
||||||
|
-- @param authr_names string containing authorization mechanisms
|
||||||
|
-- @return o instance of class
|
||||||
|
new = function(self, session_id, auth_name, auth_data, authr_name, authr_data)
|
||||||
|
local o = {
|
||||||
|
header = Packet.Header:new(1, OpCode.ACCEPT),
|
||||||
|
session_id = session_id,
|
||||||
|
auth_name = auth_name,
|
||||||
|
auth_data = auth_data,
|
||||||
|
authr_name = authr_name,
|
||||||
|
authr_data = authr_data,
|
||||||
|
}
|
||||||
|
setmetatable(o, self)
|
||||||
|
self.__index = self
|
||||||
|
return o
|
||||||
|
end,
|
||||||
|
|
||||||
|
-- Parses data based on which a new object is instantiated
|
||||||
|
-- @param data opaque string containing data received over the wire
|
||||||
|
-- @return hdr instance of class
|
||||||
|
parse = function(data)
|
||||||
|
local accept = Packet[OpCode.ACCEPT]:new()
|
||||||
|
accept.header = Packet.Header.parse(data)
|
||||||
|
local pos = 7
|
||||||
|
pos, accept.session_id, accept.auth_name, accept.auth_data,
|
||||||
|
accept.authr_name, accept.authr_data = bin.unpack(">IPPPP", data, pos)
|
||||||
|
return accept
|
||||||
|
end,
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
[OpCode.MANAGE] = {
|
||||||
|
|
||||||
|
-- Creates a new instance of class
|
||||||
|
-- @param session_id number containing the session id
|
||||||
|
-- @param disp_no number containing the display number
|
||||||
|
-- @param disp_class string containing the display class
|
||||||
|
-- @return o instance of class
|
||||||
|
new = function(self, sess_id, disp_no, disp_class)
|
||||||
|
local o = {
|
||||||
|
header = Packet.Header:new(1, OpCode.MANAGE),
|
||||||
|
session_id = sess_id,
|
||||||
|
disp_no = disp_no,
|
||||||
|
disp_class = disp_class or ""
|
||||||
|
}
|
||||||
|
setmetatable(o, self)
|
||||||
|
self.__index = self
|
||||||
|
return o
|
||||||
|
end,
|
||||||
|
|
||||||
|
-- Converts the instance to an opaque string
|
||||||
|
-- @return str string containing the instance
|
||||||
|
__tostring = function(self)
|
||||||
|
local data = bin.pack(">ISP", self.session_id, self.disp_no, self.disp_class)
|
||||||
|
self.header.length = #data
|
||||||
|
return tostring(self.header) .. data
|
||||||
|
end,
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
-- The Helper class serves as the main script interface
|
||||||
|
Helper = {
|
||||||
|
|
||||||
|
-- Creates a new instance of Helper
|
||||||
|
-- @param host table as received by the action method
|
||||||
|
-- @param port table as received by the action method
|
||||||
|
-- @param options table
|
||||||
|
-- @retun o new instance of Helper
|
||||||
|
new = function(self, host, port, options)
|
||||||
|
local o = {
|
||||||
|
host = host,
|
||||||
|
port = port,
|
||||||
|
options = options or {},
|
||||||
|
}
|
||||||
|
setmetatable(o, self)
|
||||||
|
self.__index = self
|
||||||
|
return o
|
||||||
|
end,
|
||||||
|
|
||||||
|
-- "Connects" to the server (ie. creates the socket)
|
||||||
|
-- @return status, true on success, false on failure
|
||||||
|
connect = function(self)
|
||||||
|
self.socket = nmap.new_socket("udp")
|
||||||
|
self.socket:set_timeout(self.options.timeout or 10000)
|
||||||
|
return true
|
||||||
|
end,
|
||||||
|
|
||||||
|
-- Creates a xdmcp session
|
||||||
|
-- @param auth_name string containing the authentication name
|
||||||
|
-- @param authr_name string containing the authorization mechanism name
|
||||||
|
-- @param disp_class string containing the display class
|
||||||
|
-- @return status true on success, false on failure
|
||||||
|
-- @return response table or err string containing an error message
|
||||||
|
createSession = function(self, auth_names, authr_names, disp_no)
|
||||||
|
local info = nmap.get_interface_info(self.host.interface)
|
||||||
|
if ( not(info) ) then
|
||||||
|
return false, ("Failed to get information for interface %s"):format(host.interface)
|
||||||
|
end
|
||||||
|
|
||||||
|
local req = xdmcp.Packet[xdmcp.OpCode.QUERY]:new(auth_names)
|
||||||
|
local status, response = self:exch(req)
|
||||||
|
if ( not(status) ) then
|
||||||
|
return false, response
|
||||||
|
elseif ( response.header.opcode ~= xdmcp.OpCode.WILLING ) then
|
||||||
|
return false, "Received unexpected response"
|
||||||
|
end
|
||||||
|
|
||||||
|
local REQ = xdmcp.Packet[xdmcp.OpCode.REQUEST]
|
||||||
|
local iptype = REQ.Connection.IpType.IPv4
|
||||||
|
if ( nmap.address_family() == 'inet6' ) then
|
||||||
|
iptype = REQ.Connection.IpType.IPv6
|
||||||
|
end
|
||||||
|
|
||||||
|
local conns = { REQ.Connection:new(iptype, info.address) }
|
||||||
|
local req = REQ:new(disp_no, conns, nil, nil, authr_names)
|
||||||
|
local status, response = self:exch(req)
|
||||||
|
if ( not(status) ) then
|
||||||
|
return false, response
|
||||||
|
elseif ( response.header.opcode ~= xdmcp.OpCode.ACCEPT ) then
|
||||||
|
return false, "Received unexpected response"
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Sending this last manage packet doesn't make any sense as we can't
|
||||||
|
-- set up a listening TCP server anyway. When we can, we could enable
|
||||||
|
-- this and wait for the incoming request and retrieve X protocol info.
|
||||||
|
|
||||||
|
-- local manage = xdmcp.Packet[xdmcp.OpCode.MANAGE]:new(response.session_id,
|
||||||
|
-- disp_no, "MIT-unspecified")
|
||||||
|
-- local status, response = self:exch(manage)
|
||||||
|
-- if ( not(status) ) then
|
||||||
|
-- return false, response
|
||||||
|
-- end
|
||||||
|
|
||||||
|
return true, {
|
||||||
|
session_id = response.session_id,
|
||||||
|
auth_name = response.auth_name,
|
||||||
|
auth_data = response.auth_data,
|
||||||
|
authr_name = response.authr_name,
|
||||||
|
authr_data = response.authr_data,
|
||||||
|
}
|
||||||
|
end,
|
||||||
|
|
||||||
|
send = function(self, req)
|
||||||
|
return self.socket:sendto(self.host, self.port, tostring(req))
|
||||||
|
end,
|
||||||
|
|
||||||
|
recv = function(self)
|
||||||
|
local status, data = self.socket:receive()
|
||||||
|
if ( not(status) ) then
|
||||||
|
return false, data
|
||||||
|
end
|
||||||
|
local header = Packet.Header.parse(data)
|
||||||
|
if ( not(header) ) then
|
||||||
|
return false, "Failed to parse xdmcp header"
|
||||||
|
end
|
||||||
|
if ( not(Packet[header.opcode]) ) then
|
||||||
|
return false, ("No parser for opcode: %d"):format(header.opcode)
|
||||||
|
end
|
||||||
|
local resp = Packet[header.opcode].parse(data)
|
||||||
|
if ( not(resp) ) then
|
||||||
|
return false, "Failed to parse response"
|
||||||
|
end
|
||||||
|
return true, resp
|
||||||
|
end,
|
||||||
|
|
||||||
|
-- Sends a request to the server, receives and parses a response
|
||||||
|
-- @param req instance of Packet
|
||||||
|
-- @return status true on success, false on failure
|
||||||
|
-- @return response instance of response packet
|
||||||
|
exch = function(self, req)
|
||||||
|
local status, err = self:send(req)
|
||||||
|
if ( not(status) ) then
|
||||||
|
return false, "Failed to send xdmcp request"
|
||||||
|
end
|
||||||
|
return self:recv()
|
||||||
|
end,
|
||||||
|
|
||||||
|
}
|
||||||
69
scripts/broadcast-xdmcp-discover.nse
Normal file
69
scripts/broadcast-xdmcp-discover.nse
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
description = [[
|
||||||
|
Discovers servers running the X Display Manager Control Protocol (XDMCP) by
|
||||||
|
sending a XDMCP broadcast request to the LAN. Display managers allowing access
|
||||||
|
are marked using the keyword Willing in the result.
|
||||||
|
]]
|
||||||
|
|
||||||
|
---
|
||||||
|
-- @usage
|
||||||
|
-- nmap --script broadcast-xdmcp-discover
|
||||||
|
--
|
||||||
|
-- @output
|
||||||
|
-- Pre-scan script results:
|
||||||
|
-- | broadcast-xdmcp-discover:
|
||||||
|
-- |_ 192.168.2.162 - Willing
|
||||||
|
--
|
||||||
|
-- @arg broadcast-xdmcp-discover.timeout socket timeout in seconds (default: 5)
|
||||||
|
|
||||||
|
author = "Patrik Karlsson"
|
||||||
|
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
|
||||||
|
categories = {"broadcast", "safe"}
|
||||||
|
|
||||||
|
require 'xdmcp'
|
||||||
|
|
||||||
|
prerule = function() return true end
|
||||||
|
|
||||||
|
local arg_timeout = stdnse.get_script_args(SCRIPT_NAME .. ".timeout")
|
||||||
|
|
||||||
|
action = function()
|
||||||
|
|
||||||
|
local host, port = { ip = "255.255.255.255" }, { number = 177, protocol = "udp" }
|
||||||
|
local options = { timeout = 1 }
|
||||||
|
local helper = xdmcp.Helper:new(host, port, options)
|
||||||
|
local status = helper:connect()
|
||||||
|
|
||||||
|
local req = xdmcp.Packet[xdmcp.OpCode.BCAST_QUERY]:new(nil)
|
||||||
|
local status, err = helper:send(req)
|
||||||
|
if ( not(status) ) then
|
||||||
|
return false, response
|
||||||
|
end
|
||||||
|
|
||||||
|
local timeout = arg_timeout or 5
|
||||||
|
local start = os.time()
|
||||||
|
local result = {}
|
||||||
|
repeat
|
||||||
|
|
||||||
|
local status, response = helper:recv()
|
||||||
|
if ( not(status) and response ~= "TIMEOUT" ) then
|
||||||
|
break
|
||||||
|
elseif ( status ) then
|
||||||
|
local status, _, _, rhost = helper.socket:get_info()
|
||||||
|
if ( response.header.opcode == xdmcp.OpCode.WILLING ) then
|
||||||
|
result[rhost] = true
|
||||||
|
else
|
||||||
|
result[rhost] = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
until( os.time() - start > timeout )
|
||||||
|
|
||||||
|
local output = {}
|
||||||
|
for ip, res in pairs(result) do
|
||||||
|
if ( res ) then
|
||||||
|
table.insert(output, ("%s - Willing"):format(ip))
|
||||||
|
else
|
||||||
|
table.insert(output, ("%s - Unwilling"):format(ip))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return stdnse.format_output(true, output)
|
||||||
|
end
|
||||||
@@ -36,6 +36,7 @@ Entry { filename = "broadcast-upnp-info.nse", categories = { "broadcast", "safe"
|
|||||||
Entry { filename = "broadcast-wake-on-lan.nse", categories = { "broadcast", "safe", } }
|
Entry { filename = "broadcast-wake-on-lan.nse", categories = { "broadcast", "safe", } }
|
||||||
Entry { filename = "broadcast-wpad-discover.nse", categories = { "broadcast", "safe", } }
|
Entry { filename = "broadcast-wpad-discover.nse", categories = { "broadcast", "safe", } }
|
||||||
Entry { filename = "broadcast-wsdd-discover.nse", categories = { "broadcast", "safe", } }
|
Entry { filename = "broadcast-wsdd-discover.nse", categories = { "broadcast", "safe", } }
|
||||||
|
Entry { filename = "broadcast-xdmcp-discover.nse", categories = { "broadcast", "safe", } }
|
||||||
Entry { filename = "citrix-brute-xml.nse", categories = { "auth", "intrusive", } }
|
Entry { filename = "citrix-brute-xml.nse", categories = { "auth", "intrusive", } }
|
||||||
Entry { filename = "citrix-enum-apps-xml.nse", categories = { "discovery", "safe", } }
|
Entry { filename = "citrix-enum-apps-xml.nse", categories = { "discovery", "safe", } }
|
||||||
Entry { filename = "citrix-enum-apps.nse", categories = { "discovery", "safe", } }
|
Entry { filename = "citrix-enum-apps.nse", categories = { "discovery", "safe", } }
|
||||||
@@ -313,5 +314,6 @@ Entry { filename = "wdb-version.nse", categories = { "default", "discovery", "ve
|
|||||||
Entry { filename = "whois.nse", categories = { "discovery", "external", "safe", } }
|
Entry { filename = "whois.nse", categories = { "discovery", "external", "safe", } }
|
||||||
Entry { filename = "wsdd-discover.nse", categories = { "default", "discovery", "safe", } }
|
Entry { filename = "wsdd-discover.nse", categories = { "default", "discovery", "safe", } }
|
||||||
Entry { filename = "x11-access.nse", categories = { "auth", "default", "safe", } }
|
Entry { filename = "x11-access.nse", categories = { "auth", "default", "safe", } }
|
||||||
|
Entry { filename = "xdmcp-discover.nse", categories = { "discovery", "safe", } }
|
||||||
Entry { filename = "xmpp-brute.nse", categories = { "brute", "intrusive", } }
|
Entry { filename = "xmpp-brute.nse", categories = { "brute", "intrusive", } }
|
||||||
Entry { filename = "xmpp-info.nse", categories = { "default", "discovery", "safe", "version", } }
|
Entry { filename = "xmpp-info.nse", categories = { "default", "discovery", "safe", "version", } }
|
||||||
|
|||||||
64
scripts/xdmcp-discover.nse
Normal file
64
scripts/xdmcp-discover.nse
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
description = [[
|
||||||
|
Requests a XDMCP session and lists supported authentication and authorization mechanisms
|
||||||
|
]]
|
||||||
|
|
||||||
|
---
|
||||||
|
-- @usage
|
||||||
|
-- nmap -sU -p 177 --script xdmcp-discover <ip>
|
||||||
|
--
|
||||||
|
-- @output
|
||||||
|
-- PORT STATE SERVICE
|
||||||
|
-- 177/udp open|filtered xdmcp
|
||||||
|
-- | xdmcp-discover:
|
||||||
|
-- | Session id: 0x0000703E
|
||||||
|
-- | Authorization name: MIT-MAGIC-COOKIE-1
|
||||||
|
-- |_ Authorization data: c282137c9bf8e2af88879e6eaa922326
|
||||||
|
--
|
||||||
|
|
||||||
|
author = "Patrik Karlsson"
|
||||||
|
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
|
||||||
|
categories = {"safe", "discovery"}
|
||||||
|
|
||||||
|
require 'ipOps'
|
||||||
|
require 'shortport'
|
||||||
|
require 'xdmcp'
|
||||||
|
|
||||||
|
portrule = shortport.port_or_service(177, "xdmcp", "udp")
|
||||||
|
|
||||||
|
local mutex = nmap.mutex("xdmcp-discover")
|
||||||
|
local function fail(err) return ("\n ERROR: %s"):format(err or "") end
|
||||||
|
|
||||||
|
|
||||||
|
action = function(host, port)
|
||||||
|
|
||||||
|
local DISPLAY_ID = 1
|
||||||
|
local result = {}
|
||||||
|
|
||||||
|
local helper = xdmcp.Helper:new(host, port)
|
||||||
|
local status = helper:connect()
|
||||||
|
if ( not(status) ) then
|
||||||
|
return fail("Failed to connect to server")
|
||||||
|
end
|
||||||
|
|
||||||
|
local status, response = helper:createSession(nil,
|
||||||
|
{"MIT-MAGIC-COOKIE-1", "XDM-AUTHORIZATION-1"}, DISPLAY_ID)
|
||||||
|
|
||||||
|
if ( not(status) ) then
|
||||||
|
return fail("Failed to create xdmcp session")
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert(result, ("Session id: 0x%.8X"):format(response.session_id))
|
||||||
|
if ( response.auth_name and 0 < #response.auth_name ) then
|
||||||
|
table.insert(result, ("Authentication name: %s"):format(response.auth_name))
|
||||||
|
end
|
||||||
|
if ( response.auth_data and 0 < #response.auth_data ) then
|
||||||
|
table.insert(result, ("Authentication data: %s"):format(stdnse.tohex(response.auth_data)))
|
||||||
|
end
|
||||||
|
if ( response.authr_name and 0 < #response.authr_name ) then
|
||||||
|
table.insert(result, ("Authorization name: %s"):format(response.authr_name))
|
||||||
|
end
|
||||||
|
if ( response.authr_data and 0 < #response.authr_data ) then
|
||||||
|
table.insert(result, ("Authorization data: %s"):format(stdnse.tohex(response.authr_data)))
|
||||||
|
end
|
||||||
|
return stdnse.format_output(true, result)
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user