mirror of
https://github.com/nmap/nmap.git
synced 2025-12-08 21:51:28 +00:00
o [NSE] Added maxdb-info script that tries to enumerate version and database
information from a SAP MaxDB database [Patrik]
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
# Nmap Changelog ($Id$); -*-text-*-
|
||||
|
||||
o [NSE] Added maxdb-info script that tries to enumerate version and database
|
||||
information from a SAP MaxDB database [Patrik]
|
||||
|
||||
o [NSE] Added nexpose-brute a script that performs password auditing against
|
||||
the Nexpose vulnerability scanner. [Vlatko Kosturjak]
|
||||
|
||||
|
||||
171
scripts/maxdb-info.nse
Normal file
171
scripts/maxdb-info.nse
Normal file
@@ -0,0 +1,171 @@
|
||||
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" }
|
||||
|
||||
require 'shortport'
|
||||
require 'tab'
|
||||
|
||||
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, "hardmatched")
|
||||
|
||||
return stdnse.format_output(true, result)
|
||||
end
|
||||
@@ -148,6 +148,7 @@ Entry { filename = "ldap-rootdse.nse", categories = { "discovery", "safe", } }
|
||||
Entry { filename = "ldap-search.nse", categories = { "discovery", "safe", } }
|
||||
Entry { filename = "lexmark-config.nse", categories = { "discovery", "safe", } }
|
||||
Entry { filename = "lltd-discovery.nse", categories = { "broadcast", "discovery", "safe", } }
|
||||
Entry { filename = "maxdb-info.nse", categories = { "default", "version", } }
|
||||
Entry { filename = "metasploit-xmlrpc-brute.nse", categories = { "brute", "intrusive", } }
|
||||
Entry { filename = "modbus-discover.nse", categories = { "discovery", "intrusive", } }
|
||||
Entry { filename = "mongodb-databases.nse", categories = { "default", "discovery", "safe", } }
|
||||
|
||||
Reference in New Issue
Block a user