1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-07 13:11:28 +00:00
Files
nmap/scripts/irc-brute.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

141 lines
3.6 KiB
Lua

local brute = require "brute"
local comm = require "comm"
local creds = require "creds"
local math = require "math"
local shortport = require "shortport"
local stdnse = require "stdnse"
local string = require "string"
description=[[
Performs brute force password auditing against IRC (Internet Relay Chat) servers.
]]
---
-- @usage
-- nmap --script irc-brute -p 6667 <ip>
--
-- @output
-- PORT STATE SERVICE
-- 6667/tcp open irc
-- | irc-brute:
-- | Accounts
-- | password - Valid credentials
-- | Statistics
-- |_ Performed 1927 guesses in 36 seconds, average tps: 74
--
--
-- Version 0.1
-- Created 26/10/2011 - v0.1 - created by Patrik Karlsson <patrik@cqure.net>
--
author = "Patrik Karlsson"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories={"brute","intrusive"}
portrule = shortport.port_or_service({6666,6667,6697,6679},{"irc","ircs"})
Driver = {
new = function(self, host, port, opts)
local o = { host = host, port = port, opts = opts or {} }
setmetatable(o, self)
self.__index = self
return o
end,
connect = function(self)
-- the high timeout should take delays from ident into consideration
local s, r, opts, _ = comm.tryssl(self.host,
self.port,
'',
{ timeout = self.opts.timeout or 10000 } )
if ( not(s) ) then
return false, "Failed to connect to server"
end
self.socket = s
return true
end,
login = function(self, _, password)
local msg = ("PASS %s\r\nNICK nmap_brute\r\nUSER anonymous 0 * :Nmap brute\r\n"):format(password)
local status, data = self.socket:send(msg)
local success = false
if ( not(status) ) then
local err = brute.Error:new( data )
-- This might be temporary, set the retry flag
err:setRetry( true )
return false, err
end
repeat
local status, response = self.socket:receive_buf("\r?\n", false)
-- we check for the RPL_WELCOME message, if we don't see it,
-- we failed to authenticate
if ( status and response:match("^:.-%s(%d*)%s") == "001" ) then
success = true
end
until(not(status))
if (success) then
return true, creds.Account:new("", password, creds.State.VALID)
end
return false, brute.Error:new("Incorrect password")
end,
disconnect = function(self) return self.socket:close() end,
}
local function random_nick()
return stdnse.generate_random_string(9, "abcdefghijklmnopqrstuvwxyz")
end
local function needsPassword(host, port)
local msg = ("NICK %s\r\nUSER anonymous 0 * :Nmap brute\r\n"):format(random_nick())
local s, r, opts, _ = comm.tryssl(host, port, msg, { timeout = 15000 } )
local err, code
repeat
local status, response = s:receive_buf("\r?\n", false)
if ( status ) then
code = tonumber(response:match("^:.-%s(%d*)%s"))
-- break after first code
if (code == 001 ) then
err = "The IRC service does not require authentication"
break
elseif( code ) then
break
end
end
until(not(status))
if (code == 464) then
return true
end
if ( code ) then
return false, ("Failed to check password requirements, unknown code (%d)"):format(code)
else
return false, "Failed to check password requirements"
end
end
action = function(host, port)
local status, err = needsPassword(host, port)
if ( not(status) ) then
return stdnse.format_output(false, err)
end
local engine = brute.Engine:new(Driver, host, port)
engine.options.script_name = SCRIPT_NAME
engine.options.firstonly = true
engine.options.passonly = true
local result
status, result = engine:start()
return result
end