Module: Msf::Exploit::Remote::SMB::Client::KerberosAuthentication
- Defined in:
- lib/msf/core/exploit/remote/smb/client/kerberos_authentication.rb
Overview
This class implements an override for RubySMB’s default authentication method to instead use a kerberos authenticator
Instance Method Summary collapse
- #authenticate ⇒ Object
- #kerberos_authenticator=(kerberos_authenticator) ⇒ Object
-
#smb1_authenticate ⇒ Object
Handles SMB1 Kerberos Authentication by delegating to a kerberos_authenticator implementation to generate a GSS security blob with an embedded AP_REQ.
-
#smb1_kerberos_authenticate(security_buffer) ⇒ String
The raw binary response from the server.
-
#smb1_kerberos_authenticate_packet(security_blob) ⇒ RubySMB::SMB1::Packet::SessionSetupRequest
Generates the RubySMB::SMB1::Packet::SessionSetupRequest packet with the NTLM Type 3 (Auth) message in the security_blob field.
-
#smb2_authenticate ⇒ Object
Handles SMB2 Kerberos Authentication by delegating to a kerberos_authenticator implementation to generate a GSS security blob with an embedded AP_REQ.
- #smb2_kerberos_authenticate(security_blob) ⇒ Object
- #smb2_kerberos_authenticate_packet(security_blob) ⇒ Object
Instance Method Details
#authenticate ⇒ Object
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
# File 'lib/msf/core/exploit/remote/smb/client/kerberos_authentication.rb', line 13 def authenticate raise ::RubySMB::Error::AuthenticationFailure, "Missing negotiation security buffer" if negotiation_security_buffer.nil? begin gss_api = OpenSSL::ASN1.decode(negotiation_security_buffer) mech_types = RubySMB::Gss.asn1dig(gss_api, 1, 0, 0, 0)&.value || [] has_kerberos_gss_mech_type = mech_types&.any? { |mech_type| mech_type.value == ::Rex::Proto::Gss::OID_MICROSOFT_KERBEROS_5.value } rescue OpenSSL::ASN1::ASN1Error raise ::Rex::Proto::Kerberos::Model::Error::KerberosDecodingError.new('Invalid GSS Response') end error = "Unable to negotiate kerberos with the remote host. Expected oid #{::Rex::Proto::Gss::OID_MICROSOFT_KERBEROS_5.value} in #{mech_types.map(&:value).inspect}" raise ::RubySMB::Error::AuthenticationFailure, error unless has_kerberos_gss_mech_type if smb1 smb1_authenticate else smb2_authenticate end end |
#kerberos_authenticator=(kerberos_authenticator) ⇒ Object
9 10 11 |
# File 'lib/msf/core/exploit/remote/smb/client/kerberos_authentication.rb', line 9 def kerberos_authenticator=(kerberos_authenticator) @kerberos_authenticator = kerberos_authenticator end |
#smb1_authenticate ⇒ Object
Handles SMB1 Kerberos Authentication by delegating to a kerberos_authenticator implementation to generate a GSS security blob with an embedded AP_REQ. On success information is stored about the peer/server.
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/msf/core/exploit/remote/smb/client/kerberos_authentication.rb', line 41 def smb1_authenticate raise ::RubySMB::Error::AuthenticationFailure, 'Missing kerberos authenticator' unless @kerberos_authenticator kerberos_result = @kerberos_authenticator.authenticate @application_key = @session_key = kerberos_result[:session_key].value[0...16] raw_kerberos_response = smb1_kerberos_authenticate(kerberos_result[:security_blob]) response = smb1_session_setup_response(raw_kerberos_response) @kerberos_authenticator.validate_response!(response.data_block.security_blob) response_code = response.status_code # Store the available OS information before going forward. @peer_native_os = response.data_block.native_os.to_s @peer_native_lm = response.data_block.native_lan_man.to_s @user_id = response.smb_header.uid if response_code == WindowsError::NTStatus::STATUS_SUCCESS response_code end |
#smb1_kerberos_authenticate(security_buffer) ⇒ String
Returns the raw binary response from the server.
67 68 69 70 |
# File 'lib/msf/core/exploit/remote/smb/client/kerberos_authentication.rb', line 67 def smb1_kerberos_authenticate(security_buffer) packet = smb1_kerberos_authenticate_packet(security_buffer) send_recv(packet) end |
#smb1_kerberos_authenticate_packet(security_blob) ⇒ RubySMB::SMB1::Packet::SessionSetupRequest
Generates the RubySMB::SMB1::Packet::SessionSetupRequest packet with the NTLM Type 3 (Auth) message in the security_blob field.
78 79 80 81 82 83 84 85 86 |
# File 'lib/msf/core/exploit/remote/smb/client/kerberos_authentication.rb', line 78 def smb1_kerberos_authenticate_packet(security_blob) packet = RubySMB::SMB1::Packet::SessionSetupRequest.new # packet.smb_header.uid = user_id packet.set_security_buffer(security_blob) packet.parameter_block.max_buffer_size = self.max_buffer_size packet.parameter_block.max_mpx_count = 50 packet.smb_header.flags2.extended_security = 1 packet end |
#smb2_authenticate ⇒ Object
Handles SMB2 Kerberos Authentication by delegating to a kerberos_authenticator implementation to generate a GSS security blob with an embedded AP_REQ. On success information is stored about the peer/server.
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/msf/core/exploit/remote/smb/client/kerberos_authentication.rb', line 95 def smb2_authenticate raise ::RubySMB::Error::AuthenticationFailure, 'Missing kerberos authenticator' unless @kerberos_authenticator kerberos_result = @kerberos_authenticator.authenticate raw_kerberos_response = smb2_kerberos_authenticate(kerberos_result[:security_blob]) response = smb2_session_setup_response(raw_kerberos_response) @kerberos_authenticator.validate_response!(response.buffer) @session_id = response.smb2_header.session_id if @encryption_algorithm.present? key_len = OpenSSL::Cipher.new(@encryption_algorithm).key_len else key_len = 16 end @application_key = @session_key = kerberos_result[:session_key].value[0...key_len] @session_is_guest = response.session_flags.guest == 1 if @smb3 if response.session_flags.encrypt_data == 1 # if the server indicates that encryption is required, enable it @session_encrypt_data = true elsif (@session_is_guest && password != '') || (username == '' && password == '') # disable encryption when necessary @session_encrypt_data = false end # see: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/7fd079ca-17e6-4f02-8449-46b606ea289c if @dialect == '0x0300' || @dialect == '0x0302' @application_key = RubySMB::Crypto::KDF.counter_mode( @session_key, "SMB2APP\x00", "SmbRpc\x00" ) else @application_key = RubySMB::Crypto::KDF.counter_mode( @session_key, "SMBAppKey\x00", @preauth_integrity_hash_value ) end # otherwise, leave encryption to the default value that it was initialized to end ###### # DEBUG #puts "Session ID = #{@session_id.to_binary_s.each_byte.map {|e| '%02x' % e}.join}" #puts "Session key = #{@session_key.each_byte.map {|e| '%02x' % e}.join}" #puts "PreAuthHash = #{@preauth_integrity_hash_value.each_byte.map {|e| '%02x' % e}.join}" if @preauth_integrity_hash_value ###### response.status_code end |
#smb2_kerberos_authenticate(security_blob) ⇒ Object
156 157 158 159 160 161 162 163 |
# File 'lib/msf/core/exploit/remote/smb/client/kerberos_authentication.rb', line 156 def smb2_kerberos_authenticate(security_blob) packet = smb2_kerberos_authenticate_packet(security_blob) response = send_recv(packet) if @dialect == '0x0311' update_preauth_hash(packet) end response end |
#smb2_kerberos_authenticate_packet(security_blob) ⇒ Object
149 150 151 152 153 154 |
# File 'lib/msf/core/exploit/remote/smb/client/kerberos_authentication.rb', line 149 def smb2_kerberos_authenticate_packet(security_blob) packet = RubySMB::SMB2::Packet::SessionSetupRequest.new packet.set_security_buffer(security_blob) packet.security_mode.signing_enabled = 1 packet end |