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)
def setup(self): 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.mode = self.settings.mode 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_server, targetName=targetName, targetInfo=targetInfo, version=version, flags=self.flags)
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())
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!')
def load_challenge(self, data): self.ntlmChallenge = NTLMChallenge.from_bytes(data)