Nmap Development mailing list archives
Re: [NSE Script] MySQL Server Information
From: Kris Katterjohn <katterjohn () gmail com>
Date: Tue, 18 Dec 2007 00:22:46 -0600
jah wrote:
No, it seems your script was not the cause, my messing around caused it. I think "many connection errors" refers to the application layer [1] and after much testing, I found that your script is closing sockets without issue and that the issue was further into the script. Then after a bit of reading, I found that the script was breaking when the mysql server responded with an error which it does by serving 0xff instead of a protocol byte, followed by a two byte error code and then the error string [2]. It was evident that your code wasn't handling this even though I couldn't tell exactly where it broke. Doesn't really matter though...I've attached your script, slightly modified to return any mysql error details and which shouldn't cause the above described issue in these circumstances. Hopefully.While I was testing it with many many random hosts I found that, using version detection, the version always contains "unauthorized" when I get an error code 0x046A (1130 ~ "Host not allowed to connect") from the script output - quite useful cross check I thought - and, given that nmap will have already matched the mysql error, it's maybe worth testing for this straight away (if used with version detection) to avoid running the script. I've included this modded portrule too, but it's not implemented so you can have a play - I imagine the script needs a bit more testing anyway. Next step, supply the script with args for user:pwd and try to return database names...
Great job, man :)I've attached yet another modified script which I'd like for you to try out if you can.
The changes are pretty obvious I think, but here's the rundown: Added some comments to the top.I used a little more object-oriented approach in the portrule involving the extrainfo field, especially since I added another match against it.
I grepped the nmap-service-probes and saw "unauthorized" with a lowercase and uppercase U, so I edited that part. I saw no occurrences of your suggested "unauthorised" in there, so I didn't add that.
I added a check for too many connections, which I saw in the probes file. It should match the different little versions of it from there, though I didn't find a server with that error to test with.
Another change was just for personal preference :) Instead of indenting the rest of the script after the protocol vs. error check, I just return from that if() and the rest was as before. I just think it's too long to warrant the extra indentation.
jah
Thanks a lot, Kris Katterjohn
-- Connect to MySQL server and print information such as the protocol and -- version numbers, thread id, status, capabilities and the password salt -- If, after service detection, the MySQL server appears to be blocking -- our host or is blocked from too many connections, then we don't bother -- running this script. -- Many thanks to jah (jah () zadkiel plus com) for testing and enhancements id = "MySQL Server Information" description = "Connects to a MySQL server and prints information" author = "Kris Katterjohn <katterjohn () gmail com>" license = "Look at Nmap's COPYING" categories = { "discovery", "safe" } require 'shortport' require 'bit' -- Grabs NUL-terminated string local getstring = function(orig) local str = "" local index = 1 while orig:byte(index) ~= 0 do str = str .. string.char(orig:byte(index)) index = index + 1 end return str end -- Convert two bytes into a number 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 -- Convert three bytes into a number 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 -- Convert four bytes into a number 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 -- Convert number to a list of capabilities for printing 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 if (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"))) then return true end return false end action = function(host, port) local sock local response = "" local output = "" sock = nmap.new_socket() sock:set_timeout(5000) sock:connect(host.ip, port.number) while true do local status, line = sock:receive_lines(1) if not status then break end response = response .. line end sock:close() 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) if (protocol == 255) then output = "MySQL Error detected!" -- 0xff found where protocol should be offset = offset + 1 local sqlerrno = ntohs(response:sub(offset, offset + 2)) offset = offset + 2 local sqlerrstr = response:sub(offset) output = output .. "\n" .. "Error Code was: " .. sqlerrno .. "\n" output = output .. "\n" .. sqlerrstr return output end offset = offset + 1 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
_______________________________________________ Sent through the nmap-dev mailing list http://cgi.insecure.org/mailman/listinfo/nmap-dev Archived at http://SecLists.Org
Current thread:
- [NSE Script] MySQL Server Information Kris Katterjohn (Dec 15)
- Message not available
- Re: [NSE Script] MySQL Server Information Kris Katterjohn (Dec 16)
- Re: [NSE Script] MySQL Server Information jah (Dec 17)
- Re: [NSE Script] MySQL Server Information Kris Katterjohn (Dec 17)
- Re: [NSE Script] MySQL Server Information jah (Dec 18)
- Re: [NSE Script] MySQL Server Information Kris Katterjohn (Dec 18)
- Re: [NSE Script] MySQL Server Information Thomas Buchanan (Dec 18)
- Re: [NSE Script] MySQL Server Information Kris Katterjohn (Dec 18)
- Re: [NSE Script] MySQL Server Information jah (Dec 18)
- Re: [NSE Script] MySQL Server Information Fyodor (Dec 18)
- Re: [NSE Script] MySQL Server Information Kris Katterjohn (Dec 18)
- Re: [NSE Script] MySQL Server Information jah (Dec 18)
- Re: [NSE Script] MySQL Server Information Brandon Enright (Dec 18)
- Re: [NSE Script] MySQL Server Information sawall (Dec 18)
- Re: [NSE Script] MySQL Server Information Kris Katterjohn (Dec 16)
- Message not available