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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
|
local io = require "io"
local nmap = require "nmap"
local shortport = require "shortport"
local stdnse = require "stdnse"
local string = require "string"
local table = require "table"
description = [[
Guesses Oracle instance/SID names against the TNS-listener.
If the <code>oraclesids</code> script argument is not used to specify an
alternate file, the default <code>oracle-sids</code> file will be used.
License to use the <code>oracle-sids</code> file was granted by its
author, Alexander Kornbrust (http://seclists.org/nmap-dev/2009/q4/645).
]]
---
-- @args oraclesids A file containing SIDs to try.
--
-- @usage
-- nmap --script=oracle-sid-brute --script-args=oraclesids=/path/to/sidfile -p 1521-1560 <host>
-- nmap --script=oracle-sid-brute -p 1521-1560 <host>
--
-- @output
-- PORT STATE SERVICE REASON
-- 1521/tcp open oracle syn-ack
-- | oracle-sid-brute:
-- | orcl
-- | prod
-- |_ devel
-- Version 0.3
-- Created 12/10/2009 - v0.1 - created by Patrik Karlsson <patrik@cqure.net>
-- Revised 12/11/2009 - v0.2 - Added tns_type, split packet creation to header & data
-- Revised 12/14/2009 - v0.3 - Fixed ugly file_exist kludge
author = "Patrik Karlsson"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"intrusive", "brute"}
portrule = shortport.port_or_service(1521, 'oracle-tns')
-- A table containing the different TNS types ... not complete :)
local tns_type = {CONNECT=1, REFUSE=4, REDIRECT=5, RESEND=11}
--- Creates a TNS header
-- A lot of values are still hardcoded ...
--
-- @param packetType string containing the type of TNS packet
-- @param packetLength number defining the length of the DATA segment of the packet
--
-- @return string with the raw TNS header
--
local function create_tns_header(packetType, packetLength)
local request = string.pack( ">I2 I2 BB I2",
packetLength + 34, -- Packet Length
0, -- Packet Checksum
tns_type[packetType], -- Packet Type
0, -- Reserved Byte
0 -- Header Checksum
)
return request
end
--- Creates a TNS connect packet
--
-- @param host_ip string containing the IP of the remote host
-- @param port_no number containing the remote port of the Oracle instance
-- @param sid string containing the SID against which to attempt to connect
--
-- @return string containing the raw TNS packet
--
local function create_connect_packet( host_ip, port_no, sid )
local connect_data = string.format(
"(DESCRIPTION=(CONNECT_DATA=(SID=%s)(CID=(PROGRAM=)(HOST=__jdbc__)(USER=)))\z
(ADDRESS=(PROTOCOL=tcp)(HOST=%s)(PORT=%d)))", sid, host_ip, port_no)
local data = string.pack(">I2 I2 I2 I2 I2 I2 I2 I2 I2 I2 I4 BB",
308, -- Version
300, -- Version (Compatibility)
0, -- Service Options
2048, -- Session Data Unit Size
32767, -- Maximum Transmission Data Unit Size
20376, -- NT Protocol Characteristics
0, -- Line Turnaround Value
1, -- Value of 1 in Hardware
connect_data:len(), -- Length of connect data
34, -- Offset to connect data
0, -- Maximum Receivable Connect Data
1, -- Connect Flags 0
1 -- Connect Flags 1
)
.. connect_data
local header = create_tns_header("CONNECT", connect_data:len() )
return header .. data
end
--- Process a TNS response and extracts Length, Checksum and Type
--
-- @param packet string as a raw TNS response
-- @return table with Length, Checksum and Type set
--
local function process_tns_packet( packet )
local tnspacket = {}
-- just pull out the bare minimum to be able to match
tnspacket.Length, tnspacket.Checksum, tnspacket.Type = string.unpack(">I2I2B", packet)
return tnspacket
end
action = function(host, port)
local found_sids = {}
local socket = nmap.new_socket()
local catch = function() socket:close() end
local try = nmap.new_try(catch)
local request, response, tns_packet
local sidfile
socket:set_timeout(5000)
-- open the sid file specified by the user or fallback to the default oracle-sids file
local sidfilename = nmap.registry.args.oraclesids or nmap.fetchfile("nselib/data/oracle-sids")
sidfile = io.open(sidfilename)
if not sidfile then
return
end
-- read sids line-by-line from the sidfile
for sid in sidfile:lines() do
-- check for comments
if not sid:match("#!comment:") then
try(socket:connect(host, port))
request = create_connect_packet( host.ip, port.number, sid )
try(socket:send(request))
response = try(socket:receive_bytes(1))
tns_packet = process_tns_packet(response)
-- If we get anything other than REFUSE consider it as a valid SID
if tns_packet.Type ~= tns_type.REFUSE then
table.insert(found_sids, sid)
end
try(socket:close())
end
end
sidfile:close()
return stdnse.format_output(true, found_sids)
end
|