Beispiel #1
0
    def setup(self):
        self.mode = self.settings.mode
        if self.mode.upper() == 'MANUAL':
            #for passign the messages automatically with the sessionbasekey, the using this class for sign and seal
            return

        if 'challenge' not in self.settings.template:
            self.challenge = os.urandom(8)
        else:
            self.challenge = self.settings.template['challenge']
        self.flags = self.settings.template['flags']
        if 'session_key' in self.settings.template:
            self.RandomSessionKey = self.settings.template['session_key']

        self.timestamp = self.settings.template.get(
            'timestamp')  #used in unittest only!

        if self.mode.upper() == 'SERVER':
            version = self.settings.template['version']
            targetName = self.settings.template['targetname']
            targetInfo = self.settings.template['targetinfo']

            self.ntlmChallenge = NTLMChallenge.construct(
                challenge=self.challenge,
                targetName=targetName,
                targetInfo=targetInfo,
                version=version,
                flags=self.flags)
Beispiel #2
0
def test_msdn():
	credential = Credential()
	credential.username = '******'
	credential.domain = 'Domain'
	credential.password = '******'
	
	template = {
			'flags'            :  NegotiateFlags.NEGOTIATE_56|
								  NegotiateFlags.REQUEST_NON_NT_SESSION_KEY|
								  NegotiateFlags.NEGOTIATE_KEY_EXCH|
								  NegotiateFlags.NEGOTIATE_128|
								  NegotiateFlags.NEGOTIATE_VERSION|
								  NegotiateFlags.TARGET_TYPE_SERVER|
								  NegotiateFlags.NEGOTIATE_ALWAYS_SIGN|
								  NegotiateFlags.NEGOTIATE_NTLM|
								  NegotiateFlags.NEGOTIATE_SIGN|
								  NegotiateFlags.NEGOTIATE_SEAL|
								  NegotiateFlags.NTLM_NEGOTIATE_OEM|
								  NegotiateFlags.NEGOTIATE_UNICODE,
			'version'          : Version.construct(WindowsMajorVersion.WINDOWS_MAJOR_VERSION_10, minor = WindowsMinorVersion.WINDOWS_MINOR_VERSION_0, build = 15063 ),
			'domain_name'      : 'Domain',
			'workstation_name' : 'COMPUTER',
			'ntlm_downgrade'   : True,
			'extended_security': False
	}
	settings = NTLMHandlerSettings(credential, mode = 'CLIENT', template_name = None, ntlm_downgrade = True, extended_security = False, custom_template = template)
	handler = NTLMAUTHHandler(settings)
	#assert handler.flags == int.from_bytes(b'\x33\x82\x02\xe2', "little", signed = False)
	data, is_res = handler.authenticate(None)
	print(data)
	print(is_res)
	
	details = AVPairs({AVPAIRType.MsvAvNbDomainName: 'TEST', AVPAIRType.MsvAvNbComputerName: 'WIN2019AD', AVPAIRType.MsvAvDnsDomainName: 'test.corp', AVPAIRType.MsvAvDnsComputerName: 'WIN2019AD.test.corp', AVPAIRType.MsvAvTimestamp: b'\xae\xc6\x00\xbf\xc5\xfd\xd4\x01', AVPAIRType.MsvAvFlags: b'\x02\x00\x00\x00', AVPAIRType.MsvAvSingleHost: b"0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x00R}'\xf24\xdet7`\x96c\x84\xd3oa\xae*\xa4\xfc*8\x06\x99\xf8\xca\xa6\x00\x01\x1bHm\x89", AVPAIRType.MsvChannelBindings: b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', AVPAIRType.MsvAvTargetName: 'cifs/10.10.10.2'})
	
	challenge = NTLMChallenge.construct(challenge=b'\x01\x23\x45\x67\x89\xab\xcd\xef', targetName = 'Domain', targetInfo = details, version = handler.ntlmNegotiate.Version, flags= handler.flags)
	data, is_res = handler.authenticate(challenge.to_bytes())
	print(data)
	print(is_res)
	
	print(handler.ntlmAuthenticate.LMChallenge.to_bytes().hex())
	print(handler.ntlmAuthenticate.NTChallenge.to_bytes().hex())
Beispiel #3
0
    async def authenticate(self,
                           authData,
                           flags=None,
                           seq_number=0,
                           is_rpc=False):
        if self.mode.upper() == 'SERVER':
            if self.ntlmNegotiate is None:
                ###parse client NTLMNegotiate message
                self.ntlmNegotiate = NTLMNegotiate.from_bytes(authData)
                return self.ntlmChallenge.to_bytes(), True, None

            elif self.ntlmAuthenticate is None:
                self.ntlmAuthenticate = NTLMAuthenticate.from_bytes(
                    authData, self.use_NTLMv2)
                creds = NTLMcredential.construct(self.ntlmNegotiate,
                                                 self.ntlmChallenge,
                                                 self.ntlmAuthenticate)

                # TODO: check when is sessionkey needed and check when is singing needed, and calculate the keys!
                # self.calc_SessionBaseKey()
                # self.calc_KeyExchangeKey()
                auth_credential = creds[0]
                #self.SessionBaseKey = auth_credential.calc_session_base_key()
                #self.calc_key_exchange_key()

                if auth_credential.verify(self.credential):
                    return AuthResult.FAIL, auth_credential, None
                else:
                    return AuthResult.FAIL, auth_credential, None

            else:
                raise Exception('Too many calls to do_AUTH function!')

        elif self.mode.upper() == 'CLIENT':
            if self.iteration_cnt == 0:
                if authData is not None:
                    raise Exception(
                        'First call as client MUST be with empty data!')

                if is_rpc == True:
                    #rpc (unknow reason) reqauires seal to be set, otherwise it will fail to authenticate
                    self.set_seal()

                self.iteration_cnt += 1
                #negotiate message was already calulcated in setup
                self.ntlmNegotiate = NTLMNegotiate.construct(
                    self.flags,
                    domainname=self.settings.template['domain_name'],
                    workstationname=self.settings.template['workstation_name'],
                    version=self.settings.template.get('version'))
                self.ntlmNegotiate_raw = self.ntlmNegotiate.to_bytes()
                return self.ntlmNegotiate_raw, True, None

            else:
                #server challenge incoming
                self.ntlmChallenge_raw = authData
                self.ntlmChallenge = NTLMChallenge.from_bytes(authData)

                if is_rpc == True:
                    #rpc (unknow reason) reqauires seal to be set, otherwise it will fail to authenticate
                    self.set_seal()

                ##################self.flags = self.ntlmChallenge.NegotiateFlags

                #we need to calculate the response based on the credential and the settings flags
                if self.settings.ntlm_downgrade == True:
                    #NTLMv1 authentication
                    # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/464551a8-9fc4-428e-b3d3-bc5bfb2e73a5

                    #check if we authenticate as guest
                    if self.settings.credential.is_guest == True:
                        lmresp = LMResponse()
                        lmresp.Response = b'\x00'
                        self.ntlmAuthenticate = NTLMAuthenticate.construct(
                            self.flags, lm_response=lmresp)
                        return self.ntlmAuthenticate.to_bytes(), False, None

                    if self.flags & NegotiateFlags.NEGOTIATE_EXTENDED_SESSIONSECURITY:
                        #Extended auth!
                        self.ntlm_credentials = netntlm_ess.construct(
                            self.ntlmChallenge.ServerChallenge, self.challenge,
                            self.settings.credential)

                        self.KeyExchangeKey = self.ntlm_credentials.calc_key_exchange_key(
                        )
                        self.setup_crypto()

                        self.ntlmAuthenticate = NTLMAuthenticate.construct(
                            self.flags,
                            lm_response=self.ntlm_credentials.LMResponse,
                            nt_response=self.ntlm_credentials.NTResponse,
                            version=self.ntlmNegotiate.Version,
                            encrypted_session=self.EncryptedRandomSessionKey)
                    else:
                        self.ntlm_credentials = netntlm.construct(
                            self.ntlmChallenge.ServerChallenge,
                            self.settings.credential)

                        self.KeyExchangeKey = self.ntlm_credentials.calc_key_exchange_key(
                            with_lm=self.flags
                            & NegotiateFlags.NEGOTIATE_LM_KEY,
                            non_nt_session_key=self.flags
                            & NegotiateFlags.REQUEST_NON_NT_SESSION_KEY)
                        self.setup_crypto()
                        self.ntlmAuthenticate = NTLMAuthenticate.construct(
                            self.flags,
                            lm_response=self.ntlm_credentials.LMResponse,
                            nt_response=self.ntlm_credentials.NTResponse,
                            version=self.ntlmNegotiate.Version,
                            encrypted_session=self.EncryptedRandomSessionKey)

                else:
                    #NTLMv2
                    # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/5e550938-91d4-459f-b67d-75d70009e3f3
                    if self.settings.credential.is_guest == True:
                        lmresp = LMResponse()
                        lmresp.Response = b'\x00'
                        self.ntlmAuthenticate = NTLMAuthenticate.construct(
                            self.flags, lm_response=lmresp)
                        return self.ntlmAuthenticate.to_bytes(), False, None

                    else:
                        #comment this out for testing!
                        ti = self.ntlmChallenge.TargetInfo
                        ti[AVPAIRType.MsvAvTargetName] = 'cifs/%s' % ti[
                            AVPAIRType.MsvAvNbComputerName]
                        ###

                        self.ntlm_credentials = netntlmv2.construct(
                            self.ntlmChallenge.ServerChallenge,
                            self.challenge,
                            ti,
                            self.settings.credential,
                            timestamp=self.timestamp)
                        self.KeyExchangeKey = self.ntlm_credentials.calc_key_exchange_key(
                        )
                        self.setup_crypto()

                        #TODO: if "ti" / targetinfo in the challenge message has "MsvAvFlags" type and the bit for MIC is set (0x00000002) we need to send a MIC. probably...
                        mic = None

                        self.ntlmAuthenticate = NTLMAuthenticate.construct(
                            self.flags,
                            domainname=self.settings.credential.domain,
                            workstationname=self.settings.credential.
                            workstation,
                            username=self.settings.credential.username,
                            lm_response=self.ntlm_credentials.LMResponse,
                            nt_response=self.ntlm_credentials.NTResponse,
                            version=self.ntlmNegotiate.Version,
                            encrypted_session=self.EncryptedRandomSessionKey,
                            mic=mic)

                self.ntlmAuthenticate_raw = self.ntlmAuthenticate.to_bytes()
                return self.ntlmAuthenticate_raw, False, None

        elif self.mode.upper() == 'RELAY':
            if self.iteration_cnt == 0:
                self.ntlmNegotiate_raw = authData
                self.ntlmNegotiate = NTLMNegotiate.from_bytes(authData)
                self.iteration_cnt += 1

            elif self.iteration_cnt == 1:
                self.ntlmChallenge_raw = authData
                self.ntlmChallenge = NTLMChallenge.from_bytes(authData)
                self.iteration_cnt += 1

            elif self.iteration_cnt == 2:
                self.ntlmChallenge_raw = authData
                self.ntlmChallenge = NTLMChallenge.from_bytes(authData)
                self.iteration_cnt += 1

            else:
                raise Exception('Too many iterations for relay mode!')


#def test_msdn():
#	credential = Credential()
#	credential.username = '******'
#	credential.domain = 'Domain'
#	credential.password = '******'
#
#	template = {
#			'flags'            :  NegotiateFlags.NEGOTIATE_56|
#								  NegotiateFlags.REQUEST_NON_NT_SESSION_KEY|
#								  NegotiateFlags.NEGOTIATE_KEY_EXCH|
#								  NegotiateFlags.NEGOTIATE_128|
#								  NegotiateFlags.NEGOTIATE_VERSION|
#								  NegotiateFlags.TARGET_TYPE_SERVER|
#								  NegotiateFlags.NEGOTIATE_ALWAYS_SIGN|
#								  NegotiateFlags.NEGOTIATE_NTLM|
#								  NegotiateFlags.NEGOTIATE_SIGN|
#								  NegotiateFlags.NEGOTIATE_SEAL|
#								  NegotiateFlags.NTLM_NEGOTIATE_OEM|
#								  NegotiateFlags.NEGOTIATE_UNICODE,
#			'version'          : Version.construct(WindowsMajorVersion.WINDOWS_MAJOR_VERSION_10, minor = WindowsMinorVersion.WINDOWS_MINOR_VERSION_0, build = 15063 ),
#			'domain_name'      : 'Domain',
#			'workstation_name' : 'COMPUTER',
#			'ntlm_downgrade'   : True,
#			'extended_security': False
#	}
#	settings = NTLMHandlerSettings(credential, mode = 'CLIENT', template_name = None, ntlm_downgrade = True, extended_security = False, custom_template = template)
#	handler = NTLMAUTHHandler(settings)
#	#assert handler.flags == int.from_bytes(b'\x33\x82\x02\xe2', "little", signed = False)
#	data, is_res = handler.authenticate(None)
#	print(data)
#	print(is_res)
#
#	details = AVPairs({AVPAIRType.MsvAvNbDomainName: 'TEST', AVPAIRType.MsvAvNbComputerName: 'WIN2019AD', AVPAIRType.MsvAvDnsDomainName: 'test.corp', AVPAIRType.MsvAvDnsComputerName: 'WIN2019AD.test.corp', AVPAIRType.MsvAvTimestamp: b'\xae\xc6\x00\xbf\xc5\xfd\xd4\x01', AVPAIRType.MsvAvFlags: b'\x02\x00\x00\x00', AVPAIRType.MsvAvSingleHost: b"0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x00R}'\xf24\xdet7`\x96c\x84\xd3oa\xae*\xa4\xfc*8\x06\x99\xf8\xca\xa6\x00\x01\x1bHm\x89", AVPAIRType.MsvChannelBindings: b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', AVPAIRType.MsvAvTargetName: 'cifs/10.10.10.2'})
#
#	challenge = NTLMChallenge.construct(challenge=b'\x01\x23\x45\x67\x89\xab\xcd\xef', targetName = 'Domain', targetInfo = details, version = handler.ntlmNegotiate.Version, flags= handler.flags)
#	data, is_res = handler.authenticate(challenge.to_bytes())
#	print(data)
#	print(is_res)
#
#	print(handler.ntlmAuthenticate.LMChallenge.to_bytes().hex())
#	print(handler.ntlmAuthenticate.NTChallenge.to_bytes().hex())
#
#
#def test():
#	template_name = 'Windows10_15063'
#	credential = Credential()
#	credential.username = '******'
#	credential.password = '******'
#
#	settings = NTLMHandlerSettings(credential, mode = 'CLIENT', template_name = template_name, ntlm_downgrade = False, extended_security = True)
#	handler = NTLMAUTHHandler(settings)
#	data, is_res = handler.authenticate(None)
#	print(data)
#	print(is_res)
#
#if __name__ == '__main__':
#	from aiosmb.ntlm.structures.version import Version, WindowsMajorVersion, WindowsMinorVersion
#	test_msdn()
Beispiel #4
0
 def load_challenge(self, data):
     self.ntlmChallenge = NTLMChallenge.from_bytes(data)
Beispiel #5
0
	async def authenticate(self, authData, flags = None, seq_number = 0, is_rpc = False):
		if self.mode.upper() == 'SERVER':
			if self.ntlmNegotiate is None:
				###parse client NTLMNegotiate message
				self.ntlmNegotiate = NTLMNegotiate.from_bytes(authData)
				return self.ntlmChallenge.to_bytes(), True 

			elif self.ntlmAuthenticate is None:
				self.ntlmAuthenticate = NTLMAuthenticate.from_bytes(authData, self.use_NTLMv2)
				creds = NTLMcredential.construct(self.ntlmNegotiate, self.ntlmChallenge, self.ntlmAuthenticate)
				print(creds)

				# TODO: check when is sessionkey needed and check when is singing needed, and calculate the keys!
				# self.calc_SessionBaseKey()
				# self.calc_KeyExchangeKey()
				auth_credential = creds[0]
				#self.SessionBaseKey = auth_credential.calc_session_base_key()
				#self.calc_key_exchange_key()

				if auth_credential.verify(self.credential):
					return AuthResult.FAIL, auth_credential
				else:
					return AuthResult.FAIL, auth_credential

			else:
				raise Exception('Too many calls to do_AUTH function!')
				
		elif self.mode.upper() == 'CLIENT':
			if self.iteration_cnt == 0:
				if authData is not None:
					raise Exception('First call as client MUST be with empty data!')
					
				if is_rpc == True:
					#rpc (unknow reason) reqauires seal to be set, otherwise it will fail to authenticate
					self.set_seal()
				
				self.iteration_cnt += 1
				#negotiate message was already calulcated in setup
				self.ntlmNegotiate = NTLMNegotiate.construct(self.flags, domainname = self.settings.template['domain_name'], workstationname = self.settings.template['workstation_name'], version = self.settings.template.get('version'))			
				self.ntlmNegotiate_raw = self.ntlmNegotiate.to_bytes()
				return self.ntlmNegotiate_raw, True
				
			else:
				#server challenge incoming
				self.ntlmChallenge_raw = authData
				self.ntlmChallenge = NTLMChallenge.from_bytes(authData)
				
				
				if is_rpc == True:
					#rpc (unknow reason) reqauires seal to be set, otherwise it will fail to authenticate
					self.set_seal()
				
				##################self.flags = self.ntlmChallenge.NegotiateFlags
				
				#we need to calculate the response based on the credential and the settings flags
				if self.settings.ntlm_downgrade == True:
					#NTLMv1 authentication
					# https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/464551a8-9fc4-428e-b3d3-bc5bfb2e73a5
					
					#check if we authenticate as guest
					if self.settings.credential.is_guest == True:
						lmresp = LMResponse()
						lmresp.Response = b'\x00'
						self.ntlmAuthenticate = NTLMAuthenticate.construct(self.flags, lm_response= lmresp)
						return self.ntlmAuthenticate.to_bytes(), False
						
					if self.flags & NegotiateFlags.NEGOTIATE_EXTENDED_SESSIONSECURITY:
						#Extended auth!
						self.ntlm_credentials = netntlm_ess.construct(self.ntlmChallenge.ServerChallenge, self.challenge, self.settings.credential)
						
						self.KeyExchangeKey = self.ntlm_credentials.calc_key_exchange_key()						
						self.setup_crypto()
						
						self.ntlmAuthenticate = NTLMAuthenticate.construct(self.flags, lm_response= self.ntlm_credentials.LMResponse, nt_response = self.ntlm_credentials.NTResponse, version = self.ntlmNegotiate.Version, encrypted_session = self.EncryptedRandomSessionKey)
					else:
						self.ntlm_credentials = netntlm.construct(self.ntlmChallenge.ServerChallenge, self.settings.credential)
						
						self.KeyExchangeKey = self.ntlm_credentials.calc_key_exchange_key(with_lm = self.flags & NegotiateFlags.NEGOTIATE_LM_KEY, non_nt_session_key = self.flags & NegotiateFlags.REQUEST_NON_NT_SESSION_KEY)						
						self.setup_crypto()
						self.ntlmAuthenticate = NTLMAuthenticate.construct(self.flags, lm_response= self.ntlm_credentials.LMResponse, nt_response = self.ntlm_credentials.NTResponse, version = self.ntlmNegotiate.Version, encrypted_session = self.EncryptedRandomSessionKey)

							
							
				else:
					#NTLMv2
					# https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/5e550938-91d4-459f-b67d-75d70009e3f3
					if self.settings.credential.is_guest == True:
						lmresp = LMResponse()
						lmresp.Response = b'\x00'
						self.ntlmAuthenticate = NTLMAuthenticate.construct(self.flags, lm_response= lmresp)
						return self.ntlmAuthenticate.to_bytes(), False
						
					else:
						#comment this out for testing!
						ti = self.ntlmChallenge.TargetInfo
						ti[AVPAIRType.MsvAvTargetName] = 'cifs/%s' % ti[AVPAIRType.MsvAvNbComputerName]
						###
						
						self.ntlm_credentials = netntlmv2.construct(self.ntlmChallenge.ServerChallenge, self.challenge, ti, self.settings.credential, timestamp = self.timestamp)
						self.KeyExchangeKey = self.ntlm_credentials.calc_key_exchange_key()						
						self.setup_crypto()
						
						#TODO: if "ti" / targetinfo in the challenge message has "MsvAvFlags" type and the bit for MIC is set (0x00000002) we need to send a MIC. probably...
						mic = None
						
						self.ntlmAuthenticate = NTLMAuthenticate.construct(self.flags, domainname= self.settings.credential.domain, workstationname= self.settings.credential.workstation, username= self.settings.credential.username, lm_response= self.ntlm_credentials.LMResponse, nt_response= self.ntlm_credentials.NTResponse, version = self.ntlmNegotiate.Version, encrypted_session = self.EncryptedRandomSessionKey, mic = mic)
						
				self.ntlmAuthenticate_raw = self.ntlmAuthenticate.to_bytes()
				return self.ntlmAuthenticate_raw, False
				
		elif self.mode.upper() == 'RELAY':
			if self.iteration_cnt == 0:
				self.ntlmNegotiate_raw = authData
				self.ntlmNegotiate = NTLMNegotiate.from_bytes(authData)	
				self.iteration_cnt += 1
			
			elif self.iteration_cnt == 1:
				self.ntlmChallenge_raw = authData
				self.ntlmChallenge = NTLMChallenge.from_bytes(authData)
				self.iteration_cnt += 1
			
			elif self.iteration_cnt == 2:
				self.ntlmChallenge_raw = authData
				self.ntlmChallenge = NTLMChallenge.from_bytes(authData)
				self.iteration_cnt += 1
				
			else:
				raise Exception('Too many iterations for relay mode!')