1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-13 03:09:02 +00:00

Re-indent the Lua files in nselib/data/

https://secwiki.org/w/Nmap/Code_Standards
This commit is contained in:
dmiller
2014-02-05 17:58:36 +00:00
parent 69e343f0aa
commit 7dd47ec3a3
5 changed files with 2193 additions and 2193 deletions

View File

@@ -31,12 +31,12 @@ local url = require "url"
-- @return True if login in was successful -- @return True if login in was successful
--- ---
local function try_http_basic_login(host, port, path, user, pass, digest_auth) local function try_http_basic_login(host, port, path, user, pass, digest_auth)
local credentials = {username = user, password = pass, digest = digest_auth} local credentials = {username = user, password = pass, digest = digest_auth}
local req = http.get(host, port, path, {no_cache=true, auth=credentials, redirect_ok = false}) local req = http.get(host, port, path, {no_cache=true, auth=credentials, redirect_ok = false})
if req.status and req.status ~= 401 and req.status ~= 403 then if req.status and req.status ~= 401 and req.status ~= 403 then
return true return true
end end
return false return false
end end
--- ---
@@ -51,17 +51,17 @@ end
-- @return True if login in was successful -- @return True if login in was successful
--- ---
local function try_http_post_login(host, port, path, target, failstr, params, follow_redirects) local function try_http_post_login(host, port, path, target, failstr, params, follow_redirects)
local req = http.post(host, port, url.absolute(path, target), {no_cache=true}, nil, params) local req = http.post(host, port, url.absolute(path, target), {no_cache=true}, nil, params)
if not req.status then return false end if not req.status then return false end
local status = tonumber(req.status) or 0 local status = tonumber(req.status) or 0
if follow_redirects and ( status > 300 and status < 400 ) then if follow_redirects and ( status > 300 and status < 400 ) then
req = http.get(host, port, url.absolute(path, req.header.location), { no_cache = true, redirect_ok = false }) req = http.get(host, port, url.absolute(path, req.header.location), { no_cache = true, redirect_ok = false })
end end
if req.status and req.status ~= 404 and not(http.response_contains(req, failstr)) then if req.status and req.status ~= 404 and not(http.response_contains(req, failstr)) then
return true return true
end end
return false return false
end end
--- ---
@@ -71,8 +71,8 @@ end
-- (or nil if not present) -- (or nil if not present)
--- ---
local function http_auth_realm(response) local function http_auth_realm(response)
local auth = response.header["www-authenticate"] or "" local auth = response.header["www-authenticate"] or ""
return auth:match('%srealm="([^"]*)') return auth:match('%srealm="([^"]*)')
end end
fingerprints = {} fingerprints = {}
@@ -110,10 +110,10 @@ table.insert(fingerprints, {
login_combos = { login_combos = {
{username = "tomcat", password = "tomcat"}, {username = "tomcat", password = "tomcat"},
{username = "admin", password = "admin"}, {username = "admin", password = "admin"},
-- http://cve.mitre.org/cgi-bin/cvename.cgi?name=2009-4189 -- http://cve.mitre.org/cgi-bin/cvename.cgi?name=2009-4189
{username = "ovwebusr", password = "OvW*busr1"}, {username = "ovwebusr", password = "OvW*busr1"},
-- http://cve.mitre.org/cgi-bin/cvename.cgi?name=2009-4188 -- http://cve.mitre.org/cgi-bin/cvename.cgi?name=2009-4188
{username = "j2deployer", password = "j2deployer"} {username = "j2deployer", password = "j2deployer"}
}, },
login_check = function (host, port, path, user, pass) login_check = function (host, port, path, user, pass)
return try_http_basic_login(host, port, path, user, pass, false) return try_http_basic_login(host, port, path, user, pass, false)

View File

@@ -21,345 +21,345 @@ local url = require "url"
tools = { Django = { rapidDetect = function(host, port) tools = { Django = { rapidDetect = function(host, port)
-- Check if the site gives that familiar Django admin login page. -- Check if the site gives that familiar Django admin login page.
local response = http.get(host, port, "/admin/") local response = http.get(host, port, "/admin/")
if response.body then if response.body then
if string.find(response.body, "Log in | Django site admin") or if string.find(response.body, "Log in | Django site admin") or
string.find(response.body, "this_is_the_login_form") or string.find(response.body, "this_is_the_login_form") or
string.find(response.body, "csrfmiddlewaretoken") then string.find(response.body, "csrfmiddlewaretoken") then
return "Django detected. Found Django admin login page on /admin/" return "Django detected. Found Django admin login page on /admin/"
end end
end end
-- In Django, the cookie sessionid is being set when you log in -- In Django, the cookie sessionid is being set when you log in
-- and forms will probably set a cookie called csrftoken. -- and forms will probably set a cookie called csrftoken.
if response.cookies then if response.cookies then
for _, c in pairs(response.cookies) do for _, c in pairs(response.cookies) do
if c.name == "csrftoken" then if c.name == "csrftoken" then
return "Django detected. Found sessionid cookie which means the contrib.auth package for authentication is enabled." return "Django detected. Found sessionid cookie which means the contrib.auth package for authentication is enabled."
elseif c.name == "sessionid" then elseif c.name == "sessionid" then
return "Django detected. Found csrftoken cookie." return "Django detected. Found csrftoken cookie."
end end
end end
end end
-- See if DEBUG mode still happens to be true. -- See if DEBUG mode still happens to be true.
response = http.get(host, port, "/random404page/") response = http.get(host, port, "/random404page/")
if response.body then if response.body then
if string.find(response.body, "<code>DEBUG = True</code>") then if string.find(response.body, "<code>DEBUG = True</code>") then
return "Django detected. Found Django error page on /random404page/" return "Django detected. Found Django error page on /random404page/"
end end
end end
end, end,
consumingDetect = function(page, path) consumingDetect = function(page, path)
if page then if page then
if string.find(page, "csrfmiddlewaretoken") then if string.find(page, "csrfmiddlewaretoken") then
return "Django detected. Found csrfmiddlewaretoken on " .. path return "Django detected. Found csrfmiddlewaretoken on " .. path
end end
if string.find(page, "id=\"id_") then if string.find(page, "id=\"id_") then
return "Django detected. Found id_ preffix in id attribute name on " .. path return "Django detected. Found id_ preffix in id attribute name on " .. path
end end
if string.find(page, "%-TOTAL%-FORMS") or string.find(page, "%-DELETE") then if string.find(page, "%-TOTAL%-FORMS") or string.find(page, "%-DELETE") then
return "Django detected. Found -TOTAL-FORMS and -DELETE hidden inputs, which means there is a Django formset on " .. path return "Django detected. Found -TOTAL-FORMS and -DELETE hidden inputs, which means there is a Django formset on " .. path
end end
end end
end end
}, },
RubyOnRails = { rapidDetect = function(host, port) RubyOnRails = { rapidDetect = function(host, port)
local response = http.get(host, port, "/") local response = http.get(host, port, "/")
-- Check for Mongrel or Passenger in the "Server" or "X-Powered-By" header -- Check for Mongrel or Passenger in the "Server" or "X-Powered-By" header
for h, v in pairs(response.header) do for h, v in pairs(response.header) do
if h == "x-powered-by" or h == "server" then if h == "x-powered-by" or h == "server" then
local vl = v:lower() local vl = v:lower()
local m = vl:match("mongrel") or vl:match("passenger") local m = vl:match("mongrel") or vl:match("passenger")
if m then if m then
return "RoR detected. Found '" .. m .. "' in " .. h .. " header sent by the server." return "RoR detected. Found '" .. m .. "' in " .. h .. " header sent by the server."
end end
end end
end end
-- /rails/info/propertires shows project info when in development mode -- /rails/info/propertires shows project info when in development mode
response = http.get(host, port, "/rails/info/properties") response = http.get(host, port, "/rails/info/properties")
if response.body then if response.body then
if string.find(response.body, "Ruby version") then if string.find(response.body, "Ruby version") then
return "RoR detected. Found properties file on /rails/info/properties/" return "RoR detected. Found properties file on /rails/info/properties/"
end end
end end
-- Make up a bad path and match the error page -- Make up a bad path and match the error page
response = http.get(host, port, "/random404page/") response = http.get(host, port, "/random404page/")
if response.body then if response.body then
if string.find(response.body, "Routing Error") then if string.find(response.body, "Routing Error") then
return "RoR detected. Found RoR routing error page on /random404page/" return "RoR detected. Found RoR routing error page on /random404page/"
end end
end end
end, end,
consumingDetect = function(page, path) consumingDetect = function(page, path)
-- Check the source and look for csrf patterns. -- Check the source and look for csrf patterns.
if page then if page then
if string.find(page, "csrf%-param") or string.find(page, "csrf%-token") then if string.find(page, "csrf%-param") or string.find(page, "csrf%-token") then
return "RoR detected. Found csrf field on" .. path return "RoR detected. Found csrf field on" .. path
end end
end end
end end
}, },
ASPdotNET = { rapidDetect = function(host, port) ASPdotNET = { rapidDetect = function(host, port)
local response = http.get(host, port, "/") local response = http.get(host, port, "/")
-- Look for an ASP.NET header. -- Look for an ASP.NET header.
for h, v in pairs(response.header) do for h, v in pairs(response.header) do
local vl = v:lower() local vl = v:lower()
if h == "x-aspnet-version" or string.find(vl, "asp") then if h == "x-aspnet-version" or string.find(vl, "asp") then
return "ASP.NET detected. Found related header." return "ASP.NET detected. Found related header."
end end
end end
if response.cookies then if response.cookies then
for _, c in pairs(response.cookies) do for _, c in pairs(response.cookies) do
if c.name == "aspnetsessionid" then if c.name == "aspnetsessionid" then
return "ASP.NET detected. Found aspnetsessionid cookie." return "ASP.NET detected. Found aspnetsessionid cookie."
end end
end end
end end
end, end,
consumingDetect = function(page, path) consumingDetect = function(page, path)
-- Check the source and look for common traces. -- Check the source and look for common traces.
if page then if page then
if string.find(page, " __VIEWSTATE") or if string.find(page, " __VIEWSTATE") or
string.find(page, "__EVENT") or string.find(page, "__EVENT") or
string.find(page, "__doPostBack") or string.find(page, "__doPostBack") or
string.find(page, "aspnetForm") or string.find(page, "aspnetForm") or
string.find(page, "ctl00_") then string.find(page, "ctl00_") then
return "ASP.NET detected. Found common traces on" .. path return "ASP.NET detected. Found common traces on" .. path
end end
end end
end end
}, },
CodeIgniter = { rapidDetect = function(host, port) CodeIgniter = { rapidDetect = function(host, port)
-- Match default error page. -- Match default error page.
local response = http.get(host, port, "/random404page/") local response = http.get(host, port, "/random404page/")
if response.body then if response.body then
if string.find(response.body, "#990000") and if string.find(response.body, "#990000") and
string.find(response.body, "404 Page Not Found") then string.find(response.body, "404 Page Not Found") then
return "CodeIgniter detected. Found CodeIgniter default error page on /random404page/" return "CodeIgniter detected. Found CodeIgniter default error page on /random404page/"
end end
end end
end, end,
consumingDetect = function(page, path) consumingDetect = function(page, path)
return return
end end
}, },
CakePHP = { rapidDetect = function(host, port) CakePHP = { rapidDetect = function(host, port)
-- Find CAKEPHP header. -- Find CAKEPHP header.
local response = http.get(host, port, "/") local response = http.get(host, port, "/")
for h, v in pairs(response.header) do for h, v in pairs(response.header) do
local vl = v:lower() local vl = v:lower()
if string.find(vl, "cakephp") then if string.find(vl, "cakephp") then
return "CakePHP detected. Found related header." return "CakePHP detected. Found related header."
end end
end end
end, end,
consumingDetect = function(page, path) consumingDetect = function(page, path)
return return
end end
}, },
Symfony = { rapidDetect = function(host, port) Symfony = { rapidDetect = function(host, port)
-- Find Symfony header. -- Find Symfony header.
local response = http.get(host, port, "/") local response = http.get(host, port, "/")
for h, v in pairs(response.header) do for h, v in pairs(response.header) do
local vl = v:lower() local vl = v:lower()
if string.find(vl, "symfony") then if string.find(vl, "symfony") then
return "Symfony detected. Found related header." return "Symfony detected. Found related header."
end end
end end
end, end,
consumingDetect = function(page, path) consumingDetect = function(page, path)
return return
end end
}, },
Wordpress = { rapidDetect = function(host, port) Wordpress = { rapidDetect = function(host, port)
-- Check for common traces in the source code. -- Check for common traces in the source code.
local response = http.get(host, port, "/") local response = http.get(host, port, "/")
if response.body then if response.body then
if string.find(response.body, "content=[\"']WordPress") or if string.find(response.body, "content=[\"']WordPress") or
string.find(response.body, "wp%-content") then string.find(response.body, "wp%-content") then
return "Wordpress detected. Found common traces on /" return "Wordpress detected. Found common traces on /"
end end
end end
-- Check if the default login page exists. -- Check if the default login page exists.
response = http.get(host, port, "/wp%-login") response = http.get(host, port, "/wp%-login")
if response.status == "200" then if response.status == "200" then
return "Wordpress detected. Found WP login page on /wp-login" return "Wordpress detected. Found WP login page on /wp-login"
end end
end, end,
consumingDetect = function(page, path) consumingDetect = function(page, path)
if page then if page then
if string.find(page, "content=[\"']WordPress") or if string.find(page, "content=[\"']WordPress") or
string.find(page, "wp%-content") then string.find(page, "wp%-content") then
return "Wordpress detected. Found common traces on " .. page return "Wordpress detected. Found common traces on " .. page
end end
end end
end end
}, },
Joomla = { rapidDetect = function(host, port) Joomla = { rapidDetect = function(host, port)
-- Check for common traces in the source code. -- Check for common traces in the source code.
local response = http.get(host, port, "/") local response = http.get(host, port, "/")
if response.body then if response.body then
if string.find(response.body, "content=[\"']Joomla!") then if string.find(response.body, "content=[\"']Joomla!") then
return "Joomla detected. Found common traces on /" return "Joomla detected. Found common traces on /"
end end
end end
-- Check if the default login page exists. -- Check if the default login page exists.
response = http.get(host, port, "/administrator") response = http.get(host, port, "/administrator")
if response.body and string.find(response.body, "Joomla") then if response.body and string.find(response.body, "Joomla") then
return "Joomla detected. Found Joomla login page on /administrator/" return "Joomla detected. Found Joomla login page on /administrator/"
end end
end, end,
consumingDetect = function(page, path) consumingDetect = function(page, path)
if page and string.find(page, "content=[\"']Joomla!") then if page and string.find(page, "content=[\"']Joomla!") then
return "Joomla detected. Found common traces on " .. page return "Joomla detected. Found common traces on " .. page
end end
end end
}, },
Drupal = { rapidDetect = function(host, port) Drupal = { rapidDetect = function(host, port)
-- Check for common traces in the source code. -- Check for common traces in the source code.
local response = http.get(host, port, "/") local response = http.get(host, port, "/")
if response.body then if response.body then
if string.find(response.body, "content=[\"']Drupal") then if string.find(response.body, "content=[\"']Drupal") then
return "Drupal detected. Found common traces on /" return "Drupal detected. Found common traces on /"
end end
end end
end, end,
consumingDetect = function(page, path) consumingDetect = function(page, path)
if page and string.find(page, "content=[\"']Drupal") then if page and string.find(page, "content=[\"']Drupal") then
return "Drupal detected. Found common traces on " .. page return "Drupal detected. Found common traces on " .. page
end end
end end
}, },
MediaWiki = { rapidDetect = function(host, port) MediaWiki = { rapidDetect = function(host, port)
-- Check for common traces in the source code. -- Check for common traces in the source code.
local response = http.get(host, port, "/") local response = http.get(host, port, "/")
if response.body then if response.body then
if string.find(response.body, "content=[\"']MediaWiki") or if string.find(response.body, "content=[\"']MediaWiki") or
string.find(response.body, "/mediawiki/") then string.find(response.body, "/mediawiki/") then
return "MediaWiki detected. Found common traces on /" return "MediaWiki detected. Found common traces on /"
end end
end end
end, end,
consumingDetect = function(page, path) consumingDetect = function(page, path)
if page and string.find(page, "content=[\"']MediaWiki") or if page and string.find(page, "content=[\"']MediaWiki") or
string.find(page, "/mediawiki/") then string.find(page, "/mediawiki/") then
return "MediaWiki detected. Found common traces on " .. page return "MediaWiki detected. Found common traces on " .. page
end end
end end
}, },
ColdFusion = { rapidDetect = function(host, port) ColdFusion = { rapidDetect = function(host, port)
local response = http.get(host, port, "/") local response = http.get(host, port, "/")
if response.cookies then if response.cookies then
for _, c in pairs(response.cookies) do for _, c in pairs(response.cookies) do
if c.name == "cfid" or c.name == "cftoken" then if c.name == "cfid" or c.name == "cftoken" then
return "ColdFusion detected. Found " .. c.name .. " cookie." return "ColdFusion detected. Found " .. c.name .. " cookie."
end end
end end
end end
end, end,
consumingDetect = function(page, path) consumingDetect = function(page, path)
return return
end end
}, },
Broadvision = { rapidDetect = function(host, port) Broadvision = { rapidDetect = function(host, port)
local response = http.get(host, port, "/") local response = http.get(host, port, "/")
if response.cookies then if response.cookies then
for _, c in pairs(response.cookies) do for _, c in pairs(response.cookies) do
if string.find(c.name, "bv_") then if string.find(c.name, "bv_") then
return "Broadvision detected. Found " .. c.name .. " cookie." return "Broadvision detected. Found " .. c.name .. " cookie."
end end
end end
end end
end, end,
consumingDetect = function(page, path) consumingDetect = function(page, path)
return return
end end
}, },
WebSphereCommerce = { rapidDetect = function(host, port) WebSphereCommerce = { rapidDetect = function(host, port)
local response = http.get(host, port, "/") local response = http.get(host, port, "/")
if response.cookies then if response.cookies then
for _, c in pairs(response.cookies) do for _, c in pairs(response.cookies) do
if string.find(c.name, "wc_") then if string.find(c.name, "wc_") then
return "WebSphere Commerce detected. Found " .. c.name .. " cookie." return "WebSphere Commerce detected. Found " .. c.name .. " cookie."
end end
end end
end end
end, end,
consumingDetect = function(page, path) consumingDetect = function(page, path)
return return
end end
}, },
} }

View File

@@ -11853,90 +11853,90 @@ local f = nmap.fetchfile(nikto_db_path) or io.open(nikto_db_path, "r")
if f then if f then
stdnse.print_debug(1, "Found nikto db.") stdnse.print_debug(1, "Found nikto db.")
local nikto_db = {} local nikto_db = {}
for l in io.lines(nikto_db_path) do for l in io.lines(nikto_db_path) do
-- Skip comments. -- Skip comments.
if not string.match(l, "^#.*") then if not string.match(l, "^#.*") then
record = {} record = {}
for field in string.gmatch(l, "\"(.-)\",") do for field in string.gmatch(l, "\"(.-)\",") do
-- Grab every attribute and create a record. -- Grab every attribute and create a record.
if field then if field then
string.gsub(field, '%%', '%%%%') string.gsub(field, '%%', '%%%%')
table.insert(record, field) table.insert(record, field)
end
end
-- Make sure this record doesn't exists already.
local exists = false
for _, f in pairs(fingerprints) do
if f.probes then
for __, p in pairs(f.probes) do
if p.path then
if p.path == record[4] then
exists = true
break
end
end
end
end
end
-- What we have right now, is the following record:
-- record[1]: Nikto test ID
-- record[2]: OSVDB-ID
-- record[3]: Server Type
-- record[4]: URI
-- record[5]: HTTP Method
-- record[6]: Match 1
-- record[7]: Match 1 (Or)
-- record[8]: Match1 (And)
-- record[9]: Fail 1
-- record[10]: Fail 2
-- record[11]: Summary
-- record[12]: HTTP Data
-- record[13]: Headers
-- Is this a valid record? Atm, with our current format we need
-- to skip some nikto records. See NSEDoc for more info.
if not exists
and record[4]
and record[8] == "" and record[10] == "" and record[12] == ""
and (tonumber(record[4]) == nil or (tonumber(record[4]) and record[4] == "200")) then
-- Our current format does not support HTTP code matching.
if record[6] == "200" then record[6] = "" end
nikto_fingerprint = { category = "nikto",
probes = {
{
path = record[4],
method = record[5]
}
},
matches = {
{
dontmatch = record[9],
match = record[6],
output = record[11]
},
},
}
-- If there is a second match, add it.
if record[7] and record[7] ~= "" then
table.insert(nikto_fingerprint.matches, { match = record[7], output = record[11] })
end
table.insert(fingerprints, nikto_fingerprint)
end
end end
end
-- Make sure this record doesn't exists already.
local exists = false
for _, f in pairs(fingerprints) do
if f.probes then
for __, p in pairs(f.probes) do
if p.path then
if p.path == record[4] then
exists = true
break
end
end
end
end
end
-- What we have right now, is the following record:
-- record[1]: Nikto test ID
-- record[2]: OSVDB-ID
-- record[3]: Server Type
-- record[4]: URI
-- record[5]: HTTP Method
-- record[6]: Match 1
-- record[7]: Match 1 (Or)
-- record[8]: Match1 (And)
-- record[9]: Fail 1
-- record[10]: Fail 2
-- record[11]: Summary
-- record[12]: HTTP Data
-- record[13]: Headers
-- Is this a valid record? Atm, with our current format we need
-- to skip some nikto records. See NSEDoc for more info.
if not exists
and record[4]
and record[8] == "" and record[10] == "" and record[12] == ""
and (tonumber(record[4]) == nil or (tonumber(record[4]) and record[4] == "200")) then
-- Our current format does not support HTTP code matching.
if record[6] == "200" then record[6] = "" end
nikto_fingerprint = { category = "nikto",
probes = {
{
path = record[4],
method = record[5]
}
},
matches = {
{
dontmatch = record[9],
match = record[6],
output = record[11]
},
},
}
-- If there is a second match, add it.
if record[7] and record[7] ~= "" then
table.insert(nikto_fingerprint.matches, { match = record[7], output = record[11] })
end
table.insert(fingerprints, nikto_fingerprint)
end end
end
end
end end

File diff suppressed because it is too large Load Diff

View File

@@ -6,61 +6,61 @@ TEMPLATE_NAME="CIS MySQL Benchmarks v1.0.2"
ADMIN_ACCOUNTS={"root", "debian-sys-maint"} ADMIN_ACCOUNTS={"root", "debian-sys-maint"}
-- Checks whether a resultset is empty or not -- Checks whether a resultset is empty or not
local function isEmpty(rows) local function isEmpty(rows)
if ( #rows > 0 ) then return false end if ( #rows > 0 ) then return false end
return true return true
end end
-- Extracts a column from a row and return all occurances as an array -- Extracts a column from a row and return all occurances as an array
local function col2tab(rs, cname) local function col2tab(rs, cname)
local tab = {} local tab = {}
local cpos local cpos
for i=1, #rs.cols do for i=1, #rs.cols do
if ( rs.cols[i].name == cname ) then if ( rs.cols[i].name == cname ) then
cpos = i cpos = i
break break
end end
end end
if ( not(cpos) ) then if ( not(cpos) ) then
return return
end end
for _, row in ipairs(rs.rows) do table.insert(tab, row[cpos]) end for _, row in ipairs(rs.rows) do table.insert(tab, row[cpos]) end
return tab return tab
end end
local function createINstmt(tab) local function createINstmt(tab)
local tab2 = {} local tab2 = {}
for i=1, #tab do tab2[i] = ("'%s'"):format(tab[i]) end for i=1, #tab do tab2[i] = ("'%s'"):format(tab[i]) end
return stdnse.strjoin(",", tab2) return stdnse.strjoin(",", tab2)
end end
-- This next section contains all the tests -- This next section contains all the tests
-- Logging -- Logging
test { id="3.1", desc="Skip symbolic links", sql="SHOW variables WHERE Variable_name = 'log_error' AND Value IS NOT NULL", check=function(rowstab) test { id="3.1", desc="Skip symbolic links", sql="SHOW variables WHERE Variable_name = 'log_error' AND Value IS NOT NULL", check=function(rowstab)
return { status = not(isEmpty(rowstab[1])) } return { status = not(isEmpty(rowstab[1])) }
end end
} }
test { id="3.2", desc="Logs not on system partition", sql="SHOW variables WHERE Variable_name = 'log_bin' AND Value <> 'OFF'", check=function(rowstab) test { id="3.2", desc="Logs not on system partition", sql="SHOW variables WHERE Variable_name = 'log_bin' AND Value <> 'OFF'", check=function(rowstab)
local log = col2tab(rowstab[1], 'Value') local log = col2tab(rowstab[1], 'Value')
return { status = isEmpty(rowstab[1]), result = log, review = not(isEmpty(rowstab[1])) } return { status = isEmpty(rowstab[1]), result = log, review = not(isEmpty(rowstab[1])) }
end end
} }
test { id="3.2", desc="Logs not on database partition", sql="SHOW variables WHERE Variable_name = 'log_bin' AND Value <> 'OFF'", check=function(rowstab) test { id="3.2", desc="Logs not on database partition", sql="SHOW variables WHERE Variable_name = 'log_bin' AND Value <> 'OFF'", check=function(rowstab)
local log = col2tab(rowstab[1], 'Value') local log = col2tab(rowstab[1], 'Value')
return { status = isEmpty(rowstab[1]), result = log, review = not(isEmpty(rowstab[1])) } return { status = isEmpty(rowstab[1]), result = log, review = not(isEmpty(rowstab[1])) }
end end
} }
-- General -- General
test { id="4.1", desc="Supported version of MySQL", sql="SHOW VARIABLES like 'version'", check=function(rowstab) test { id="4.1", desc="Supported version of MySQL", sql="SHOW VARIABLES like 'version'", check=function(rowstab)
local ver = col2tab(rowstab[1], 'Value')[1] local ver = col2tab(rowstab[1], 'Value')[1]
return { status = true, review = true, result = ("Version: %s"):format(ver) } return { status = true, review = true, result = ("Version: %s"):format(ver) }
end end
} }
test { id="4.4", desc="Remove test database", sql="SHOW DATABASES like 'test'", check=function(rowstab) return { status = isEmpty(rowstab[1]) } end } test { id="4.4", desc="Remove test database", sql="SHOW DATABASES like 'test'", check=function(rowstab) return { status = isEmpty(rowstab[1]) } end }
@@ -68,155 +68,155 @@ test { id="4.4", desc="Remove test database", sql="SHOW DATABASES like 'test'",
test { id="4.5", desc="Change admin account name", sql="SELECT user FROM mysql.user WHERE user='root';", check=function(rowstab) return { status = isEmpty(rowstab[1]) } end } test { id="4.5", desc="Change admin account name", sql="SELECT user FROM mysql.user WHERE user='root';", check=function(rowstab) return { status = isEmpty(rowstab[1]) } end }
test { id="4.7", desc="Verify Secure Password Hashes", sql="SELECT DISTINCT user, password from mysql.user where length(password) < 41 AND length(password) > 0", check=function(rowstab) test { id="4.7", desc="Verify Secure Password Hashes", sql="SELECT DISTINCT user, password from mysql.user where length(password) < 41 AND length(password) > 0", check=function(rowstab)
local users = col2tab(rowstab[1], 'user') local users = col2tab(rowstab[1], 'user')
users.name = ( #users > 0 ) and "The following users were found having weak password hashes" users.name = ( #users > 0 ) and "The following users were found having weak password hashes"
return { status = isEmpty(rowstab[1]), result = users } return { status = isEmpty(rowstab[1]), result = users }
end end
} }
test { id="4.9", desc="Wildcards in user hostname", sql="select user from mysql.user where host = '%'", check=function(rowstab) test { id="4.9", desc="Wildcards in user hostname", sql="select user from mysql.user where host = '%'", check=function(rowstab)
local users = col2tab(rowstab[1], 'user') local users = col2tab(rowstab[1], 'user')
users.name = ( #users > 0 ) and "The following users were found with wildcards in hostname" users.name = ( #users > 0 ) and "The following users were found with wildcards in hostname"
return { status = isEmpty(rowstab[1]), result = users } return { status = isEmpty(rowstab[1]), result = users }
end end
} }
test { id="4.10", desc="No blank passwords", sql="select distinct user, password from mysql.user where length(password) = 0 or password is null", check=function(rowstab) test { id="4.10", desc="No blank passwords", sql="select distinct user, password from mysql.user where length(password) = 0 or password is null", check=function(rowstab)
local users = col2tab(rowstab[1], 'user') local users = col2tab(rowstab[1], 'user')
users.name = ( #users > 0 ) and "The following users were found having blank/empty passwords" users.name = ( #users > 0 ) and "The following users were found having blank/empty passwords"
return { status = isEmpty(rowstab[1]), result = users } return { status = isEmpty(rowstab[1]), result = users }
end end
} }
test { id="4.11", desc="Anonymous account", sql="select distinct user from mysql.user where user =''", check=function(rowstab) return { status = isEmpty(rowstab[1]) } end } test { id="4.11", desc="Anonymous account", sql="select distinct user from mysql.user where user =''", check=function(rowstab) return { status = isEmpty(rowstab[1]) } end }
-- MySQL Permissions -- MySQL Permissions
test { id="5.1", desc="Access to mysql database", test { id="5.1", desc="Access to mysql database",
sql = { "SELECT user, host FROM mysql.db WHERE db = 'mysql' and ((Select_priv = 'Y') or (Insert_priv = 'Y') " .. sql = { "SELECT user, host FROM mysql.db WHERE db = 'mysql' and ((Select_priv = 'Y') or (Insert_priv = 'Y') " ..
"or (Update_priv = 'Y') or (Delete_priv = 'Y') or (Create_priv = 'Y') or (Drop_priv = 'Y'))", "or (Update_priv = 'Y') or (Delete_priv = 'Y') or (Create_priv = 'Y') or (Drop_priv = 'Y'))",
"SELECT user, host FROM mysql.user WHERE (Select_priv = 'Y') or (Insert_priv = 'Y') or " .. "SELECT user, host FROM mysql.user WHERE (Select_priv = 'Y') or (Insert_priv = 'Y') or " ..
"(Update_priv = 'Y') or (Delete_priv = 'Y') or (Create_priv = 'Y') or (Drop_priv = 'Y')" }, "(Update_priv = 'Y') or (Delete_priv = 'Y') or (Create_priv = 'Y') or (Drop_priv = 'Y')" },
check = function(rowstab) check = function(rowstab)
local result = tab.new(2) local result = tab.new(2)
tab.addrow(result, "user", "host") tab.addrow(result, "user", "host")
local rs = rowstab[1] local rs = rowstab[1]
for _, row in ipairs(rs.rows) do for _, row in ipairs(rs.rows) do
tab.addrow( result, row[1], row[2] ) tab.addrow( result, row[1], row[2] )
end end
return { status = false, review = true, result = { tab.dump(result), name="Verify the following users that have access to the MySQL database" } } return { status = false, review = true, result = { tab.dump(result), name="Verify the following users that have access to the MySQL database" } }
end end
} }
test { id="5.2", desc="Do not grant FILE privileges to non Admin users", test { id="5.2", desc="Do not grant FILE privileges to non Admin users",
sql=("SELECT user, host FROM mysql.user WHERE File_priv = 'Y' AND user NOT IN (%s)"):format(createINstmt(ADMIN_ACCOUNTS)), sql=("SELECT user, host FROM mysql.user WHERE File_priv = 'Y' AND user NOT IN (%s)"):format(createINstmt(ADMIN_ACCOUNTS)),
check=function(rowstab) check=function(rowstab)
local users = col2tab(rowstab[1], 'user') local users = col2tab(rowstab[1], 'user')
users.name = ( #users > 0 ) and "The following users were found having the FILE privilege" users.name = ( #users > 0 ) and "The following users were found having the FILE privilege"
return { status = isEmpty(rowstab[1]), result = users, review = not(isEmpty(rowstab[1])) } return { status = isEmpty(rowstab[1]), result = users, review = not(isEmpty(rowstab[1])) }
end end
} }
test { id="5.3", desc="Do not grant PROCESS privileges to non Admin users", test { id="5.3", desc="Do not grant PROCESS privileges to non Admin users",
sql=("SELECT user, host FROM mysql.user WHERE Process_priv = 'Y' AND user NOT IN (%s)"):format(createINstmt(ADMIN_ACCOUNTS)), sql=("SELECT user, host FROM mysql.user WHERE Process_priv = 'Y' AND user NOT IN (%s)"):format(createINstmt(ADMIN_ACCOUNTS)),
check=function(rowstab) check=function(rowstab)
local users = col2tab(rowstab[1], 'user') local users = col2tab(rowstab[1], 'user')
users.name = ( #users > 0 ) and "The following users were found having the PROCESS privilege" users.name = ( #users > 0 ) and "The following users were found having the PROCESS privilege"
return { status = isEmpty(rowstab[1]), result = users, review = not(isEmpty(rowstab[1])) } return { status = isEmpty(rowstab[1]), result = users, review = not(isEmpty(rowstab[1])) }
end end
} }
test { id="5.4", desc="Do not grant SUPER privileges to non Admin users", test { id="5.4", desc="Do not grant SUPER privileges to non Admin users",
sql=("SELECT user, host FROM mysql.user WHERE Super_priv = 'Y' AND user NOT IN (%s)"):format(createINstmt(ADMIN_ACCOUNTS)), sql=("SELECT user, host FROM mysql.user WHERE Super_priv = 'Y' AND user NOT IN (%s)"):format(createINstmt(ADMIN_ACCOUNTS)),
check=function(rowstab) check=function(rowstab)
local users = col2tab(rowstab[1], 'user') local users = col2tab(rowstab[1], 'user')
users.name = ( #users > 0 ) and "The following users were found having the SUPER privilege" users.name = ( #users > 0 ) and "The following users were found having the SUPER privilege"
return { status = isEmpty(rowstab[1]), result = users, review = not(isEmpty(rowstab[1])) } return { status = isEmpty(rowstab[1]), result = users, review = not(isEmpty(rowstab[1])) }
end end
} }
test { id="5.5", desc="Do not grant SHUTDOWN privileges to non Admin users", test { id="5.5", desc="Do not grant SHUTDOWN privileges to non Admin users",
sql=("SELECT user, host FROM mysql.user WHERE Shutdown_priv = 'Y' AND user NOT IN (%s)"):format(createINstmt(ADMIN_ACCOUNTS)), sql=("SELECT user, host FROM mysql.user WHERE Shutdown_priv = 'Y' AND user NOT IN (%s)"):format(createINstmt(ADMIN_ACCOUNTS)),
check=function(rowstab) check=function(rowstab)
local users = col2tab(rowstab[1], 'user') local users = col2tab(rowstab[1], 'user')
users.name = ( #users > 0 ) and "The following users were found having the SHUTDOWN privilege" users.name = ( #users > 0 ) and "The following users were found having the SHUTDOWN privilege"
return { status = isEmpty(rowstab[1]), result = users, review = not(isEmpty(rowstab[1])) } return { status = isEmpty(rowstab[1]), result = users, review = not(isEmpty(rowstab[1])) }
end end
} }
test { id="5.6", desc="Do not grant CREATE USER privileges to non Admin users", test { id="5.6", desc="Do not grant CREATE USER privileges to non Admin users",
sql=("SELECT user, host FROM mysql.user WHERE Create_user_priv = 'Y' AND user NOT IN (%s)"):format(createINstmt(ADMIN_ACCOUNTS)), sql=("SELECT user, host FROM mysql.user WHERE Create_user_priv = 'Y' AND user NOT IN (%s)"):format(createINstmt(ADMIN_ACCOUNTS)),
check=function(rowstab) check=function(rowstab)
local users = col2tab(rowstab[1], 'user') local users = col2tab(rowstab[1], 'user')
users.name = ( #users > 0 ) and "The following users were found having the CREATE USER privilege" users.name = ( #users > 0 ) and "The following users were found having the CREATE USER privilege"
return { status = isEmpty(rowstab[1]), result = users, review = not(isEmpty(rowstab[1])) } return { status = isEmpty(rowstab[1]), result = users, review = not(isEmpty(rowstab[1])) }
end end
} }
test { id="5.7", desc="Do not grant RELOAD privileges to non Admin users", test { id="5.7", desc="Do not grant RELOAD privileges to non Admin users",
sql=("SELECT user, host FROM mysql.user WHERE Reload_priv = 'Y' AND user NOT IN (%s)"):format(createINstmt(ADMIN_ACCOUNTS)), sql=("SELECT user, host FROM mysql.user WHERE Reload_priv = 'Y' AND user NOT IN (%s)"):format(createINstmt(ADMIN_ACCOUNTS)),
check=function(rowstab) check=function(rowstab)
local users = col2tab(rowstab[1], 'user') local users = col2tab(rowstab[1], 'user')
users.name = ( #users > 0 ) and "The following users were found having the RELOAD privilege" users.name = ( #users > 0 ) and "The following users were found having the RELOAD privilege"
return { status = isEmpty(rowstab[1]), result = users, review = not(isEmpty(rowstab[1])) } return { status = isEmpty(rowstab[1]), result = users, review = not(isEmpty(rowstab[1])) }
end end
} }
test { id="5.8", desc="Do not grant GRANT privileges to non Admin users", test { id="5.8", desc="Do not grant GRANT privileges to non Admin users",
sql=("SELECT user, host FROM mysql.user WHERE Grant_priv = 'Y' AND user NOT IN (%s)"):format(createINstmt(ADMIN_ACCOUNTS)), sql=("SELECT user, host FROM mysql.user WHERE Grant_priv = 'Y' AND user NOT IN (%s)"):format(createINstmt(ADMIN_ACCOUNTS)),
check=function(rowstab) check=function(rowstab)
local users = col2tab(rowstab[1], 'user') local users = col2tab(rowstab[1], 'user')
users.name = ( #users > 0 ) and "The following users were found having the GRANT privilege" users.name = ( #users > 0 ) and "The following users were found having the GRANT privilege"
return { status = isEmpty(rowstab[1]), result = users, review = not(isEmpty(rowstab[1])) } return { status = isEmpty(rowstab[1]), result = users, review = not(isEmpty(rowstab[1])) }
end end
} }
-- MySQL Configuraiton options -- MySQL Configuraiton options
test { id="6.2", desc="Disable Load data local", sql="SHOW variables WHERE Variable_name = 'local_infile' AND Value='OFF'", check=function(rowstab) test { id="6.2", desc="Disable Load data local", sql="SHOW variables WHERE Variable_name = 'local_infile' AND Value='OFF'", check=function(rowstab)
return { status = not(isEmpty(rowstab[1])) } return { status = not(isEmpty(rowstab[1])) }
end end
} }
test { id="6.3", desc="Disable old password hashing", sql="SHOW variables WHERE Variable_name = 'old_passwords' AND Value='OFF'", check=function(rowstab) test { id="6.3", desc="Disable old password hashing", sql="SHOW variables WHERE Variable_name = 'old_passwords' AND Value='OFF'", check=function(rowstab)
return { status = not(isEmpty(rowstab[1])) } return { status = not(isEmpty(rowstab[1])) }
end end
} }
test { id="6.4", desc="Safe show database", sql="SHOW variables WHERE Variable_name = 'safe_show_database' AND Value='ON'", check=function(rowstab) test { id="6.4", desc="Safe show database", sql="SHOW variables WHERE Variable_name = 'safe_show_database' AND Value='ON'", check=function(rowstab)
return { status = not(isEmpty(rowstab[1])) } return { status = not(isEmpty(rowstab[1])) }
end end
} }
test { id="6.5", desc="Secure auth", sql="SHOW variables WHERE Variable_name = 'secure_auth' AND Value='ON'", check=function(rowstab) test { id="6.5", desc="Secure auth", sql="SHOW variables WHERE Variable_name = 'secure_auth' AND Value='ON'", check=function(rowstab)
return { status = not(isEmpty(rowstab[1])) } return { status = not(isEmpty(rowstab[1])) }
end end
} }
test { id="6.6", desc="Grant tables", sql="SHOW variables WHERE Variable_name = 'skip_grant_tables' AND Value='OFF'", check=function(rowstab) test { id="6.6", desc="Grant tables", sql="SHOW variables WHERE Variable_name = 'skip_grant_tables' AND Value='OFF'", check=function(rowstab)
return { status = not(isEmpty(rowstab[1])) } return { status = not(isEmpty(rowstab[1])) }
end end
} }
test { id="6.7", desc="Skip merge", sql="SHOW variables WHERE Variable_name = 'have_merge_engine' AND Value='DISABLED'", check=function(rowstab) test { id="6.7", desc="Skip merge", sql="SHOW variables WHERE Variable_name = 'have_merge_engine' AND Value='DISABLED'", check=function(rowstab)
return { status = not(isEmpty(rowstab[1])) } return { status = not(isEmpty(rowstab[1])) }
end end
} }
test { id="6.8", desc="Skip networking", sql="SHOW variables WHERE Variable_name = 'skip_networking' AND Value='ON'", check=function(rowstab) test { id="6.8", desc="Skip networking", sql="SHOW variables WHERE Variable_name = 'skip_networking' AND Value='ON'", check=function(rowstab)
return { status = not(isEmpty(rowstab[1])) } return { status = not(isEmpty(rowstab[1])) }
end end
} }
test { id="6.9", desc="Safe user create", sql="select @@global.sql_mode, @@session.sql_mode FROM dual WHERE @@session.sql_mode='NO_AUTO_CREATE_USER' AND @@global.sql_mode='NO_AUTO_CREATE_USER'", check=function(rowstab) test { id="6.9", desc="Safe user create", sql="select @@global.sql_mode, @@session.sql_mode FROM dual WHERE @@session.sql_mode='NO_AUTO_CREATE_USER' AND @@global.sql_mode='NO_AUTO_CREATE_USER'", check=function(rowstab)
return { status = not(isEmpty(rowstab[1])) } return { status = not(isEmpty(rowstab[1])) }
end end
} }
test { id="6.10", desc="Skip symbolic links", sql="SHOW variables WHERE Variable_name = 'have_symlink' AND Value='DISABLED'", check=function(rowstab) test { id="6.10", desc="Skip symbolic links", sql="SHOW variables WHERE Variable_name = 'have_symlink' AND Value='DISABLED'", check=function(rowstab)
return { status = not(isEmpty(rowstab[1])) } return { status = not(isEmpty(rowstab[1])) }
end end
} }