description = [[
Connects to a MySQL server and prints information such as the protocol and
version numbers, thread ID, status, capabilities, and the password salt.
If service detection is performed and the server appears to be blocking
our host or is blocked because of too many connections, then this script
isn't run (see the portrule).
]]
---
-- @output
-- 3306/tcp open mysql
-- | mysql-info: Protocol: 10
-- | Version: 5.0.51a-3ubuntu5.1
-- | Thread ID: 7
-- | Some Capabilities: Connect with DB, Transactions, Secure Connection
-- | Status: Autocommit
-- |_ Salt: bYyt\NQ/4V6IN+*3`imj
-- Many thanks to jah (jah@zadkiel.plus.com) for testing and enhancements
author = "Kris Katterjohn"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = { "default", "discovery", "safe" }
require 'bit'
require 'comm'
--- Grabs NUL-terminated string
--@param orig Start of the string
--@return The NUL-terminated string
local getstring = function(orig)
return orig:match("^([^%z]*)");
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
--@param num Start of the capabilities data
--@return String describing the capabilities offered
local capabilities = function(num)
local caps = ""
if bit.band(num, 1) > 0 then
caps = caps .. "Long Passwords, "
end
if bit.band(num, 8) > 0 then
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
portrule = function(host, port)
local extra = port.version.extrainfo
return (port.number == 3306 or port.service == "mysql")
and port.protocol == "tcp"
and port.state == "open"
and not (extra ~= nil
and (extra:match("[Uu]nauthorized")
or extra:match("[Tt]oo many connection")))
end
action = function(host, port)
local output = ""
local status, response = comm.get_banner(host, port, {timeout=5000})
if not status then
return
end
local length = ntoh3(response:sub(1, 3))
if length ~= response:len() - 4 then
return "Invalid greeting (Not MySQL?)"
end
-- Keeps track of where we are in the binary data
local offset = 1 + 4
local protocol = response:byte(offset)
offset = offset + 1
-- If a 0xff is here instead of the protocol, an error occurred.
-- 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
end
Copyright 2K16 - 2K18 Indonesian Hacker Rulez