-
Notifications
You must be signed in to change notification settings - Fork 1
/
irc-brute.nse
144 lines (121 loc) · 3.58 KB
/
irc-brute.nse
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
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, brute.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()
local nick = ""
for i = 0, 8, 1 do
nick = nick .. string.char(math.random(97, 122)) -- lowercase ascii
end
return nick
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