mirror of
https://github.com/nmap/nmap.git
synced 2025-12-06 04:31:29 +00:00
o Improved the mysql library to handle multiple columns with the same name,
added a formatResultset function to format a query response to a table suitable for script output. [Patrik Karlsson]
This commit is contained in:
@@ -1,5 +1,9 @@
|
||||
# Nmap Changelog ($Id$); -*-text-*-
|
||||
|
||||
o Improved the mysql library to handle multiple columns with the same name,
|
||||
added a formatResultset function to format a query response to a table
|
||||
suitable for script output. [Patrik Karlsson]
|
||||
|
||||
o The message "nexthost: failed to determine route to ..." is now a
|
||||
warning rather than a fatal error. Addresses that are skipped in
|
||||
this way are recorded in the XML output as <target> elements. [David
|
||||
|
||||
@@ -3,7 +3,7 @@ require("tab")
|
||||
TEMPLATE_NAME="CIS MySQL Benchmarks v1.0.2"
|
||||
|
||||
-- These accounts should be treated as admins and excluded from some of the results
|
||||
local ADMIN_ACCOUNTS={"root", "debian-sys-maint"}
|
||||
ADMIN_ACCOUNTS={"root", "debian-sys-maint"}
|
||||
|
||||
-- Checks whether a resultset is empty or not
|
||||
local function isEmpty(rows)
|
||||
@@ -12,9 +12,19 @@ local function isEmpty(rows)
|
||||
end
|
||||
|
||||
-- Extracts a column from a row and return all occurances as an array
|
||||
local function col2tab(rows, cname)
|
||||
local function col2tab(rs, cname)
|
||||
local tab = {}
|
||||
for _, row in ipairs(rows) do table.insert(tab, row[cname]) end
|
||||
local cpos
|
||||
for i=1, #rs.cols do
|
||||
if ( rs.cols[i].name == cname ) then
|
||||
cpos = i
|
||||
break
|
||||
end
|
||||
end
|
||||
if ( not(cpos) ) then
|
||||
return
|
||||
end
|
||||
for _, row in ipairs(rs.rows) do table.insert(tab, row[cpos]) end
|
||||
return tab
|
||||
end
|
||||
|
||||
@@ -92,10 +102,9 @@ test { id="5.1", desc="Access to mysql database",
|
||||
local result = tab.new(2)
|
||||
tab.addrow(result, "user", "host")
|
||||
|
||||
for _, rows in ipairs(rowstab) do
|
||||
for _, row in ipairs(rows) do
|
||||
tab.addrow( result, row.user, row.host )
|
||||
end
|
||||
local rs = rowstab[1]
|
||||
for _, row in ipairs(rs.rows) do
|
||||
tab.addrow( result, row[1], row[2] )
|
||||
end
|
||||
|
||||
return { status = false, review = true, result = { tab.dump(result), name="Verify the following users that have access to the MySQL database" } }
|
||||
|
||||
@@ -17,6 +17,8 @@ module(... or "mysql", package.seeall)
|
||||
-- fixed a number of incorrect receives and changed
|
||||
-- them to receive_bytes instead.
|
||||
|
||||
local tab = require('tab')
|
||||
|
||||
local HAVE_SSL = false
|
||||
|
||||
if pcall(require,'openssl') then
|
||||
@@ -455,11 +457,10 @@ end
|
||||
-- ref: http://forge.mysql.com/wiki/MySQL_Internals_ClientServer_Protocol#Row_Data_Packet
|
||||
--
|
||||
-- @param data string containing the row data packet
|
||||
-- @param fields table containing the field data as recieved from <code>decodeFieldPackets</code>
|
||||
-- @param count number containing the number of fields to decode
|
||||
-- @return status true on success, false on failure
|
||||
-- @return rows table containing row tables
|
||||
function decodeDataPackets( data, fields, count )
|
||||
function decodeDataPackets( data, count )
|
||||
|
||||
local len, pos = 0, 1, 1
|
||||
local header, row, rows = {}, {}, {}
|
||||
@@ -470,7 +471,7 @@ function decodeDataPackets( data, fields, count )
|
||||
|
||||
for i=1, count do
|
||||
pos, len = bin.unpack("C", data, pos )
|
||||
pos, row[fields[i].name] = bin.unpack("A" .. len, data, pos)
|
||||
pos, row[i] = bin.unpack("A" .. len, data, pos)
|
||||
end
|
||||
|
||||
table.insert( rows, row )
|
||||
@@ -530,12 +531,39 @@ function sqlQuery( socket, query )
|
||||
return false, fields
|
||||
end
|
||||
|
||||
status, rows = decodeDataPackets(rs.data, fields, field_count)
|
||||
status, rows = decodeDataPackets(rs.data, field_count)
|
||||
|
||||
if not status then
|
||||
return false, rows
|
||||
end
|
||||
|
||||
return true, rows
|
||||
|
||||
return true, { cols = fields, rows = rows }
|
||||
end
|
||||
|
||||
---
|
||||
-- Formats the resultset returned from <code>sqlQuery</code>
|
||||
--
|
||||
-- @param rs table as returned from <code>sqlQuery</code>
|
||||
-- @param options table containing additional options, currently:
|
||||
-- - <code>noheaders</code> - does not include column names in result
|
||||
-- @return string containing the formated resultset table
|
||||
function formatResultset(rs, options)
|
||||
options = options or {}
|
||||
if ( not(rs) or not(rs.cols) or not(rs.rows) ) then
|
||||
return
|
||||
end
|
||||
|
||||
local restab = tab.new(#rs.cols)
|
||||
local colnames = {}
|
||||
|
||||
if ( not(options.noheaders) ) then
|
||||
for _, col in ipairs(rs.cols) do table.insert(colnames, col.name) end
|
||||
tab.addrow(restab, unpack(colnames))
|
||||
end
|
||||
|
||||
for _, row in ipairs(rs.rows) do
|
||||
tab.addrow(restab, unpack(row))
|
||||
end
|
||||
|
||||
return tab.dump(restab)
|
||||
end
|
||||
|
||||
@@ -86,7 +86,7 @@ require 'shortport'
|
||||
require 'mysql'
|
||||
|
||||
portrule = shortport.port_or_service(3306, "mysql")
|
||||
local TEMPLATE_NAME = ""
|
||||
local TEMPLATE_NAME, ADMIN_ACCOUNTS = "", ""
|
||||
|
||||
local function loadAuditRulebase( filename )
|
||||
|
||||
@@ -103,6 +103,7 @@ local function loadAuditRulebase( filename )
|
||||
|
||||
file()
|
||||
TEMPLATE_NAME = getfenv(file)["TEMPLATE_NAME"]
|
||||
ADMIN_ACCOUNTS = getfenv(file)["ADMIN_ACCOUNTS"]
|
||||
return true, rules
|
||||
end
|
||||
|
||||
@@ -121,7 +122,7 @@ action = function( host, port )
|
||||
end
|
||||
|
||||
local status, tests = loadAuditRulebase( filename )
|
||||
if( not(status) ) then return rules end
|
||||
if( not(status) ) then return tests end
|
||||
|
||||
local socket = nmap.new_socket()
|
||||
status = socket:connect(host, port)
|
||||
@@ -166,7 +167,10 @@ action = function( host, port )
|
||||
socket:close()
|
||||
results.name = TEMPLATE_NAME
|
||||
|
||||
table.insert(results, {"", ("The audit was performed using the db-account: %s"):format(username)})
|
||||
table.insert(results, "")
|
||||
table.insert(results, {name = "Additional information", ("The audit was performed using the db-account: %s"):format(username),
|
||||
("The following admin accounts were excluded from the audit: %s"):format(stdnse.strjoin(",", ADMIN_ACCOUNTS))
|
||||
})
|
||||
|
||||
return stdnse.format_output(true, { results })
|
||||
end
|
||||
@@ -78,12 +78,9 @@ action = function( host, port )
|
||||
status, response = mysql.loginRequest( socket, { authversion = "post41", charset = response.charset }, username, password, response.salt )
|
||||
|
||||
if status and response.errorcode == 0 then
|
||||
status, rows = mysql.sqlQuery( socket, "show databases" )
|
||||
local status, rs = mysql.sqlQuery( socket, "show databases" )
|
||||
if status then
|
||||
for i=1, #rows do
|
||||
-- cheap way of avoiding duplicates
|
||||
dbs[rows[i]['Database']] = rows[i]['Database']
|
||||
end
|
||||
result = mysql.formatResultset(rs, { noheaders = true })
|
||||
|
||||
-- if we got here as root, we've got them all
|
||||
-- if we're here as someone else, we cant be sure
|
||||
@@ -94,11 +91,5 @@ action = function( host, port )
|
||||
end
|
||||
socket:close()
|
||||
end
|
||||
|
||||
for _, v in pairs( dbs ) do
|
||||
table.insert(result, v)
|
||||
end
|
||||
|
||||
return stdnse.format_output(true, result)
|
||||
|
||||
end
|
||||
|
||||
@@ -81,12 +81,9 @@ action = function( host, port )
|
||||
status, response = mysql.loginRequest( socket, { authversion = "post41", charset = response.charset }, username, password, response.salt )
|
||||
|
||||
if status and response.errorcode == 0 then
|
||||
status, rows = mysql.sqlQuery( socket, "SELECT DISTINCT user FROM mysql.user" )
|
||||
status, rs = mysql.sqlQuery( socket, "SELECT DISTINCT user FROM mysql.user" )
|
||||
if status then
|
||||
for i=1, #rows do
|
||||
table.insert(result, rows[i]['user'])
|
||||
end
|
||||
break
|
||||
result = mysql.formatResultset(rs, { noheaders = true })
|
||||
end
|
||||
end
|
||||
socket:close()
|
||||
|
||||
@@ -89,10 +89,10 @@ action = function( host, port )
|
||||
status, response = mysql.loginRequest( socket, { authversion = "post41", charset = response.charset }, username, password, response.salt )
|
||||
|
||||
if status and response.errorcode == 0 then
|
||||
status, rows = mysql.sqlQuery( socket, "show variables" )
|
||||
local status, rs = mysql.sqlQuery( socket, "show variables" )
|
||||
if status then
|
||||
for i=1, #rows do
|
||||
table.insert(result, string.format("%s: %s" , rows[i]['Variable_name'], rows[i]['Value']) )
|
||||
for _, row in ipairs(rs.rows) do
|
||||
table.insert(result, ("%s: %s"):format(row[1], row[2]) )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user