Files
metasploit-gs/lib/metasploit/framework/ldap/client.rb
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

137 lines
5.4 KiB
Ruby
Raw Normal View History

2023-07-05 12:48:57 +01:00
# frozen_string_literal: true
module Metasploit
module Framework
module LDAP
2023-07-18 22:48:00 +01:00
2023-07-05 12:48:57 +01:00
module Client
def ldap_connect_opts(rhost, rport, connect_timeout, ssl: true, opts: {})
2023-07-05 12:48:57 +01:00
connect_opts = {
host: rhost,
port: rport,
connect_timeout: connect_timeout,
2023-07-19 16:39:34 +01:00
proxies: opts[:proxies]
2023-07-05 12:48:57 +01:00
}
if ssl
connect_opts[:encryption] = {
method: :simple_tls,
tls_options: {
verify_mode: OpenSSL::SSL::VERIFY_NONE
}
}
end
case opts[:ldap_auth]
when Msf::Exploit::Remote::AuthOption::SCHANNEL
pfx_path = opts[:ldap_cert_file]
2023-09-15 12:23:49 +01:00
raise Msf::ValidationError, 'The LDAP::CertFile option is required when using SCHANNEL authentication.' if pfx_path.blank?
raise Msf::ValidationError, 'The SSL option must be enabled when using SCHANNEL authentication.' if ssl != true
2023-07-05 12:48:57 +01:00
unless ::File.file?(pfx_path) && ::File.readable?(pfx_path)
2023-09-15 12:23:49 +01:00
raise Msf::ValidationError, 'Failed to load the PFX certificate file. The path was not a readable file.'
2023-07-05 12:48:57 +01:00
end
begin
pkcs = OpenSSL::PKCS12.new(File.binread(pfx_path), '')
rescue StandardError => e
2023-09-15 12:23:49 +01:00
raise Msf::ValidationError, "Failed to load the PFX file (#{e})"
2023-07-05 12:48:57 +01:00
end
connect_opts[:auth] = {
method: :sasl,
mechanism: 'EXTERNAL',
initial_credential: '',
challenge_response: true
}
connect_opts[:encryption] = {
method: :start_tls,
tls_options: {
verify_mode: OpenSSL::SSL::VERIFY_NONE,
cert: pkcs.certificate,
key: pkcs.key
}
}
when Msf::Exploit::Remote::AuthOption::KERBEROS
2023-09-15 12:23:49 +01:00
raise Msf::ValidationError, 'The Ldap::Rhostname option is required when using Kerberos authentication.' if opts[:ldap_rhostname].blank?
raise Msf::ValidationError, 'The DOMAIN option is required when using Kerberos authentication.' if opts[:domain].blank?
2023-07-24 19:13:04 +01:00
2023-07-05 12:48:57 +01:00
offered_etypes = Msf::Exploit::Remote::AuthOption.as_default_offered_etypes(opts[:ldap_krb_offered_enc_types])
2023-09-15 12:23:49 +01:00
raise Msf::ValidationError, 'At least one encryption type is required when using Kerberos authentication.' if offered_etypes.empty?
2023-07-05 12:48:57 +01:00
kerberos_authenticator = Msf::Exploit::Remote::Kerberos::ServiceAuthenticator::LDAP.new(
host: opts[:domain_controller_rhost].blank? ? nil : opts[:domain_controller_rhost],
2023-07-05 12:48:57 +01:00
hostname: opts[:ldap_rhostname],
realm: opts[:domain],
username: opts[:username],
password: opts[:password],
framework: opts[:framework],
2023-07-18 22:48:00 +01:00
framework_module: opts[:framework_module],
2023-07-05 12:48:57 +01:00
cache_file: opts[:ldap_krb5_cname].blank? ? nil : opts[:ldap_krb5_cname],
ticket_storage: opts[:kerberos_ticket_storage],
offered_etypes: offered_etypes
)
connect_opts[:auth] = {
method: :sasl,
mechanism: 'GSS-SPNEGO',
2023-07-18 22:48:00 +01:00
initial_credential: proc do
kerberos_result = kerberos_authenticator.authenticate
kerberos_result[:security_blob]
end,
2023-07-05 12:48:57 +01:00
challenge_response: true
}
when Msf::Exploit::Remote::AuthOption::NTLM
ntlm_client = RubySMB::NTLM::Client.new(
opts[:username],
opts[:password],
workstation: 'WORKSTATION',
domain: opts[:domain].blank? ? '.' : opts[:domain],
flags:
RubySMB::NTLM::NEGOTIATE_FLAGS[:UNICODE] |
RubySMB::NTLM::NEGOTIATE_FLAGS[:REQUEST_TARGET] |
RubySMB::NTLM::NEGOTIATE_FLAGS[:NTLM] |
RubySMB::NTLM::NEGOTIATE_FLAGS[:ALWAYS_SIGN] |
RubySMB::NTLM::NEGOTIATE_FLAGS[:EXTENDED_SECURITY] |
RubySMB::NTLM::NEGOTIATE_FLAGS[:KEY_EXCHANGE] |
RubySMB::NTLM::NEGOTIATE_FLAGS[:TARGET_INFO] |
RubySMB::NTLM::NEGOTIATE_FLAGS[:VERSION_INFO]
)
negotiate = proc do |challenge|
ntlmssp_offset = challenge.index('NTLMSSP')
type2_blob = challenge.slice(ntlmssp_offset..-1)
challenge = [type2_blob].pack('m')
type3_message = ntlm_client.init_context(challenge)
type3_message.serialize
end
connect_opts[:auth] = {
method: :sasl,
mechanism: 'GSS-SPNEGO',
initial_credential: ntlm_client.init_context.serialize,
challenge_response: negotiate
}
when Msf::Exploit::Remote::AuthOption::PLAINTEXT
connect_opts[:auth] = {
method: :simple,
username: opts[:username],
2023-07-05 12:48:57 +01:00
password: opts[:password]
}
when Msf::Exploit::Remote::AuthOption::AUTO
unless opts[:username].blank? # plaintext if specified
connect_opts[:auth] = {
method: :simple,
username: opts[:username],
2023-07-05 12:48:57 +01:00
password: opts[:password]
}
end
end
connect_opts
end
end
end
end
end