Lucene search

K
nmapPatrik KarlssonNMAP:CITRIX-ENUM-SERVERS.NSE
HistoryDec 14, 2009 - 7:30 a.m.

citrix-enum-servers NSE Script

2009-12-1407:30:38
Patrik Karlsson
nmap.org
111

9.8 High

CVSS3

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

10 High

CVSS2

Access Vector

NETWORK

Access Complexity

LOW

Authentication

NONE

Confidentiality Impact

COMPLETE

Integrity Impact

COMPLETE

Availability Impact

COMPLETE

AV:N/AC:L/Au:N/C:C/I:C/A:C

0.973 High

EPSS

Percentile

99.8%

Extracts a list of Citrix servers from the ICA Browser service.

Example Usage

sudo ./nmap -sU --script=citrix-enum-servers -p 1604

Script Output

PORT     STATE SERVICE
1604/udp open  unknown
| citrix-enum-servers:
|   CITRIXSRV01
|_  CITRIXSRV02

Requires


local nmap = require "nmap"
local shortport = require "shortport"
local stdnse = require "stdnse"
local string = require "string"
local table = require "table"

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 <[email protected]>
-- Revised 11/26/2009 - v0.2 - minor packet documentation


author = "Patrik Karlsson"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"discovery", "safe"}


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 packet_len, pos = string.unpack("<I2", response)
  local server_name
  local server_list = {}

  if packet_len < 40 then
    return
  end

  -- the list of published applications starts at offset 40
  local offset = 41

  while offset < packet_len do
    server_name, pos = string.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 its 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)

  local 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) ~= "\x01" 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

9.8 High

CVSS3

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

10 High

CVSS2

Access Vector

NETWORK

Access Complexity

LOW

Authentication

NONE

Confidentiality Impact

COMPLETE

Integrity Impact

COMPLETE

Availability Impact

COMPLETE

AV:N/AC:L/Au:N/C:C/I:C/A:C

0.973 High

EPSS

Percentile

99.8%

Related for NMAP:CITRIX-ENUM-SERVERS.NSE