Lucene search

K
nmapPatrik KarlssonNMAP:ICAP-INFO.NSE
HistoryMay 22, 2012 - 6:34 p.m.

icap-info NSE Script

2012-05-2218:34:25
Patrik Karlsson
nmap.org
133

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%

Tests a list of known ICAP service names and prints information about any it detects. The Internet Content Adaptation Protocol (ICAP) is used to extend transparent proxy servers and is generally used for content filtering and antivirus scanning.

Example Usage

nmap -p 1344 <ip> --script icap-info

Script Output

PORT     STATE SERVICE
1344/tcp open  unknown
| icap-info:
|   /avscan
|     Service: C-ICAP/0.1.6 server - Clamav/Antivirus service
|     ISTag: CI0001-000-0973-6314940
|   /echo
|     Service: C-ICAP/0.1.6 server - Echo demo service
|     ISTag: CI0001-XXXXXXXXX
|   /srv_clamav
|     Service: C-ICAP/0.1.6 server - Clamav/Antivirus service
|     ISTag: CI0001-000-0973-6314940
|   /url_check
|     Service: C-ICAP/0.1.6 server - Url_Check demo service
|_    ISTag: CI0001-XXXXXXXXX

Requires


local nmap = require "nmap"
local match = require "match"
local shortport = require "shortport"
local stdnse = require "stdnse"
local stringaux = require "stringaux"
local table = require "table"

description = [[
Tests a list of known ICAP service names and prints information about
any it detects. The Internet Content Adaptation Protocol (ICAP) is
used to extend transparent proxy servers and is generally used for
content filtering and antivirus scanning.
]]

---
-- @usage
-- nmap -p 1344 <ip> --script icap-info
--
-- @output
-- PORT     STATE SERVICE
-- 1344/tcp open  unknown
-- | icap-info:
-- |   /avscan
-- |     Service: C-ICAP/0.1.6 server - Clamav/Antivirus service
-- |     ISTag: CI0001-000-0973-6314940
-- |   /echo
-- |     Service: C-ICAP/0.1.6 server - Echo demo service
-- |     ISTag: CI0001-XXXXXXXXX
-- |   /srv_clamav
-- |     Service: C-ICAP/0.1.6 server - Clamav/Antivirus service
-- |     ISTag: CI0001-000-0973-6314940
-- |   /url_check
-- |     Service: C-ICAP/0.1.6 server - Url_Check demo service
-- |_    ISTag: CI0001-XXXXXXXXX
--
--

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


portrule = shortport.port_or_service(1344, "icap")

local function fail(err) return stdnse.format_output(false, err) end

local function parseResponse(resp)
  if ( not(resp) ) then
    return
  end

  local resp_p = { header = {}, rawheader = {} }
  local resp_tbl = stringaux.strsplit("\r?\n", resp)

  if ( not(resp_tbl) or #resp_tbl == 0 ) then
    stdnse.debug2("Received an invalid response from server")
    return
  end

  resp_p.status = tonumber(resp_tbl[1]:match("^ICAP/1%.0 (%d*) .*$"))
  resp_p['status-line'] = resp_tbl[1]

  for i=2, #resp_tbl do
    local key, val = resp_tbl[i]:match("^([^:]*):%s*(.*)$")
    if ( not(key) or not(val) ) then
      stdnse.debug2("Failed to parse header: %s", resp_tbl[i])
    else
      resp_p.header[key:lower()] = val
    end
    table.insert(resp_p.rawheader, resp_tbl[i])
  end
  return resp_p
end

action = function(host, port)

  local services = {"/avscan", "/echo", "/srv_clamav", "/url_check", "/nmap" }
  local headers = {"Service", "ISTag"}
  local probe = {
    "OPTIONS icap://%s%s ICAP/1.0",
    "Host: %s",
    "User-Agent: nmap icap-client/0.01",
    "Encapsulated: null-body=0"
  }
  local hostname = stdnse.get_hostname(host)
  local result = {}

  for _, service in ipairs(services) do
    local socket = nmap.new_socket()
    socket:set_timeout(5000)
    if ( not(socket:connect(host, port)) ) then
      return fail("Failed to connect to server")
    end

    local request = (table.concat(probe, "\r\n") .. "\r\n\r\n"):format(hostname, service, hostname)

    if ( not(socket:send(request)) ) then
      socket:close()
      return fail("Failed to send request to server")
    end

    local status, resp = socket:receive_buf(match.pattern_limit("\r\n\r\n", 2048), false)
    if ( not(status) ) then
      return fail("Failed to receive response from server")
    end

    local resp_p = parseResponse(resp)
    if ( resp_p and resp_p.status == 200 ) then
      local result_part = { name = service }
      for _, h in ipairs(headers) do
        if ( resp_p.header[h:lower()] ) then
          table.insert(result_part, ("%s: %s"):format(h, resp_p.header[h:lower()]))
        end
      end
      table.insert(result, result_part)
    end
  end
  return stdnse.format_output(true, result)
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:ICAP-INFO.NSE