Lucene search

K
nmapPatrik KarlssonNMAP:MAXDB-INFO.NSE
HistoryNov 17, 2011 - 10:12 p.m.

maxdb-info NSE Script

2011-11-1722:12:59
Patrik Karlsson
nmap.org
147

9.8 High

CVSS3

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

10 High

CVSS2

Access Vector

NETWORK

Access Complexity

LOW

Authentication

NONE

Confidentiality Impact

COMPLETE

Integrity Impact

COMPLETE

Availability Impact

COMPLETE

AV:N/AC:L/Au:N/C:C/I:C/A:C

0.973 High

EPSS

Percentile

99.8%

Retrieves version and database information from a SAP Max DB database.

Example Usage

nmap -p 7210 --script maxdb-info <ip>

Script 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

Requires


local nmap = require "nmap"
local shortport = require "shortport"
local stdnse = require "stdnse"
local string = require "string"
local stringaux = require "stringaux"
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 https://nmap.org/book/man-legal.html"
categories = { "default", "version", "safe" }


portrule = shortport.version_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.debug2("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.debug2("Failed to read packet from server")
    return false, "Failed to read packet from server"
  end
  local len = string.unpack("<I2", 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.debug2("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 containing 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(stringaux.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(stringaux.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

local function fail (err) return stdnse.format_output(false, err) 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, stdnse.fromhex( handshake))
  if ( not(status) ) then
    return fail("Failed to perform handshake with MaxDB server")
  end

  status, data = exchPacket(socket, stdnse.fromhex( dbm_version))
  if ( not(status) ) then
    return fail("Failed to request version information from server")
  end

  local version_info = parseVersion(data)
  if ( not(version_info) ) then
    return fail("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, stdnse.fromhex( db_enum))
  socket:close()
  if ( not(status) ) then
    return fail("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

9.8 High

CVSS3

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

10 High

CVSS2

Access Vector

NETWORK

Access Complexity

LOW

Authentication

NONE

Confidentiality Impact

COMPLETE

Integrity Impact

COMPLETE

Availability Impact

COMPLETE

AV:N/AC:L/Au:N/C:C/I:C/A:C

0.973 High

EPSS

Percentile

99.8%

Related for NMAP:MAXDB-INFO.NSE