File: fingerprint-strings.nse

package info (click to toggle)
nmap 7.40-1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 50,080 kB
  • ctags: 26,777
  • sloc: ansic: 98,862; cpp: 64,063; python: 17,751; sh: 14,584; xml: 11,448; makefile: 2,635; perl: 2,585; yacc: 660; lex: 457; asm: 372; java: 45; objc: 43
file content (123 lines) | stat: -rw-r--r-- 3,392 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
local stdnse = require "stdnse"
local nmap = require "nmap"
local lpeg = require "lpeg"
local U = require "lpeg-utility"
local table = require "table"

description = [[
Prints the readable strings from service fingerprints of unknown services.
]]

---
--@usage
-- nmap -sV --script fingerprint-strings <target>
--
--@output
--| fingerprint-strings:
--|   DNSStatusRequest, GenericLines, LANDesk-RC, TLSSessionReq:
--|     bobo
--|     bobobo
--|   GetRequest, HTTPOptions, LPDString, NULL, RTSPRequest, giop, oracle-tns:
--|     bobobo
--|   Help, LDAPSearchReq, TerminalServer:
--|     bobobo
--|     bobobo
--|   Kerberos, NotesRPC, SIPOptions:
--|     bobo
--|   LDAPBindReq:
--|     bobobo
--|     bobo
--|     bobobo
--|   SSLSessionReq, SSLv23SessionReq:
--|     bobo
--|     bobobo
--|     bobo
--|   afp:
--|     bobo
--|_    bobo
--
--@args fingerprint-strings.n The number of printable ASCII characters required to make up a "string" (Default: 4)

author = "Daniel Miller"
categories = {"version"}

portrule = function (host, port)
  -- Run for any port that has a service fingerprint indicating an unknown service
  return port.version and port.version.service_fp
end

-- Create a table if necessary and append to it
local function safe_append (t, v)
  if t then
    t[#t+1] = v
  else
    t = {v}
  end
  return t
end

-- Extract strings of length n or greater.
local function strings (blob, n)
  local pat = lpeg.P {
    (lpeg.V "plain" + lpeg.V "skip")^1,
    -- Collect long-enough string of printable and space characters
    plain = (lpeg.R "\x21\x7e" + lpeg.V "space")^n,
    -- Collapse white space
    space = (lpeg.S " \t"^1)/" ",
    -- Skip anything else
    skip = ((lpeg.R "\x21\x7e"^-(n-1) * (lpeg.R "\0 " + lpeg.R "\x7f\xff")^1)^1)/"\n    ",
  }
  return lpeg.match(lpeg.Cs(pat), blob)
end

action = function(host, port)
  -- Get the table of probe responses
  local responses = U.parse_fp(port.version.service_fp)
  -- extract the probe names
  local probes = stdnse.keys(responses)
  -- If there were no probes (WEIRD!) we're done.
  if #probes <= 0 then
    return nil
  end

  local min = stdnse.get_script_args(SCRIPT_NAME .. ".n") or 4

  -- Ensure probes show up in the same order every time
  table.sort(probes)
  local invert = {}
  for i=1, #probes do
    -- Extract the strings from this probe
    local plain = strings(responses[probes[i]], min)
    if plain then
      stdnse.debug1("%s:>>>%s<<<", probes[i], plain)
      -- rearrange some whitespace to look nice
      plain = plain:gsub("^[\n ]*", "\n    "):gsub("[\n ]+$", "")
      -- Gather all the probes that had this same set of strings.
      if plain ~= "" then
        invert[plain] = safe_append(invert[plain], probes[i])
      end
    end
  end

  -- If none of the probes had sufficiently long strings, then we're done.
  if not next(invert) then
    return nil
  end

  -- Now reverse the representation so that strings are listed under probes
  local labels = {}
  local lookup = {}
  for plain, plist in pairs(invert) do
    local label = table.concat(plist, ", ")
    labels[#labels+1] = label
    lookup[label] = plain
  end
  -- Always keep sorted order!
  table.sort(labels)
  local out = stdnse.output_table()
  for i=1, #labels do
    out[labels[i]] = lookup[labels[i]]
  end
  -- XML output will not be very useful because this is intended for users eyes only.
  return out
end