Module: RubySMB::Client::Authentication
Overview
This module holds all the backend client methods for authentication.
Instance Method Summary collapse
-
#authenticate ⇒ WindowsError::NTStatus
Responsible for handling Authentication and Session Setup for the SMB Client.
-
#smb1_anonymous_auth ⇒ WindowsError::ErrorCode
Attempts an Anonymous logon to the remote server.
-
#smb1_anonymous_auth_request ⇒ Object
Creates a SessionSetupRequest for an anonymous access session.
- #smb1_anonymous_auth_response(raw_response) ⇒ Object
-
#smb1_authenticate ⇒ Object
Handles the SMB1 NTLMSSP 4-way handshake for Authentication and store information about the peer/server.
-
#smb1_ntlmssp_auth_packet(type3_message, user_id) ⇒ RubySMB::SMB1::Packet::SessionSetupRequest
Generates the SMB1::Packet::SessionSetupRequest packet with the NTLM Type 3 (Auth) message in the security_blob field.
-
#smb1_ntlmssp_authenticate(type3_message, user_id) ⇒ String
Takes the NTLM Type 3 (authenticate) message and calls the routines to build the Auth packet, sends the packet and receives the raw response.
-
#smb1_ntlmssp_challenge_packet(raw_response) ⇒ Object
Takes the raw binary string and returns a SMB1::Packet::SessionSetupResponse.
-
#smb1_ntlmssp_final_packet(raw_response) ⇒ Object
Takes the raw binary string and returns a SMB1::Packet::SessionSetupResponse.
-
#smb1_ntlmssp_negotiate ⇒ String
Sends the SMB1::Packet::SessionSetupRequest packet and receives the response.
-
#smb1_ntlmssp_negotiate_packet ⇒ RubySMB::SMB1::Packet::SessionSetupRequest
Creates the SMB1::Packet::SessionSetupRequest packet for the first part of the NTLMSSP 4-way hnadshake.
-
#smb1_session_setup_response(raw_response) ⇒ Object
Takes the raw binary string and returns a SMB1::Packet::SessionSetupResponse.
-
#smb1_type2_message(response_packet) ⇒ String
Parses out the NTLM Type 2 Message from a SMB1::Packet::SessionSetupResponse.
-
#smb2_authenticate ⇒ Object
Handles the SMB2 NTLMSSP 4-way handshake for Authentication and store information about the peer/server.
-
#smb2_ntlmssp_auth_packet(type3_message, session_id) ⇒ RubySMB::SMB2::Packet::SessionSetupRequest
Generates the SMB2::Packet::SessionSetupRequest packet with the NTLM Type 3 (Auth) message in the security_blob field.
-
#smb2_ntlmssp_authenticate(type3_message, user_id) ⇒ String
Takes the NTLM Type 3 (authenticate) message and calls the routines to build the Auth packet, sends the packet and receives the raw response.
-
#smb2_ntlmssp_challenge_packet(raw_response) ⇒ Object
Takes the raw binary string and returns a SMB2::Packet::SessionSetupResponse.
-
#smb2_ntlmssp_final_packet(raw_response) ⇒ Object
Takes the raw binary string and returns a SMB2::Packet::SessionSetupResponse.
-
#smb2_ntlmssp_negotiate ⇒ String
Sends the SMB2::Packet::SessionSetupRequest packet and receives the response.
-
#smb2_ntlmssp_negotiate_packet ⇒ RubySMB::SMB2::Packet::SessionSetupRequest
Creates the SMB2::Packet::SessionSetupRequest packet for the first part of the NTLMSSP 4-way handshake.
-
#smb2_session_setup_response(raw_response) ⇒ Object
Takes the raw binary string and returns a SMB2::Packet::SessionSetupResponse.
-
#smb2_type2_message(response_packet) ⇒ String
Parses out the NTLM Type 2 Message from a SMB2::Packet::SessionSetupResponse.
Methods included from PeerInfo
#extract_os_version, #store_target_info
Instance Method Details
#authenticate ⇒ WindowsError::NTStatus
Responsible for handling Authentication and Session Setup for the SMB Client. It returns the final Status code from the authentication exchange.
14 15 16 17 18 19 20 21 22 23 24 |
# File 'lib/ruby_smb/client/authentication.rb', line 14 def authenticate if smb1 if username.empty? && password.empty? smb1_anonymous_auth else smb1_authenticate end else smb2_authenticate end end |
#smb1_anonymous_auth ⇒ WindowsError::ErrorCode
Attempts an Anonymous logon to the remote server.
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/ruby_smb/client/authentication.rb', line 33 def smb1_anonymous_auth request = smb1_anonymous_auth_request raw_response = send_recv(request) response = smb1_anonymous_auth_response(raw_response) response_code = response.status_code if response_code == WindowsError::NTStatus::STATUS_SUCCESS self.user_id = response.smb_header.uid self.peer_native_os = response.data_block.native_os.to_s self.peer_native_lm = response.data_block.native_lan_man.to_s self.primary_domain = response.data_block.primary_domain.to_s end response_code end |
#smb1_anonymous_auth_request ⇒ Object
Creates a SessionSetupRequest for an anonymous access session.
51 52 53 54 55 56 57 58 |
# File 'lib/ruby_smb/client/authentication.rb', line 51 def smb1_anonymous_auth_request packet = RubySMB::SMB1::Packet::SessionSetupLegacyRequest.new packet.data_block.oem_password = "\x00" packet.parameter_block.max_buffer_size = self.max_buffer_size packet.parameter_block.max_mpx_count = 50 packet.parameter_block.capabilities.extended_security = 0 packet end |
#smb1_anonymous_auth_response(raw_response) ⇒ Object
60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/ruby_smb/client/authentication.rb', line 60 def smb1_anonymous_auth_response(raw_response) packet = RubySMB::SMB1::Packet::SessionSetupLegacyResponse.read(raw_response) unless packet.valid? raise RubySMB::Error::InvalidPacket.new( expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID, expected_cmd: RubySMB::SMB1::Packet::SessionSetupLegacyResponse::COMMAND, packet: packet ) end packet end |
#smb1_authenticate ⇒ Object
Handles the SMB1 NTLMSSP 4-way handshake for Authentication and store information about the peer/server.
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/ruby_smb/client/authentication.rb', line 75 def smb1_authenticate response = smb1_ntlmssp_negotiate challenge_packet = smb1_ntlmssp_challenge_packet(response) # Store the available OS information before going forward. @peer_native_os = challenge_packet.data_block.native_os.to_s @peer_native_lm = challenge_packet.data_block.native_lan_man.to_s user_id = challenge_packet.smb_header.uid = (challenge_packet) = @ntlm_client.init_context() @application_key = @session_key = @ntlm_client.session_key = @ntlm_client.session. store_target_info(.target_info) if .has_flag?(:TARGET_INFO) @os_version = extract_os_version(.os_version.to_s) unless .os_version.empty? raw = smb1_ntlmssp_authenticate(, user_id) response = smb1_ntlmssp_final_packet(raw) response_code = response.status_code @user_id = user_id if response_code == WindowsError::NTStatus::STATUS_SUCCESS response_code end |
#smb1_ntlmssp_auth_packet(type3_message, user_id) ⇒ RubySMB::SMB1::Packet::SessionSetupRequest
Generates the SMB1::Packet::SessionSetupRequest packet with the NTLM Type 3 (Auth) message in the security_blob field.
127 128 129 130 131 132 133 134 135 |
# File 'lib/ruby_smb/client/authentication.rb', line 127 def smb1_ntlmssp_auth_packet(, user_id) packet = RubySMB::SMB1::Packet::SessionSetupRequest.new packet.smb_header.uid = user_id packet.set_type3_blob(.serialize) 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 |
#smb1_ntlmssp_authenticate(type3_message, user_id) ⇒ String
Takes the NTLM Type 3 (authenticate) message and calls the routines to build the Auth packet, sends the packet and receives the raw response.
116 117 118 119 |
# File 'lib/ruby_smb/client/authentication.rb', line 116 def smb1_ntlmssp_authenticate(, user_id) packet = smb1_ntlmssp_auth_packet(, user_id) send_recv(packet) end |
#smb1_ntlmssp_challenge_packet(raw_response) ⇒ Object
Takes the raw binary string and returns a SMB1::Packet::SessionSetupResponse
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
# File 'lib/ruby_smb/client/authentication.rb', line 172 def smb1_ntlmssp_challenge_packet(raw_response) packet = RubySMB::SMB1::Packet::SessionSetupResponse.read(raw_response) unless packet.valid? raise RubySMB::Error::InvalidPacket.new( expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID, expected_cmd: RubySMB::SMB1::Packet::SessionSetupResponse::COMMAND, packet: packet ) end status_code = packet.status_code unless status_code.name == 'STATUS_MORE_PROCESSING_REQUIRED' raise RubySMB::Error::UnexpectedStatusCode, status_code end packet end |
#smb1_ntlmssp_final_packet(raw_response) ⇒ Object
Takes the raw binary string and returns a SMB1::Packet::SessionSetupResponse
167 168 169 |
# File 'lib/ruby_smb/client/authentication.rb', line 167 def smb1_ntlmssp_final_packet(raw_response) smb1_session_setup_response(raw_response) end |
#smb1_ntlmssp_negotiate ⇒ String
Sends the SMB1::Packet::SessionSetupRequest packet and receives the response.
105 106 107 108 |
# File 'lib/ruby_smb/client/authentication.rb', line 105 def smb1_ntlmssp_negotiate packet = smb1_ntlmssp_negotiate_packet send_recv(packet) end |
#smb1_ntlmssp_negotiate_packet ⇒ RubySMB::SMB1::Packet::SessionSetupRequest
Creates the SMB1::Packet::SessionSetupRequest packet for the first part of the NTLMSSP 4-way hnadshake. This packet initializes negotiations for the NTLMSSP authentication
142 143 144 145 146 147 148 149 150 |
# File 'lib/ruby_smb/client/authentication.rb', line 142 def smb1_ntlmssp_negotiate_packet = ntlm_client.init_context packet = RubySMB::SMB1::Packet::SessionSetupRequest.new packet.set_type1_blob(.serialize) 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 |
#smb1_session_setup_response(raw_response) ⇒ Object
Takes the raw binary string and returns a SMB1::Packet::SessionSetupResponse
153 154 155 156 157 158 159 160 161 162 163 164 |
# File 'lib/ruby_smb/client/authentication.rb', line 153 def smb1_session_setup_response(raw_response) packet = RubySMB::SMB1::Packet::SessionSetupResponse.read(raw_response) unless packet.valid? raise RubySMB::Error::InvalidPacket.new( expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID, expected_cmd: RubySMB::SMB1::Packet::SessionSetupResponse::COMMAND, packet: packet ) end packet end |
#smb1_type2_message(response_packet) ⇒ String
Parses out the NTLM Type 2 Message from a SMB1::Packet::SessionSetupResponse
194 195 196 197 198 199 |
# File 'lib/ruby_smb/client/authentication.rb', line 194 def (response_packet) sec_blob = response_packet.data_block.security_blob ntlmssp_offset = sec_blob.index('NTLMSSP') type2_blob = sec_blob.slice(ntlmssp_offset..-1) [type2_blob].pack('m') end |
#smb2_authenticate ⇒ Object
Handles the SMB2 NTLMSSP 4-way handshake for Authentication and store information about the peer/server.
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 |
# File 'lib/ruby_smb/client/authentication.rb', line 207 def smb2_authenticate response = smb2_ntlmssp_negotiate challenge_packet = smb2_ntlmssp_challenge_packet(response) if @dialect == '0x0311' update_preauth_hash(challenge_packet) end @session_id = challenge_packet.smb2_header.session_id = (challenge_packet) = @ntlm_client.init_context() @application_key = @session_key = @ntlm_client.session_key = ntlm_client.session. store_target_info(.target_info) if .has_flag?(:TARGET_INFO) @os_version = extract_os_version(.os_version.to_s) unless .os_version.empty? raw = smb2_ntlmssp_authenticate(, @session_id) response = smb2_ntlmssp_final_packet(raw) @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_ntlmssp_auth_packet(type3_message, session_id) ⇒ RubySMB::SMB2::Packet::SessionSetupRequest
Generates the SMB2::Packet::SessionSetupRequest packet with the NTLM Type 3 (Auth) message in the security_blob field.
356 357 358 359 360 361 362 |
# File 'lib/ruby_smb/client/authentication.rb', line 356 def smb2_ntlmssp_auth_packet(, session_id) packet = RubySMB::SMB2::Packet::SessionSetupRequest.new packet.smb2_header.session_id = session_id packet.set_type3_blob(.serialize) packet.security_mode.signing_enabled = 1 packet end |
#smb2_ntlmssp_authenticate(type3_message, user_id) ⇒ String
Takes the NTLM Type 3 (authenticate) message and calls the routines to build the Auth packet, sends the packet and receives the raw response.
341 342 343 344 345 346 347 348 |
# File 'lib/ruby_smb/client/authentication.rb', line 341 def smb2_ntlmssp_authenticate(, user_id) packet = smb2_ntlmssp_auth_packet(, user_id) response = send_recv(packet) if @dialect == '0x0311' update_preauth_hash(packet) end response end |
#smb2_ntlmssp_challenge_packet(raw_response) ⇒ Object
Takes the raw binary string and returns a SMB2::Packet::SessionSetupResponse
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 |
# File 'lib/ruby_smb/client/authentication.rb', line 281 def smb2_ntlmssp_challenge_packet(raw_response) packet = RubySMB::SMB2::Packet::SessionSetupResponse.read(raw_response) unless packet.valid? raise RubySMB::Error::InvalidPacket.new( expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID, expected_cmd: RubySMB::SMB2::Packet::SessionSetupResponse::COMMAND, packet: packet ) end status_code = packet.status_code unless status_code.name == 'STATUS_MORE_PROCESSING_REQUIRED' raise RubySMB::Error::UnexpectedStatusCode, status_code end packet end |
#smb2_ntlmssp_final_packet(raw_response) ⇒ Object
Takes the raw binary string and returns a SMB2::Packet::SessionSetupResponse
276 277 278 |
# File 'lib/ruby_smb/client/authentication.rb', line 276 def smb2_ntlmssp_final_packet(raw_response) smb2_session_setup_response(raw_response) end |
#smb2_ntlmssp_negotiate ⇒ String
Sends the SMB2::Packet::SessionSetupRequest packet and receives the response.
302 303 304 305 306 307 308 309 |
# File 'lib/ruby_smb/client/authentication.rb', line 302 def smb2_ntlmssp_negotiate packet = smb2_ntlmssp_negotiate_packet response = send_recv(packet) if @dialect == '0x0311' update_preauth_hash(packet) end response end |
#smb2_ntlmssp_negotiate_packet ⇒ RubySMB::SMB2::Packet::SessionSetupRequest
Creates the SMB2::Packet::SessionSetupRequest packet for the first part of the NTLMSSP 4-way handshake. This packet initializes negotiations for the NTLMSSP authentication
316 317 318 319 320 321 322 |
# File 'lib/ruby_smb/client/authentication.rb', line 316 def smb2_ntlmssp_negotiate_packet = ntlm_client.init_context packet = RubySMB::SMB2::Packet::SessionSetupRequest.new packet.set_type1_blob(.serialize) packet.security_mode.signing_enabled = 1 packet end |
#smb2_session_setup_response(raw_response) ⇒ Object
Takes the raw binary string and returns a SMB2::Packet::SessionSetupResponse
262 263 264 265 266 267 268 269 270 271 272 273 |
# File 'lib/ruby_smb/client/authentication.rb', line 262 def smb2_session_setup_response(raw_response) packet = RubySMB::SMB2::Packet::SessionSetupResponse.read(raw_response) unless packet.valid? raise RubySMB::Error::InvalidPacket.new( expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID, expected_cmd: RubySMB::SMB2::Packet::SessionSetupResponse::COMMAND, packet: packet ) end packet end |
#smb2_type2_message(response_packet) ⇒ String
Parses out the NTLM Type 2 Message from a SMB2::Packet::SessionSetupResponse
328 329 330 331 332 333 |
# File 'lib/ruby_smb/client/authentication.rb', line 328 def (response_packet) sec_blob = response_packet.buffer ntlmssp_offset = sec_blob.index('NTLMSSP') type2_blob = sec_blob.slice(ntlmssp_offset..-1) [type2_blob].pack('m') end |