mirror of
https://github.com/nmap/nmap.git
synced 2025-12-14 03:39:02 +00:00
o [NSE] Add new DB2 library and two scripts
- db2-brute.nse uses the unpwdb library to guess credentials for DB2 - db2-info.nse re-write of Tom Sellers script to use the new library [Patrik]
This commit is contained in:
166
scripts/db2-brute.nse
Normal file
166
scripts/db2-brute.nse
Normal file
@@ -0,0 +1,166 @@
|
||||
description = [[
|
||||
Performs password guessing against IBM DB2
|
||||
]]
|
||||
|
||||
---
|
||||
-- @usage
|
||||
-- nmap -p 50000 --script db2-brute <host>
|
||||
--
|
||||
-- @output
|
||||
-- 50000/tcp open ibm-db2
|
||||
-- | db2-brute:
|
||||
-- |_ db2admin:db2admin => Login Correct
|
||||
--
|
||||
--
|
||||
-- @args db2-brute.threads the amount of accounts to attempt to brute force in parallell (default 10)
|
||||
-- @args db2-brute.dbname the database name against which to guess passwords (default SAMPLE)
|
||||
--
|
||||
|
||||
author = "Patrik Karlsson"
|
||||
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
|
||||
categories={"intrusive", "auth"}
|
||||
|
||||
require "stdnse"
|
||||
require "shortport"
|
||||
require "db2"
|
||||
require "unpwdb"
|
||||
|
||||
-- Version 0.3
|
||||
-- Created 05/08/2010 - v0.1 - created by Patrik Karlsson <patrik@cqure.net>
|
||||
-- Revised 05/09/2010 - v0.2 - re-wrote as multi-threaded <patrik@cqure.net>
|
||||
-- Revised 05/10/2010 - v0.3 - revised parallellised design <patrik@cqure.net>
|
||||
|
||||
portrule = shortport.port_or_service({50000,60000},"ibm-db2", "tcp", {"open", "open|filtered"})
|
||||
|
||||
--- Credential iterator
|
||||
--
|
||||
-- @param usernames iterator from unpwdb
|
||||
-- @param passwords iterator from unpwdb
|
||||
-- @return username string
|
||||
-- @return password string
|
||||
local function new_usrpwd_iterator (usernames, passwords)
|
||||
local function next_username_password ()
|
||||
for username in usernames do
|
||||
for password in passwords do
|
||||
coroutine.yield(username, password)
|
||||
end
|
||||
passwords("reset")
|
||||
end
|
||||
while true do coroutine.yield(nil, nil) end
|
||||
end
|
||||
return coroutine.wrap(next_username_password)
|
||||
end
|
||||
|
||||
--- Iterates over the password list and guesses passwords
|
||||
--
|
||||
-- @param host table with information as recieved by <code>action</code>
|
||||
-- @param port table with information as recieved by <code>action</code>
|
||||
-- @param database string containing the database name
|
||||
-- @param username string containing the username against which to guess
|
||||
-- @param valid_accounts table in which to store found accounts
|
||||
doLogin = function( host, port, database, creds, valid_accounts )
|
||||
local helper, status, response, passwords
|
||||
local condvar = nmap.condvar( valid_accounts )
|
||||
|
||||
for username, password in creds do
|
||||
-- Checks if a password was already discovered for this account
|
||||
if ( nmap.registry.db2users == nil or nmap.registry.db2users[username] == nil ) then
|
||||
helper = db2.Helper:new()
|
||||
helper:connect( host, port )
|
||||
stdnse.print_debug( "Trying %s/%s against %s...", username, password, host.ip )
|
||||
status, response = helper:login( database, username, password )
|
||||
helper:close()
|
||||
|
||||
if ( status ) then
|
||||
-- Add credentials for future db2 scripts to use
|
||||
if nmap.registry.db2users == nil then
|
||||
nmap.registry.db2users = {}
|
||||
end
|
||||
nmap.registry.db2users[username]=password
|
||||
table.insert( valid_accounts, string.format("%s:%s => Login Correct", username, password:len()>0 and password or "<empty>" ) )
|
||||
end
|
||||
end
|
||||
end
|
||||
condvar("broadcast")
|
||||
end
|
||||
|
||||
--- Checks if the supplied database exists
|
||||
--
|
||||
-- @param host table with information as recieved by <code>action</code>
|
||||
-- @param port table with information as recieved by <code>action</code>
|
||||
-- @param database string containing the database name
|
||||
-- @return status true on success, false on failure
|
||||
isValidDb = function( host, port, database )
|
||||
local status, response
|
||||
local helper = db2.Helper:new()
|
||||
|
||||
helper:connect( host, port )
|
||||
-- Authenticate with a static probe account to see if the db is valid
|
||||
status, response = helper:login( database, "dbnameprobe1234", "dbnameprobe1234" )
|
||||
helper:close()
|
||||
|
||||
if ( not(status) and response:match("Database not found") ) then
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
--- Returns the amount of currenlty active threads
|
||||
--
|
||||
-- @param threads table containing the list of threads
|
||||
-- @return count number containing the number of non-dead threads
|
||||
threadCount = function( threads )
|
||||
local count = 0
|
||||
|
||||
for thread in pairs(threads) do
|
||||
if ( coroutine.status(thread) == "dead" ) then
|
||||
threads[thread] = nil
|
||||
else
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
return count
|
||||
end
|
||||
|
||||
action = function( host, port )
|
||||
|
||||
local result, response, status = {}, nil, nil
|
||||
local valid_accounts, threads = {}, {}
|
||||
local usernames, passwords, creds
|
||||
local database = nmap.registry.args['db2-brute.dbname'] or "SAMPLE"
|
||||
local condvar = nmap.condvar( valid_accounts )
|
||||
local max_threads = nmap.registry.args['db2-brute.threads'] and tonumber( nmap.registry.args['db2-brute.threads'] ) or 10
|
||||
|
||||
-- Check if the DB specified is valid
|
||||
if( not(isValidDb(host, port, database)) ) then
|
||||
return ("The databases %s was not found. (Use --script-args db2-brute.dbname=<dbname> to specify database)"):format(database)
|
||||
end
|
||||
|
||||
status, usernames = unpwdb.usernames()
|
||||
if ( not(status) ) then
|
||||
return "Failed to load usernames"
|
||||
end
|
||||
|
||||
-- make sure we have a valid pw file
|
||||
status, passwords = unpwdb.passwords()
|
||||
if ( not(status) ) then
|
||||
return "Failed to load passwords"
|
||||
end
|
||||
|
||||
creds = new_usrpwd_iterator( usernames, passwords )
|
||||
|
||||
stdnse.print_debug("Starting brute force with %d threads", max_threads )
|
||||
|
||||
for i=1,max_threads do
|
||||
local co = stdnse.new_thread( doLogin, host, port, database, creds, valid_accounts )
|
||||
threads[co] = true
|
||||
end
|
||||
|
||||
-- wait for all threads to finnish running
|
||||
while threadCount(threads)>0 do
|
||||
condvar("wait")
|
||||
end
|
||||
|
||||
return stdnse.format_output(true, valid_accounts)
|
||||
|
||||
end
|
||||
@@ -1,356 +1,89 @@
|
||||
description = [[
|
||||
Attempts to extract information from IBM DB2 Server instances. The script sends a
|
||||
DB2 EXCSAT (exchange server attributes) command packet and parses the response.
|
||||
]]
|
||||
|
||||
-- rev 1.3 (2009-12-16)
|
||||
|
||||
---
|
||||
-- @output
|
||||
-- PORT STATE SERVICE
|
||||
-- 50000/tcp open ibm-db2
|
||||
-- | db2-info: DB2 Version: 8.02.9
|
||||
-- | Server Platform: QDB2/SUN
|
||||
-- | Instance Name: db2inst1
|
||||
-- |_ External Name: db2inst1db2agent00002B430
|
||||
|
||||
author = "Tom Sellers"
|
||||
|
||||
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
|
||||
|
||||
categories = {"safe", "discovery", "version"}
|
||||
|
||||
require "stdnse"
|
||||
require "shortport"
|
||||
|
||||
portrule = shortport.port_or_service({50000,60000},"ibm-db2", "tcp", {"open", "open|filtered"})
|
||||
|
||||
-- This function processes a section of the EXCSAT response packet
|
||||
|
||||
--@param response This is the data returned from the server as a result of the client query.
|
||||
--@param position This is the position within the response that this function will start processing from.
|
||||
--@param ebcdic2ascii This is a table containing a conversion chart for returning the ASCII value of EBCDIC encoded HEX value.
|
||||
--@return section_length This is the length of the currect section. Will be used to move position for processing next section.
|
||||
--@return data_string This string contains the data pulled from this section of the server response.
|
||||
local function process_block(response, position, ebcdic2ascii)
|
||||
|
||||
-- This fuction assumes that the current position is the start of a section within
|
||||
-- the DB2 EXCSAT response packet
|
||||
|
||||
-- Get the length of this section of the response packet
|
||||
local section_length = string.format("%d",string.byte(response,position +1)) .. string.format("%d",string.byte(response,position + 2))
|
||||
position = position + 2
|
||||
|
||||
-- locate the data string and convert it from EBCDIC to ASCII
|
||||
local i = 0
|
||||
local data_string = ""
|
||||
for i = (position + 3),(position + section_length -2 ),1 do
|
||||
-- stdnse.print_debug("%s","INFO: Current postion (i) = " .. i)
|
||||
-- stdnse.print_debug("%s","INFO: Hex value = " .. string.format("%x",string.byte(response,i)))
|
||||
-- stdnse.print_debug("%s","INFO: Current data_string = " .. data_string)
|
||||
if string.format("%x",string.byte(response,i)) == "0" then
|
||||
break
|
||||
end
|
||||
data_string = data_string .. ebcdic2ascii[string.format("%x",string.byte(response,i))]
|
||||
end
|
||||
|
||||
return section_length, data_string
|
||||
|
||||
end -- fuction process_block
|
||||
|
||||
|
||||
|
||||
action = function(host, port)
|
||||
|
||||
local ebcdic2ascii = {
|
||||
-- The following reference was used for this table: http://www.simotime.com/asc2ebc1.htm
|
||||
["00"] = string.format("%c", 00),
|
||||
["40"] = " ",
|
||||
["81"] = "a",
|
||||
["82"] = "b",
|
||||
["83"] = "c",
|
||||
["84"] = "d",
|
||||
["85"] = "e",
|
||||
["86"] = "f",
|
||||
["87"] = "g",
|
||||
["88"] = "h",
|
||||
["89"] = "i",
|
||||
["91"] = "j",
|
||||
["92"] = "k",
|
||||
["93"] = "l",
|
||||
["94"] = "m",
|
||||
["95"] = "n",
|
||||
["96"] = "o",
|
||||
["97"] = "p",
|
||||
["98"] = "q",
|
||||
["99"] = "r",
|
||||
["a2"] = "s",
|
||||
["a3"] = "t",
|
||||
["a4"] = "u",
|
||||
["a5"] = "v",
|
||||
["a6"] = "w",
|
||||
["a7"] = "x",
|
||||
["a8"] = "y",
|
||||
["a9"] = "z",
|
||||
["c1"] = "A",
|
||||
["c2"] = "B",
|
||||
["c3"] = "C",
|
||||
["c4"] = "D",
|
||||
["c5"] = "E",
|
||||
["c6"] = "F",
|
||||
["c7"] = "G",
|
||||
["c8"] = "H",
|
||||
["c9"] = "I",
|
||||
["d1"] = "J",
|
||||
["d2"] = "K",
|
||||
["d3"] = "L",
|
||||
["d4"] = "M",
|
||||
["d5"] = "N",
|
||||
["d6"] = "O",
|
||||
["d7"] = "P",
|
||||
["d8"] = "Q",
|
||||
["d9"] = "R",
|
||||
["e2"] = "S",
|
||||
["e3"] = "T",
|
||||
["e4"] = "U",
|
||||
["e5"] = "V",
|
||||
["e6"] = "W",
|
||||
["e7"] = "X",
|
||||
["e8"] = "Y",
|
||||
["e9"] = "Z",
|
||||
["f0"] = 0,
|
||||
["f1"] = 1,
|
||||
["f2"] = 2,
|
||||
["f3"] = 3,
|
||||
["f4"] = 4,
|
||||
["f5"] = 5,
|
||||
["f6"] = 6,
|
||||
["f7"] = 7,
|
||||
["f8"] = 8,
|
||||
["f9"] = 9,
|
||||
["4b"] = ".",
|
||||
["4c"] = "<",
|
||||
["4d"] = "(",
|
||||
["4e"] = "+",
|
||||
["4f"] = "|",
|
||||
["5a"] = "!",
|
||||
["5b"] = "$",
|
||||
["5c"] = "*",
|
||||
["5d"] = ")",
|
||||
["5e"] = ";",
|
||||
["60"] = "-",
|
||||
["61"] = "/",
|
||||
["6b"] = ",",
|
||||
["6c"] = "%",
|
||||
["6d"] = "_",
|
||||
["6e"] = ">",
|
||||
["6f"] = "?",
|
||||
["79"] = "`",
|
||||
["7a"] = ":",
|
||||
["7b"] = "#",
|
||||
["7c"] = "@",
|
||||
["7d"] = "'",
|
||||
["7e"] = "=",
|
||||
["7f"] = "\"",
|
||||
["a1"] = "~",
|
||||
["ba"] = "[",
|
||||
["bb"] = "]",
|
||||
["c0"] = "{",
|
||||
["d0"] = "}",
|
||||
["e0"] = "\\" -- escape the \ character
|
||||
}
|
||||
|
||||
-- ebcdic2ascii does not contain all value, set a default value
|
||||
-- to improve stability.
|
||||
setmetatable(ebcdic2ascii, { __index = function() return " " end })
|
||||
|
||||
-- create the socket used for our connection
|
||||
local socket = nmap.new_socket()
|
||||
|
||||
-- set a reasonable timeout value
|
||||
socket:set_timeout(10000)
|
||||
|
||||
-- do some exception handling / cleanup
|
||||
local catch = function()
|
||||
stdnse.print_debug("%s", "db2-info: ERROR communicating with " .. host.ip .. " on port " .. port.number .. "/" .. port.protocol)
|
||||
socket:close()
|
||||
end
|
||||
|
||||
local try = nmap.new_try(catch)
|
||||
|
||||
try(socket:connect(host.ip, port.number, "tcp"))
|
||||
|
||||
-- Build DB2 EXCSAT (exchange server attributes) command packet
|
||||
|
||||
local query = string.char(0x00, 0x98, 0xd0, 0x41, 0x00, 0x01, 0x00, 0x92, 0x10, 0x41) -- Header
|
||||
|
||||
-- NOTE: The server's response packet is in the same format at the client query packet being built
|
||||
-- in the section below.
|
||||
|
||||
-- External Name section: first two bytes (00,48) are section length in HEX, next bytes (11,5e) are section identifier for External Name
|
||||
-- In this packet the external name is 'db2jcc_application JCC03570300' encoded in EBCDIC
|
||||
query = query .. string.char(0x00, 0x48, 0x11, 0x5e, 0x84, 0x82, 0xf2, 0x91, 0x83, 0x83, 0x6d, 0x81, 0x97, 0x97, 0x93, 0x89)
|
||||
query = query .. string.char(0x83, 0x81, 0xa3, 0x89, 0x96, 0x95, 0x40, 0x40, 0xd1, 0xc3, 0xc3, 0xf0, 0xf3, 0xf5, 0xf7, 0xf0)
|
||||
query = query .. string.char(0xf3, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)
|
||||
query = query .. string.char(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)
|
||||
query = query .. string.char(0x00, 0x00, 0x00, 0x60, 0xf0, 0xf0, 0xf0, 0xf1)
|
||||
|
||||
-- Client Name section: first two bytes (00,16) are section length in HEX, next two bytes (11,6d) are section identifier for Server Name
|
||||
-- In the request packet Server Name = client name. The value here is all spaces, encoded in EBCDIC
|
||||
query = query .. string.char(0x00, 0x16, 0x11, 0x6d, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40)
|
||||
query = query .. string.char(0x40, 0x40, 0x40, 0x40, 0x40, 0x40)
|
||||
|
||||
-- Product Release Level section: This section is not as important in the client query as it is in the server response.
|
||||
-- The first two bytes (00,0c) are section length in HEX, next two bytes (11,5a) are section identifier for Product Release Level
|
||||
-- The value here is 'JCC03570' encoded in EBCDIC
|
||||
query = query .. string.char(0x00, 0x0c, 0x11, 0x5a, 0xd1, 0xc3, 0xc3, 0xf0, 0xf3, 0xf5, 0xf7, 0xf0)
|
||||
|
||||
-- Manager level section: first two bytes (00,18) are section length in HEX, next two bytes (14,04) are section identifier for Manager-Level List
|
||||
query = query .. string.char(0x00, 0x18, 0x14, 0x04, 0x14, 0x03, 0x00, 0x07, 0x24, 0x07, 0x00, 0x0a, 0x24, 0x0f, 0x00, 0x08)
|
||||
query = query .. string.char(0x14, 0x40, 0x00, 0x09, 0x14, 0x74, 0x00, 0x08)
|
||||
|
||||
-- Server Class section: first two bytes (00,0c) are section length in HEX, next two bytes (11,47) are section identifier for Server Class Name
|
||||
-- This section is essentially platform software information. The value here is 'QDB2/JBM' encoded in EBCDIC)
|
||||
query = query .. string.char(0x00, 0x0c, 0x11, 0x47, 0xd8, 0xc4, 0xc2, 0xf2, 0x61, 0xd1, 0xe5, 0xd4)
|
||||
|
||||
-- Access Security section
|
||||
query = query .. string.char(0x00, 0x26, 0xd0, 0x01, 0x00, 0x02, 0x00, 0x20, 0x10, 0x6d, 0x00, 0x06, 0x11, 0xa2, 0x00, 0x03)
|
||||
|
||||
|
||||
-- Database name section: This is the client's query for a specific database. A DB2 default database name, 'db2insta1', was chosen.
|
||||
-- It is encoded below in EBCDIC. The first two bytes (00,16) are section length in HEX, next two bytes (21,10) are section identifier
|
||||
-- for Relational Database Name
|
||||
query = query .. string.char(0x00, 0x16, 0x21, 0x10, 0x84, 0x82, 0xf2, 0x89, 0x95, 0xa2, 0xa3, 0xf1, 0x40, 0x40, 0x40, 0x40)
|
||||
query = query .. string.char(0x40, 0x40, 0x40, 0x40, 0x40, 0x40)
|
||||
|
||||
try(socket:send(query))
|
||||
|
||||
local status
|
||||
local response
|
||||
|
||||
-- read in any response we might get
|
||||
status, response = socket:receive()
|
||||
|
||||
socket:close()
|
||||
|
||||
if (not status) or (response == "TIMEOUT") or (response == nil) then
|
||||
stdnse.print_debug("%s","db2-info: ERROR: No data, ending communications with " .. host.ip .. ":" .. port.number .. "/" .. port.protocol)
|
||||
return
|
||||
end
|
||||
|
||||
local position = 0
|
||||
|
||||
-- Check to see if the data is actually a DB2 DDM EXCSAT response.
|
||||
-- 0d in the 3rd byte of the data section seems to be a reliable test.
|
||||
if string.format("%x",string.byte(response,position + 3)) ~= "d0" then
|
||||
return
|
||||
end
|
||||
|
||||
local bytes = " "
|
||||
local len_response = string.len(response) - 2
|
||||
|
||||
-- Parse response until the EXCSAT identifier is found. From here we should
|
||||
-- be able to find everything else.
|
||||
while (bytes ~= "1443") and (position <= len_response) do
|
||||
bytes = string.format("%x",string.byte(response,position +1)) .. string.format("%x",string.byte(response,position + 2))
|
||||
if bytes == nil then
|
||||
return
|
||||
end
|
||||
position = position + 2
|
||||
end
|
||||
|
||||
if position >= len_response then
|
||||
-- If this section is true then this either not a valid response or
|
||||
-- it is in a format that we have not seen. Exit cleanly.
|
||||
return
|
||||
end
|
||||
|
||||
-- ****************************************************************************
|
||||
-- Process the Server class section of the response packet
|
||||
-- ****************************************************************************
|
||||
local len_external_name, external_name = process_block(response, position, ebcdic2ascii)
|
||||
|
||||
-- ****************************************************************************
|
||||
-- Process the Manager Level section of the response packet
|
||||
-- ****************************************************************************
|
||||
-- Move the position to the beginning of the current section
|
||||
position = position + len_external_name
|
||||
|
||||
-- Get the length of the next block, Wireshark calls this "Manager-Level list"
|
||||
-- We are going to skip over this section
|
||||
local len_manager_level = string.format("%d",string.byte(response, position +1)) .. string.format("%d",string.byte(response,position + 2))
|
||||
|
||||
|
||||
-- ****************************************************************************
|
||||
-- Process the Server class section of the response packet
|
||||
-- ****************************************************************************
|
||||
-- Move the position to the beginning of the current section
|
||||
position = position + len_manager_level
|
||||
local len_server_class, server_class = process_block(response, position, ebcdic2ascii)
|
||||
|
||||
|
||||
-- ****************************************************************************
|
||||
-- Process the Server name section of the response packet
|
||||
-- ****************************************************************************
|
||||
-- Move the position to the beginning of the current section
|
||||
position = position + len_server_class
|
||||
local len_server_name, server_name = process_block(response, position, ebcdic2ascii)
|
||||
|
||||
-- ****************************************************************************
|
||||
-- Process the Server version section of the response packet
|
||||
-- ****************************************************************************
|
||||
-- Move the position to the beginning of the current section
|
||||
position = position + len_server_name
|
||||
|
||||
local len_server_version, server_version = process_block(response, position, ebcdic2ascii)
|
||||
|
||||
if string.sub(server_version,1,3) == "SQL" then
|
||||
local major_version = string.sub(server_version,4,5)
|
||||
|
||||
-- strip the leading 0 from the major version, for consistency with
|
||||
-- nmap-service-probes results
|
||||
if string.sub(major_version,1,1) == "0" then
|
||||
major_version = string.sub(major_version,2)
|
||||
end
|
||||
local minor_version = string.sub(server_version,6,7)
|
||||
local hotfix = string.sub(server_version,8)
|
||||
server_version = major_version .. "." .. minor_version .. "." .. hotfix
|
||||
end
|
||||
|
||||
-- Try to determine which of the two values (probe version vs script) has more
|
||||
-- precision. A couple DB2 versions send DB2 UDB 7.1 vs SQL090204 (9.02.04)
|
||||
local _
|
||||
local current_count = 0
|
||||
if port.version.version ~= nil then
|
||||
_, current_count = string.gsub(port.version.version, "%.", "%.")
|
||||
end
|
||||
|
||||
local new_count = 0
|
||||
if server_version ~= nil then
|
||||
_, new_count = string.gsub(server_version, "%.", "%.")
|
||||
end
|
||||
|
||||
if current_count < new_count then
|
||||
port.version.version = server_version
|
||||
end
|
||||
|
||||
-- Set port information
|
||||
port.version.name = "ibm-db2"
|
||||
port.version.product = "IBM DB2 Database Server"
|
||||
port.version.name_confidence = 100
|
||||
nmap.set_port_state(host, port, "open")
|
||||
if server_class ~= nil then port.version.extrainfo = server_class end
|
||||
|
||||
nmap.set_port_version(host, port, "hardmatched")
|
||||
|
||||
-- Generate results
|
||||
local results = "DB2 Version: " .. server_version .. "\n"
|
||||
results = results .. "Server Platform: " .. server_class .. "\n"
|
||||
results = results .. "Instance Name: " .. server_name .. "\n"
|
||||
results = results .. "External Name: " .. external_name
|
||||
|
||||
return results
|
||||
|
||||
end
|
||||
|
||||
|
||||
description = [[
|
||||
Attempts to extract information from IBM DB2 Server instances. The script sends a
|
||||
DB2 EXCSAT (exchange server attributes) command packet and parses the response.
|
||||
]]
|
||||
|
||||
---
|
||||
-- @output
|
||||
-- PORT STATE SERVICE
|
||||
-- 50000/tcp open ibm-db2
|
||||
-- | db2-info: DB2 Version: 8.02.9
|
||||
-- | Server Platform: QDB2/SUN
|
||||
-- | Instance Name: db2inst1
|
||||
-- |_ External Name: db2inst1db2agent00002B430
|
||||
|
||||
author = "Patrik Karlsson"
|
||||
|
||||
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
|
||||
|
||||
categories = {"safe", "discovery", "version"}
|
||||
|
||||
require "stdnse"
|
||||
require "shortport"
|
||||
require "db2"
|
||||
|
||||
-- Version 0.1
|
||||
-- Created 05/08/2010 - v0.1 - created by Patrik Karlsson <patrik@cqure.net>
|
||||
|
||||
--
|
||||
-- parseVersion was ripped from the old db2-info.nse written by Tom Sellers
|
||||
--
|
||||
|
||||
portrule = shortport.port_or_service({50000,60000},"ibm-db2", "tcp", {"open", "open|filtered"})
|
||||
|
||||
--- Converts the prodrel server string to a version string
|
||||
--
|
||||
-- @param server_version string containing the product release
|
||||
-- @return ver string containing the version information
|
||||
local function parseVersion( server_version )
|
||||
|
||||
if string.sub(server_version,1,3) == "SQL" then
|
||||
local major_version = string.sub(server_version,4,5)
|
||||
|
||||
-- strip the leading 0 from the major version, for consistency with
|
||||
-- nmap-service-probes results
|
||||
if string.sub(major_version,1,1) == "0" then
|
||||
major_version = string.sub(major_version,2)
|
||||
end
|
||||
local minor_version = string.sub(server_version,6,7)
|
||||
local hotfix = string.sub(server_version,8)
|
||||
server_version = major_version .. "." .. minor_version .. "." .. hotfix
|
||||
end
|
||||
|
||||
return server_version
|
||||
end
|
||||
|
||||
action = function( host, port )
|
||||
|
||||
local db2helper = db2.Helper:new()
|
||||
local status, response
|
||||
|
||||
status, response = db2helper:connect(host, port)
|
||||
if( not(status) ) then
|
||||
return response
|
||||
end
|
||||
|
||||
status, response = db2helper:getServerInfo()
|
||||
if( not(status) ) then
|
||||
return response
|
||||
end
|
||||
|
||||
db2helper:close()
|
||||
|
||||
-- Set port information
|
||||
port.version.name = "ibm-db2"
|
||||
port.version.product = "IBM DB2 Database Server"
|
||||
port.version.name_confidence = 100
|
||||
nmap.set_port_state(host, port, "open")
|
||||
if response.srvclass ~= nil then port.version.extrainfo = response.srvclass end
|
||||
|
||||
nmap.set_port_version(host, port, "hardmatched")
|
||||
|
||||
-- Generate results
|
||||
local results = "DB2 Version: " .. parseVersion(response.prodrel) .. "\n"
|
||||
results = results .. "Server Platform: " .. response.srvclass .. "\n"
|
||||
results = results .. "Instance Name: " .. response.srvname .. "\n"
|
||||
results = results .. "External Name: " .. response.extname
|
||||
|
||||
return results
|
||||
end
|
||||
@@ -15,6 +15,7 @@ Entry { filename = "couchdb-databases.nse", categories = { "discovery", "safe",
|
||||
Entry { filename = "couchdb-stats.nse", categories = { "discovery", "safe", } }
|
||||
Entry { filename = "daap-get-library.nse", categories = { "discovery", "safe", } }
|
||||
Entry { filename = "daytime.nse", categories = { "discovery", "safe", } }
|
||||
Entry { filename = "db2-brute.nse", categories = { "auth", "intrusive", } }
|
||||
Entry { filename = "db2-das-info.nse", categories = { "discovery", "safe", "version", } }
|
||||
Entry { filename = "db2-info.nse", categories = { "discovery", "safe", "version", } }
|
||||
Entry { filename = "dhcp-discover.nse", categories = { "default", "discovery", "intrusive", } }
|
||||
|
||||
Reference in New Issue
Block a user