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
|
description = [[
Decodes the VSNNUM version number from an Oracle TNS listener.
]]
local shortport = require "shortport"
local nmap = require "nmap"
local comm = require "comm"
local stdnse = require "stdnse"
local string = require "string"
local U = require "lpeg-utility"
author = "Daniel Miller"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"version", "safe"}
portrule = function (host, port)
return (
-- -sV has an actual version for this, no need to send more probes and decode.
not (port.version and port.version.version and port.version.version ~= "")
-- Otherwise, normal checking for port numbers etc.
and shortport.version_port_or_service({1521,1522,1523}, "oracle-tns")(host, port)
)
end
-- Lifted from nmap-service-probes
-- TODO: Figure out if we can send a better probe than this. We might need to
-- send ADDRESS, CID, etc.
local oracle_tns_probe = "\0Z\0\0\x01\0\0\0\x016\x01,\0\0\x08\0\x7F\xFF\x7F\x08\0\0\0\x01\0 \0:\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x004\xE6\0\0\0\x01\0\0\0\0\0\0\0\0(CONNECT_DATA=(COMMAND=version))"
local ERR_CODES = {
["1189"] = "unauthorized",
["1194"] = "insecure transport",
["12154"] = "unknown identifier",
["12504"] = "requires service name",
["12505"] = "unknown sid",
["12514"] = "unknown service name",
}
local function decode_vsnnum (vsnnum)
vsnnum = tonumber(vsnnum)
return string.format("%d.%d.%d.%d.%d",
vsnnum >> 24,
vsnnum >> 20 & 0xF,
vsnnum >> 12 & 0xFF,
vsnnum >> 8 & 0xF,
vsnnum & 0xFF
)
end
do
local test_data = {
["135290880"] = "8.1.6.0.0",
["153092352"] = "9.2.0.1.0",
["169869568"] = "10.2.0.1.0",
["185599488"] = "11.1.0.6.0",
["202375680"] = "12.1.0.2.0",
["301989888"] = "18.0.0.0.0",
["318767104"] = "19.0.0.0.0",
["352321536"] = "21.0.0.0.0",
}
for n, v in pairs(test_data) do
local ver = decode_vsnnum(n)
assert(ver == v, ("%s == %s"):format(ver, v))
end
end
action = function (host, port)
local response
-- Did the service engine already do the hard work?
if port.version and port.version.service_fp then
-- Probes sent, replies received, but no match.
response = U.get_response(port.version.service_fp, "oracle-tns")
end
if not response then
-- Have to send the probe ourselves
local status
status, response = comm.exchange(host, port, oracle_tns_probe)
if not status then
stdnse.debug1("Couldn't get a response: %s", response)
return nil
end
end
local vsnnum = response and response:match("%(VSNNUM=(%d+)%)", 12)
port.version = port.version or {}
if vsnnum then
local version = decode_vsnnum(vsnnum)
port.version.product = "Oracle TNS listener"
port.version.version = version
local cpes = port.version.cpe or {}
cpes[#cpes+1] = "cpe:/a:oracle:database_server:" .. version
port.version.cpe = cpes
end
local errno = response and response:match("%(ERR=(%d+)%)", 12)
if errno then
port.version.extrainfo = ERR_CODES[errno] or ("error: "..errno)
end
if vsnnum or errno then
nmap.set_port_version(host, port, "hardmatched")
end
end
|