summaryrefslogtreecommitdiffstats
path: root/scripts/oracle-sid-brute.nse
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/oracle-sid-brute.nse')
-rw-r--r--scripts/oracle-sid-brute.nse171
1 files changed, 171 insertions, 0 deletions
diff --git a/scripts/oracle-sid-brute.nse b/scripts/oracle-sid-brute.nse
new file mode 100644
index 0000000..d559b54
--- /dev/null
+++ b/scripts/oracle-sid-brute.nse
@@ -0,0 +1,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