CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/lib/metasploit/framework/login_scanner/ldap.rb
Views: 1904
# frozen_string_literal: true12require 'metasploit/framework/login_scanner/base'3require 'metasploit/framework/ldap/client'45module Metasploit6module Framework7module LoginScanner8class LDAP9include Metasploit::Framework::LoginScanner::Base10include Metasploit::Framework::LDAP::Client11include Msf::Exploit::Remote::LDAP1213LIKELY_PORTS = [ 389, 636 ]14LIKELY_SERVICE_NAMES = [ 'ldap', 'ldaps', 'ldapssl' ]1516attr_accessor :opts, :realm_key17# @!attribute use_client_as_proof18# @return [Boolean] If a login is successful and this attribute is true - an LDAP::Client instance is used as proof19attr_accessor :use_client_as_proof2021# This method sets the sane defaults for things22# like timeouts and TCP evasion options23def set_sane_defaults24self.opts ||= {}25self.connection_timeout = 30 if self.connection_timeout.nil?26nil27end2829def attempt_login(credential)30result_opts = {31credential: credential,32status: Metasploit::Model::Login::Status::INCORRECT,33proof: nil,34host: host,35port: port,36protocol: 'tcp',37service_name: 'ldap'38}3940result_opts.merge!(do_login(credential))41Result.new(result_opts)42end4344def do_login(credential)45opts = {46username: credential.public,47password: credential.private,48framework_module: framework_module,49ldap_auth: 'auto'50}.merge(@opts)5152connect_opts = ldap_connect_opts(host, port, connection_timeout, ssl: opts[:ssl], opts: opts)53begin54ldap_client = ldap_open(connect_opts, keep_open: true)55return status_code(ldap_client)56rescue StandardError => e57{ status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: e }58end59end6061def status_code(ldap_client)62operation_result = ldap_client.get_operation_result.table[:code]63case operation_result64when 065result = { status: Metasploit::Model::Login::Status::SUCCESSFUL }66if use_client_as_proof67result[:proof] = ldap_client68result[:connection] = ldap_client.socket69end70result71else72{ status: Metasploit::Model::Login::Status::INCORRECT, proof: "Bind Result: #{operation_result}" }73end74end7576def each_credential77cred_details.each do |raw_cred|78# This could be a Credential object, or a Credential Core, or an Attempt object79# so make sure that whatever it is, we end up with a Credential.80credential = raw_cred.to_credential8182if opts[:ldap_auth] == Msf::Exploit::Remote::AuthOption::KERBEROS && opts[:ldap_krb5_cname]83# If we're using kerberos auth with a ccache then the password is irrelevant84# Remove it from the credential so we don't store it85credential.private = nil86elsif opts[:ldap_auth] == Msf::Exploit::Remote::AuthOption::SCHANNEL87# If we're using kerberos auth with schannel then the user/password is irrelevant88# Remove it from the credential so we don't store it89credential.public = nil90credential.private = nil91end9293if credential.realm.present? && realm_key.present?94credential.realm_key = realm_key95elsif credential.realm.present? && realm_key.blank?96# This service has no realm key, so the realm will be97# meaningless. Strip it off.98credential.realm = nil99credential.realm_key = nil100end101102yield credential103104if opts[:append_domain] && credential.realm.nil?105credential.public = "#{credential.public}@#{opts[:domain]}"106yield credential107end108end109end110end111end112end113end114115116