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
|
local brute = require "brute"
local creds = require "creds"
local ipmi = require "ipmi"
local shortport = require "shortport"
local rand = require "rand"
description = [[
Performs brute force password auditing against IPMI RPC server.
]]
---
-- @usage
-- nmap -sU --script ipmi-brute -p 623 <host>
--
-- @output
-- PORT STATE SERVICE REASON
-- 623/udp open|filtered unknown
-- | ipmi-brute:
-- | Accounts
-- |_ admin:admin => Valid credentials
--
author = "Claudiu Perta"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"intrusive", "brute"}
portrule = shortport.port_or_service(623, "asf-rmcp", "udp", {"open", "open|filtered"})
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 = brute.new_socket()
self.socket:set_timeout(
((self.host.times and self.host.times.timeout) or 8) * 1000)
self.socket:connect(self.host, self.port, "udp")
return true
end,
login = function(self, username, password)
local console_session_id = rand.random_string(4)
local console_random_id = rand.random_string(16)
local request = ipmi.session_open_request(console_session_id)
local status, reply
self.socket:send(request)
status, reply = self.socket:receive()
if not status then
return false, brute.Error:new(
"No response to IPMI open session request")
end
local session = ipmi.parse_open_session_reply(reply)
if session["session_payload_type"] ~= ipmi.PAYLOADS["RMCPPLUSOPEN_REP"] then
return false, brute.Error:new("Unknown response to open session request")
end
if session["error_code"] ~= 0 then
return false, brute.Error:new(ipmi.RMCP_ERRORS[session.error_code] or "Unknown error")
end
local bmc_session_id = session["bmc_session_id"]
local rakp1_request = ipmi.rakp_1_request(
bmc_session_id, console_random_id, username)
self.socket:send(rakp1_request)
status, reply = self.socket:receive()
if not status then
return false, brute.Error:new("No response to RAKP1 message")
end
local rakp2_message = ipmi.parse_rakp_1_reply(reply)
if rakp2_message["session_payload_type"] ~= ipmi.PAYLOADS["RAKP2"] then
return false, brute.Error:new("Unknown response to RAPK1 request")
end
if rakp2_message["error_code"] ~= 0 then
return false, brute.Error:new(
ipmi.RMCP_ERRORS[rakp2_message["error_code"]])
end
local hmac_salt = ipmi.rakp_hmac_sha1_salt(
console_session_id,
session["bmc_session_id"],
console_random_id,
rakp2_message["bmc_random_id"],
rakp2_message["bmc_guid"],
0x14,
username
)
local found = ipmi.verify_rakp_hmac_sha1(
hmac_salt, rakp2_message["hmac_sha1"], password)
if found then
return true, creds.Account:new(username, password, creds.State.VALID)
else
return false, brute.Error:new("Incorrect password")
end
end,
disconnect = function(self)
self.socket:close()
end,
check = function(host, port)
return true
end
}
action = function(host, port)
local status, result
local engine = brute.Engine:new(Driver, host, port)
engine.options.script_name = SCRIPT_NAME
status, result = engine:start()
return result
end
|