mirror of
https://github.com/nmap/nmap.git
synced 2025-12-19 14:09:02 +00:00
Update mysql-info to use mysql.lua
Also added structured output and support for more capabilities.
This commit is contained in:
@@ -1,5 +1,8 @@
|
|||||||
local bit = require "bit"
|
local bit = require "bit"
|
||||||
local comm = require "comm"
|
local mysql = require "mysql"
|
||||||
|
local nmap = require "nmap"
|
||||||
|
local stdnse = require "stdnse"
|
||||||
|
local table = require "table"
|
||||||
|
|
||||||
description = [[
|
description = [[
|
||||||
Connects to a MySQL server and prints information such as the protocol and
|
Connects to a MySQL server and prints information such as the protocol and
|
||||||
@@ -13,12 +16,27 @@ isn't run (see the portrule).
|
|||||||
---
|
---
|
||||||
-- @output
|
-- @output
|
||||||
-- 3306/tcp open mysql
|
-- 3306/tcp open mysql
|
||||||
-- | mysql-info: Protocol: 10
|
-- | mysql-info:
|
||||||
|
-- | Protocol: 10
|
||||||
-- | Version: 5.0.51a-3ubuntu5.1
|
-- | Version: 5.0.51a-3ubuntu5.1
|
||||||
-- | Thread ID: 7
|
-- | Thread ID: 7
|
||||||
-- | Some Capabilities: Connect with DB, Transactions, Secure Connection
|
-- | Capabilities flags: 40968
|
||||||
|
-- | Some Capabilities: ConnectWithDatabase, SupportsTransactions, Support41Auth
|
||||||
-- | Status: Autocommit
|
-- | Status: Autocommit
|
||||||
-- |_ Salt: bYyt\NQ/4V6IN+*3`imj
|
-- |_ Salt: bYyt\NQ/4V6IN+*3`imj
|
||||||
|
--
|
||||||
|
--@xmloutput
|
||||||
|
-- <elem key="Protocol">10</elem>
|
||||||
|
-- <elem key="Version">5.0.51a-3ubuntu5.1</elem>
|
||||||
|
-- <elem key="Thread ID">7</elem>
|
||||||
|
-- <elem key="Capabilities flags">40968</elem>
|
||||||
|
-- <table key="Some Capabilities">
|
||||||
|
-- <elem>ConnectWithDatabase</elem>
|
||||||
|
-- <elem>SupportsTransactions</elem>
|
||||||
|
-- <elem>Support41Auth</elem>
|
||||||
|
-- </table>
|
||||||
|
-- <elem key="Status">Autocommit</elem>
|
||||||
|
-- <elem key="Salt">bYyt\NQ/4V6IN+*3`imj</elem>
|
||||||
|
|
||||||
-- Many thanks to jah (jah@zadkiel.plus.com) for testing and enhancements
|
-- Many thanks to jah (jah@zadkiel.plus.com) for testing and enhancements
|
||||||
|
|
||||||
@@ -28,82 +46,19 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
|
|||||||
|
|
||||||
categories = { "default", "discovery", "safe" }
|
categories = { "default", "discovery", "safe" }
|
||||||
|
|
||||||
|
|
||||||
--- Grabs NUL-terminated string
|
|
||||||
--@param orig Start of the string
|
|
||||||
--@return The NUL-terminated string
|
|
||||||
local getstring = function(orig)
|
|
||||||
return orig:match("^([^\0]*)");
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Converts two bytes into a number
|
|
||||||
--@param num Start of the two bytes
|
|
||||||
--@return The converted number
|
|
||||||
local ntohs = function(num)
|
|
||||||
local b1 = bit.band(num:byte(1), 255)
|
|
||||||
local b2 = bit.band(num:byte(2), 255)
|
|
||||||
|
|
||||||
return bit.bor(b1, bit.lshift(b2, 8))
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Converts three bytes into a number
|
|
||||||
--@param num Start of the three bytes
|
|
||||||
--@return The converted number
|
|
||||||
local ntoh3 = function(num)
|
|
||||||
local b1 = bit.band(num:byte(1), 255)
|
|
||||||
local b2 = bit.band(num:byte(2), 255)
|
|
||||||
local b3 = bit.band(num:byte(3), 255)
|
|
||||||
|
|
||||||
return bit.bor(b1, bit.lshift(b2, 8), bit.lshift(b3, 16))
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Converts four bytes into a number
|
|
||||||
--@param num Start of the four bytes
|
|
||||||
--@return The converted number
|
|
||||||
local ntohl = function(num)
|
|
||||||
local b1 = bit.band(num:byte(1), 255)
|
|
||||||
local b2 = bit.band(num:byte(2), 255)
|
|
||||||
local b3 = bit.band(num:byte(3), 255)
|
|
||||||
local b4 = bit.band(num:byte(4), 255)
|
|
||||||
|
|
||||||
return bit.bor(b1, bit.lshift(b2, 8), bit.lshift(b3, 16), bit.lshift(b4, 24))
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Converts a number to a string description of the capabilities
|
--- Converts a number to a string description of the capabilities
|
||||||
--@param num Start of the capabilities data
|
--@param num Start of the capabilities data
|
||||||
--@return String describing the capabilities offered
|
--@return table containing the names of the capabilities offered
|
||||||
local capabilities = function(num)
|
local capabilities = function(num)
|
||||||
local caps = ""
|
local caps = {}
|
||||||
|
|
||||||
if bit.band(num, 1) > 0 then
|
for k, v in pairs(mysql.Capabilities) do
|
||||||
caps = caps .. "Long Passwords, "
|
if bit.band(num, v) > 0 then
|
||||||
|
caps[#caps+1] = k
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if bit.band(num, 8) > 0 then
|
return caps
|
||||||
caps = caps .. "Connect with DB, "
|
|
||||||
end
|
|
||||||
|
|
||||||
if bit.band(num, 32) > 0 then
|
|
||||||
caps = caps .. "Compress, "
|
|
||||||
end
|
|
||||||
|
|
||||||
if bit.band(num, 64) > 0 then
|
|
||||||
caps = caps .. "ODBC, "
|
|
||||||
end
|
|
||||||
|
|
||||||
if bit.band(num, 2048) > 0 then
|
|
||||||
caps = caps .. "SSL, "
|
|
||||||
end
|
|
||||||
|
|
||||||
if bit.band(num, 8192) > 0 then
|
|
||||||
caps = caps .. "Transactions, "
|
|
||||||
end
|
|
||||||
|
|
||||||
if bit.band(num, 32768) > 0 then
|
|
||||||
caps = caps .. "Secure Connection, "
|
|
||||||
end
|
|
||||||
|
|
||||||
return caps:gsub(", $", "")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
portrule = function(host, port)
|
portrule = function(host, port)
|
||||||
@@ -118,90 +73,51 @@ portrule = function(host, port)
|
|||||||
end
|
end
|
||||||
|
|
||||||
action = function(host, port)
|
action = function(host, port)
|
||||||
local output = ""
|
local output = stdnse.output_table()
|
||||||
|
local socket = nmap.new_socket()
|
||||||
|
socket:set_timeout(5000)
|
||||||
|
|
||||||
local status, response = comm.get_banner(host, port, {timeout=5000})
|
local status, err = socket:connect(host, port)
|
||||||
|
|
||||||
if not status then
|
if not status then
|
||||||
return
|
stdnse.print_debug("%s: error connecting: %s", SCRIPT_NAME, err)
|
||||||
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
local length = ntoh3(response:sub(1, 3))
|
local status, info = mysql.receiveGreeting(socket)
|
||||||
|
|
||||||
if length ~= response:len() - 4 then
|
if not status then
|
||||||
return "Invalid greeting (Not MySQL?)"
|
stdnse.print_debug("%s: MySQL error: %s", SCRIPT_NAME, info)
|
||||||
|
output["MySQL Error"] = info
|
||||||
|
if nmap.verbosity() > 1 then
|
||||||
|
return output
|
||||||
|
else
|
||||||
|
return nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Keeps track of where we are in the binary data
|
output["Protocol"] = info.proto
|
||||||
local offset = 1 + 4
|
output["Version"] = info.version
|
||||||
|
output["Thread ID"] = info.threadid
|
||||||
|
|
||||||
local protocol = response:byte(offset)
|
output["Capabilities flags"] = info.capabilities
|
||||||
|
local caps = capabilities(info.capabilities)
|
||||||
|
if #caps > 0 then
|
||||||
|
setmetatable(caps, {
|
||||||
|
__tostring = function (self)
|
||||||
|
return table.concat(self, ", ")
|
||||||
|
end
|
||||||
|
})
|
||||||
|
output["Some Capabilities"] = caps
|
||||||
|
end
|
||||||
|
|
||||||
offset = offset + 1
|
if info.status == 2 then
|
||||||
|
output["Status"] = "Autocommit"
|
||||||
|
else
|
||||||
|
output["Status"] = info.status
|
||||||
|
end
|
||||||
|
|
||||||
-- If a 0xff is here instead of the protocol, an error occurred.
|
output["Salt"] = info.salt
|
||||||
-- Pass it along to the user..
|
|
||||||
if (protocol == 255) then
|
|
||||||
output = "MySQL Error detected!\n"
|
|
||||||
|
|
||||||
local sqlerrno = ntohs(response:sub(offset, offset + 2))
|
|
||||||
|
|
||||||
offset = offset + 2
|
|
||||||
|
|
||||||
local sqlerrstr = response:sub(offset)
|
|
||||||
|
|
||||||
output = output .. "Error Code was: " .. sqlerrno .. "\n"
|
|
||||||
|
|
||||||
output = output .. sqlerrstr
|
|
||||||
|
|
||||||
return output
|
|
||||||
end
|
|
||||||
|
|
||||||
local version = getstring(response:sub(offset))
|
|
||||||
|
|
||||||
offset = offset + version:len() + 1
|
|
||||||
|
|
||||||
local threadid = ntohl(response:sub(offset, offset + 4))
|
|
||||||
|
|
||||||
offset = offset + 4
|
|
||||||
|
|
||||||
local salt = getstring(response:sub(offset))
|
|
||||||
|
|
||||||
offset = offset + salt:len() + 1
|
|
||||||
|
|
||||||
local caps = capabilities(ntohs(response:sub(offset, offset + 2)))
|
|
||||||
|
|
||||||
offset = offset + 2
|
|
||||||
|
|
||||||
offset = offset + 1
|
|
||||||
|
|
||||||
local status = ""
|
|
||||||
|
|
||||||
if ntohs(response:sub(offset, offset + 2)) == 2 then
|
|
||||||
status = "Autocommit"
|
|
||||||
end
|
|
||||||
|
|
||||||
offset = offset + 2
|
|
||||||
|
|
||||||
offset = offset + 13 -- unused
|
|
||||||
|
|
||||||
if response:len() - offset + 1 == 13 then
|
|
||||||
salt = salt .. getstring(response:sub(offset))
|
|
||||||
end
|
|
||||||
|
|
||||||
output = output .. "Protocol: " .. protocol .. "\n"
|
|
||||||
output = output .. "Version: " .. version .. "\n"
|
|
||||||
output = output .. "Thread ID: " .. threadid .. "\n"
|
|
||||||
|
|
||||||
if caps:len() > 0 then
|
|
||||||
output = output .. "Some Capabilities: " .. caps .. "\n"
|
|
||||||
end
|
|
||||||
|
|
||||||
if status:len() > 0 then
|
|
||||||
output = output .. "Status: " .. status .. "\n"
|
|
||||||
end
|
|
||||||
|
|
||||||
output = output .. "Salt: " .. salt .. "\n"
|
|
||||||
|
|
||||||
return output
|
return output
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user