D7net
Home
Console
Upload
information
Create File
Create Folder
About
Tools
:
/
usr
/
share
/
nmap
/
scripts
/
Filename :
maxdb-info.nse
back
Copy
local bin = require "bin" local nmap = require "nmap" local shortport = require "shortport" local stdnse = require "stdnse" local tab = require "tab" local table = require "table" description = [[ Retrieves version and database information from a SAP Max DB database. ]] --- -- @usage -- nmap -p 7210 --script maxdb-info <ip> -- -- @output -- PORT STATE SERVICE REASON -- 7210/tcp open maxdb syn-ack -- | maxdb-info: -- | Version: 7.8.02 -- | Build: DBMServer 7.8.02 Build 021-121-242-175 -- | OS: UNIX -- | Instroot: /opt/sdb/MaxDB -- | Sysname: Linux 3.0.0-12-generic #20-Ubuntu SMP Fri Oct 7 14:56:25 UTC 2011 -- | Databases -- | instance path version kernel state -- | MAXDB /opt/sdb/MaxDB 7.8.02.21 fast running -- | MAXDB /opt/sdb/MaxDB 7.8.02.21 quick offline -- | MAXDB /opt/sdb/MaxDB 7.8.02.21 slow offline -- |_ MAXDB /opt/sdb/MaxDB 7.8.02.21 test offline -- author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = { "default", "version" } portrule = shortport.port_or_service(7210, "maxdb", "tcp") -- Sends and receive a MaxDB packet -- @param socket already connected to the server -- @param packet string containing the data to send -- @return status true on success, false on failure -- @return data string containing the raw response from the server local function exchPacket(socket, packet) local status, err = socket:send(packet) if ( not(status) ) then stdnse.print_debug(2, "Failed to send packet to server") return false, "Failed to send packet to server" end local data status, data= socket:receive() if ( not(status) ) then stdnse.print_debug(2, "Failed to read packet from server") return false, "Failed to read packet from server" end local pos, len = bin.unpack("<S", data) -- make sure we've got it all if ( len ~= #data ) then local tmp status, tmp = socket:receive_bytes(len - #data) if ( not(status) ) then stdnse.print_debug(2, "Failed to read packet from server") return false, "Failed to read packet from server" end data = data .. tmp end return true, data end -- Sends and receives a MaxDB command and does some very basic checks of the -- response. -- @param socket already connected to the server -- @param packet string containing the data to send -- @return status true on success, false on failure -- @return data string containing the raw response from the server local function exchCommand(socket, packet) local status, data = exchPacket(socket, packet) if( status ) then if ( #data < 26 ) then return false, "Response to short" end if ( "OK" ~= data:sub(25, 26) ) then return false, "Incorrect response from server (no OK found)" end end return status, data end -- Parses and decodes the raw version response from the server -- @param data string containing the raw response -- @return version_info table containining a number of dynamic fields based on -- the response from the server. The fields typically include: -- <code>VERSION</code>, <code>BUILD</code>, <code>OS</code>, -- <code>INSTROOT</code>,<code>LOGON</code>, <code>CODE</code>, -- <code>SWAP</code>, <code>UNICODE</code>, <code>INSTANCE</code>, -- <code>SYSNAME</code>, <code>MASKING</code>, -- <code>REPLYTREATMENT</code> and <code>SDBDBM_IPCLOCATION</code> local function parseVersion(data) local version_info = {} if ( #data > 27 ) then for _, line in ipairs(stdnse.strsplit("\n", data:sub(28))) do local key, val = line:match("^(%S+)%s-=%s(.*)%s*$") if ( key ) then version_info[key] = val end end end return version_info end -- Parses and decodes the raw database response from the server -- @param data string containing the raw response -- @return result string containing a table of database instance information local function parseDatabases(data) local result = tab.new(5) tab.addrow(result, "instance", "path", "version", "kernel", "state") for _, line in ipairs(stdnse.strsplit("\n", data:sub(28))) do local cols = {} cols.instance, cols.path, cols.ver, cols.kernel, cols.state = line:match("^(.-)%s*\t(.-)%s*\t(.-)%s*\t(.-)%s-\t(.-)%s-$") if ( cols.instance ) then tab.addrow(result, cols.instance, cols.path, cols.ver, cols.kernel, cols.state) end end return tab.dump(result) end action = function(host, port) -- this could really be more elegant, but it has to do for now local handshake = "5a000000035b000001000000ffffffff000004005a000000000242000409000000400000d03f00000040000070000000000500000004000000020000000300000749343231360004501c2a035201037201097064626d73727600" local dbm_version = "28000000033f000001000000ac130000000004002800000064626d5f76657273696f6e2020202020" local db_enum = "20000000033f000001000000ac130000000004002000000064625f656e756d20" local socket = nmap.new_socket() socket:set_timeout(10000) local status, err = socket:connect(host, port) local data status, data = exchPacket(socket, bin.pack("H", handshake)) if ( not(status) ) then return "\n ERROR: Failed to perform handshake with MaxDB server" end status, data = exchPacket(socket, bin.pack("H", dbm_version)) if ( not(status) ) then return "\n ERROR: Failed to request version information from server" end local version_info = parseVersion(data) if ( not(version_info) ) then return "\n ERROR: Failed to parse version information from server" end local result, filter = {}, {"Version", "Build", "OS", "Instroot", "Sysname"} for _, f in ipairs(filter) do table.insert(result, ("%s: %s"):format(f, version_info[f:upper()])) end status, data = exchCommand(socket, bin.pack("H", db_enum)) socket:close() if ( not(status) ) then return "\n ERROR: Failed to request version information from server" end local dbs = parseDatabases(data) table.insert(result, { name = "Databases", dbs } ) -- set the version information port.version.name = "maxdb" port.version.product = "SAP MaxDB" port.version.version = version_info.VERSION port.version.ostype = version_info.SYSNAME nmap.set_port_version(host, port) return stdnse.format_output(true, result) end