diff options
Diffstat (limited to 'scripts/oracle-sid-brute.nse')
-rw-r--r-- | scripts/oracle-sid-brute.nse | 171 |
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 |