mirror of
https://github.com/nmap/nmap.git
synced 2026-02-03 12:06:35 +00:00
Fix MySQL version detection, greeting parsing. Fixes #529
This commit is contained in:
@@ -13,6 +13,7 @@ local nmap = require "nmap"
|
||||
local stdnse = require "stdnse"
|
||||
local string = require "string"
|
||||
local table = require "table"
|
||||
local math = require "math"
|
||||
_ENV = stdnse.module("mysql", stdnse.seeall)
|
||||
|
||||
-- Version 0.3
|
||||
@@ -50,7 +51,8 @@ Capabilities =
|
||||
ExtCapabilities =
|
||||
{
|
||||
SupportsMultipleStatments = 0x1,
|
||||
SupportsMultipleResults = 0x2
|
||||
SupportsMultipleResults = 0x2,
|
||||
SupportsAuthPlugins = 0x8,
|
||||
}
|
||||
|
||||
Charset =
|
||||
@@ -123,23 +125,43 @@ function receiveGreeting( socket )
|
||||
pos, is_error = bin.unpack( "C", data, pos )
|
||||
|
||||
if ( is_error == 0xff ) then
|
||||
pos, response.errorcode = bin.unpack( "S", data, pos )
|
||||
pos, response.errorcode = bin.unpack( "<S", data, pos )
|
||||
pos, response.errormsg = bin.unpack("A" .. (#data - pos + 1), data, pos )
|
||||
|
||||
return false, response.errormsg
|
||||
end
|
||||
|
||||
pos, response.proto = bin.unpack( "C", data, pos )
|
||||
response.proto = is_error
|
||||
pos, response.version = bin.unpack( "z", data, pos )
|
||||
pos, response.threadid = bin.unpack( "I", data, pos )
|
||||
pos, response.salt, _ = bin.unpack( "A8C", data, pos )
|
||||
pos, response.capabilities = bin.unpack( "S", data, pos )
|
||||
pos, response.charset = bin.unpack( "C", data, pos )
|
||||
pos, response.status = bin.unpack( "S", data, pos )
|
||||
pos, _ = bin.unpack( "A13", data, pos )
|
||||
pos, tmp = bin.unpack( "A12", data, pos )
|
||||
pos, response.threadid = bin.unpack( "<I", data, pos )
|
||||
|
||||
if response.proto == 10 then
|
||||
pos, response.salt, _ = bin.unpack( "A8C", data, pos )
|
||||
pos, response.capabilities = bin.unpack( "<S", data, pos )
|
||||
if pos < #data then
|
||||
pos, response.charset = bin.unpack( "C", data, pos )
|
||||
pos, response.status = bin.unpack( "<S", data, pos )
|
||||
pos, response.extcapabilities = bin.unpack( "<S", data, pos) -- capabilities, upper 2 bytes
|
||||
local auth_plugin_len
|
||||
pos, auth_plugin_len = bin.unpack("C", data, pos)
|
||||
pos, tmp = bin.unpack( "A10", data, pos )
|
||||
if tmp ~= "\0\0\0\0\0\0\0\0\0\0" then
|
||||
stdnse.debug2("reserved bytes are not nulls")
|
||||
end
|
||||
if response.capabilities & Capabilities.Support41Auth > 0 then
|
||||
pos, tmp = bin.unpack("A" .. math.max(13, auth_plugin_len - 8), data, pos)
|
||||
response.salt = response.salt .. tmp
|
||||
end
|
||||
if response.extcapabilities & ExtCapabilities.SupportsAuthPlugins > 0 then
|
||||
response.auth_plugin_name = bin.unpack("z", data, pos)
|
||||
end
|
||||
end
|
||||
elseif response.proto == 9 then
|
||||
pos, response.auth_plugin_data = bin.unpack( "z", data, pos )
|
||||
else
|
||||
stdnse.debug2("Unknown MySQL protocol version: %d", response.proto)
|
||||
end
|
||||
|
||||
response.salt = response.salt .. tmp
|
||||
response.errorcode = 0
|
||||
|
||||
return true, response
|
||||
|
||||
@@ -49,10 +49,10 @@ categories = { "default", "discovery", "safe" }
|
||||
--- Converts a number to a string description of the capabilities
|
||||
--@param num Start of the capabilities data
|
||||
--@return table containing the names of the capabilities offered
|
||||
local capabilities = function(num)
|
||||
local bitset = function(num, lookup)
|
||||
local caps = {}
|
||||
|
||||
for k, v in pairs(mysql.Capabilities) do
|
||||
for k, v in pairs(lookup) do
|
||||
if bit.band(num, v) > 0 then
|
||||
caps[#caps+1] = k
|
||||
end
|
||||
@@ -100,24 +100,34 @@ action = function(host, port)
|
||||
output["Version"] = info.version
|
||||
output["Thread ID"] = info.threadid
|
||||
|
||||
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
|
||||
if info.proto == 10 then
|
||||
output["Capabilities flags"] = info.capabilities
|
||||
local caps = bitset(info.capabilities, mysql.Capabilities)
|
||||
if info.extcapabilities then
|
||||
local extcaps = bitset(info.extcapabilities, mysql.ExtCapabilities)
|
||||
for i, c in ipairs(extcaps) do
|
||||
caps[#caps+1] = c
|
||||
end
|
||||
end
|
||||
if #caps > 0 then
|
||||
setmetatable(caps, {
|
||||
__tostring = function (self)
|
||||
return table.concat(self, ", ")
|
||||
end
|
||||
})
|
||||
output["Some Capabilities"] = caps
|
||||
end
|
||||
|
||||
if info.status == 2 then
|
||||
output["Status"] = "Autocommit"
|
||||
else
|
||||
output["Status"] = info.status
|
||||
end
|
||||
if info.status == 2 then
|
||||
output["Status"] = "Autocommit"
|
||||
else
|
||||
output["Status"] = info.status
|
||||
end
|
||||
|
||||
output["Salt"] = info.salt
|
||||
output["Salt"] = info.salt
|
||||
|
||||
output["Auth Plugin Name"] = info.auth_plugin_name
|
||||
end
|
||||
|
||||
return output
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user