mirror of
https://github.com/nmap/nmap.git
synced 2025-12-06 20:51:30 +00:00
socket:connect(host.ip, port.number) socket:connect(host.ip, port.number, port.protocol) to this: socket:connect(host, port) connect can take host and port tables now, and the default protocol is taken from the port table if possible.
142 lines
3.7 KiB
Lua
142 lines
3.7 KiB
Lua
description = [[
|
|
Extracts a list of Citrix servers from the ICA Browser service.
|
|
]]
|
|
|
|
---
|
|
-- @usage sudo ./nmap -sU --script=citrix-enum-servers -p 1604
|
|
--
|
|
-- @output
|
|
-- PORT STATE SERVICE
|
|
-- 1604/udp open unknown
|
|
-- | citrix-enum-servers:
|
|
-- | CITRIXSRV01
|
|
-- |_ CITRIXSRV02
|
|
--
|
|
|
|
-- Version 0.2
|
|
|
|
-- Created 11/26/2009 - v0.1 - created by Patrik Karlsson <patrik@cqure.net>
|
|
-- Revised 11/26/2009 - v0.2 - minor packet documentation
|
|
|
|
|
|
author = "Patrik Karlsson"
|
|
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
|
|
categories = {"discovery", "safe"}
|
|
|
|
require "comm"
|
|
require "shortport"
|
|
|
|
portrule = shortport.portnumber(1604, "udp")
|
|
|
|
--
|
|
-- process the response from the server
|
|
-- @param response string, complete server response
|
|
-- @return string row delimited with \n containing all published applications
|
|
--
|
|
function process_server_response(response)
|
|
|
|
local pos, packet_len = bin.unpack("SS", response)
|
|
local server_name
|
|
local server_list = {}
|
|
|
|
if packet_len < 40 then
|
|
return
|
|
end
|
|
|
|
-- the list of published applications starts at offset 40
|
|
offset = 41
|
|
|
|
while offset < packet_len do
|
|
pos, server_name = bin.unpack("z", response:sub(offset))
|
|
offset = offset + pos - 1
|
|
table.insert(server_list, server_name)
|
|
end
|
|
|
|
return server_list
|
|
|
|
end
|
|
|
|
|
|
action = function(host, port)
|
|
|
|
local packet, counter, socket
|
|
local query = {}
|
|
local server_list = {}
|
|
|
|
--
|
|
-- Packets were intercepted from the Citrix Program Neighborhood client
|
|
-- They are used to query a server for it's list of published applications
|
|
--
|
|
-- We're really not interested in the responses to the first two packets
|
|
-- The third response contains the list of published applications
|
|
-- I couldn't find any documentation on this protocol so I'm providing
|
|
-- some brief information for the bits and bytes this script uses.
|
|
--
|
|
-- Spec. of response to query[2] that contains a list of published apps
|
|
--
|
|
-- offset size content
|
|
-- -------------------------
|
|
-- 0 16-bit Length
|
|
-- 12 32-bit Server IP (not used here)
|
|
-- 30 8-bit Last packet (1), More packets(0)
|
|
-- 40 - null-separated list of applications
|
|
--
|
|
query[0] = string.char(
|
|
0x1e, 0x00, -- Length: 30
|
|
0x01, 0x30, 0x02, 0xfd, 0xa8, 0xe3, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00
|
|
)
|
|
|
|
query[1] = string.char(
|
|
0x2a, 0x00, -- Length: 42
|
|
0x01, 0x32, 0x02, 0xfd, 0xa8, 0xe3, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
|
)
|
|
|
|
counter = 0
|
|
|
|
socket = nmap.new_socket()
|
|
socket:set_timeout(5000)
|
|
|
|
try = nmap.new_try(function() socket:close() end)
|
|
try(socket:connect(host, port))
|
|
|
|
-- send the two first packets and never look back
|
|
repeat
|
|
try(socket:send(query[counter]))
|
|
packet = try(socket:receive())
|
|
counter = counter + 1
|
|
until (counter>#query)
|
|
|
|
-- process the first response
|
|
server_list = process_server_response( packet )
|
|
|
|
--
|
|
-- the byte at offset 31 in the response has a really magic function
|
|
-- if it is set to zero (0) we have more response packets to process
|
|
-- if it is set to one (1) we have arrived at the last packet of our journey
|
|
--
|
|
while packet:sub(31,31) ~= string.char(0x01) do
|
|
packet = try( socket:receive() )
|
|
local tmp_table = process_server_response( packet )
|
|
|
|
for _, v in ipairs(tmp_table) do
|
|
table.insert(server_list, v)
|
|
end
|
|
end
|
|
|
|
if #server_list>0 then
|
|
nmap.set_port_state(host, port, "open")
|
|
end
|
|
|
|
socket:close()
|
|
|
|
return stdnse.format_output(true, server_list)
|
|
|
|
end
|