def test_skip_me(self): auth = PasswordAuthentication('SERVER2012', 'Administrator', 'Pa55w0rd', compatibility=3) ntlm_context = NtlmContext(auth, session_security='none', hostname='thor') context = ntlm_context.initialize_security_context() token = context.send(None) # token.dump_flags() encoded = base64.b64encode(token) session = Session() session.headers.update({'Authorization': 'NTLM ' + encoded}) response = session.post("http://192.168.137.238:80") ntlm_regex = re.compile('(?:.*,)*\s*NTLM\s*([^,]*),?', re.I) authreq = response.headers.get('www-authenticate', None) if authreq: match_obj = ntlm_regex.search(authreq) if match_obj and len(match_obj.group(1)) > 0: encoded = match_obj.group(1) challenge = base64.b64decode(encoded) # challenge.dump_flags() print binascii.hexlify(challenge) response_token = context.send(challenge) # response_token.dump_flags() encoded_response_token = base64.b64encode(response_token) session.headers.update({'Authorization': 'NTLM ' + encoded_response_token}) response = session.get("http://192.168.137.238:80/") print response.content
def test_that_initialize_security_context_generates_negotiate_token(self): ntlm_context = NtlmContext(self.auth, hostname='thor', session_security='none') context = ntlm_context.initialize_security_context() token = context.send(None) self.assertEqual(self.tokens.negotiate, token)
def test_that_initialize_security_context_generates_negotiate_seal_token( self): ntlm_context = NtlmContext(self.auth, hostname='DEVMAC', session_security='encrypt') context = ntlm_context.initialize_security_context() token = context.send(None) self.assertEqual(token, self.tokens.negotiate_seal)
def __init__(self, pkg_name): self.pkg_info = win32security.QuerySecurityPackageInfo(pkg_name) auth = PasswordAuthentication('workgroup', 'developer', 'password', compatibility=4) ntlm_context = NtlmContext(auth, session_security='none') self.context = ntlm_context.initialize_security_context() _BaseAuth.__init__(self)
def handle_401(self, response, **kwargs): self.context = NtlmContext(self.password_authenticator, session_security='encrypt') credssp_processor = self._credssp_processor(self.context) next(credssp_processor) while response.status_code == 401: # This is required response.content response.raw.release_conn() client_request = credssp_processor.send(response) response = response.connection.send(client_request, **kwargs) return response
def _credssp_processor(self): """ Implements a state machine :return: """ response = (yield) context = self._get_credssp_header(response) if context is None: raise Exception('The remote host did not respond with a \'www-authenticate\' header containing ' '\'CredSSP\' as an available authentication mechanism') # 1. First, secure the channel with a RC4-SHA TLS Handshake if not context: tls_credssp = SSL.Connection(self.tls_credssp_context) tls_credssp.set_connect_state() while True: try: tls_credssp.do_handshake() except SSL.WantReadError: response = yield self._set_credssp_header(response.request, tls_credssp.bio_read(4096)) context = self._get_credssp_header(response) if context is None or not context: raise Exception('The remote host rejected the CredSSP TLS handshake') tls_credssp.bio_write(context) else: break # add logging to display the negotiated cipher (move to a function) openssl_lib = _util.binding.lib ffi = _util.binding.ffi cipher = openssl_lib.SSL_get_current_cipher(tls_credssp._ssl) cipher_name = ffi.string( openssl_lib.SSL_CIPHER_get_name(cipher)) # print cipher_name # 2. Send an TSRequest containing an NTLM Negotiate Request context = NtlmContext(PasswordAuthentication(self.domain, self.username, self.password), session_security='encrypt') context_generator = context.initialize_security_context() negotiate_token = context_generator.send(None) ts_request = TSRequest() ts_request['negoTokens'] = negotiate_token tls_credssp.send(ts_request.getData()) http_challenge_response = yield self._set_credssp_header(response.request, tls_credssp.bio_read(4096)) # Extract and decrypt the encoded TSRequest response struct from the Negotiate header authenticate_header = self._get_credssp_header(http_challenge_response) if not authenticate_header or authenticate_header is None: raise Exception("The remote host rejected the CredSSP negotiation token") tls_credssp.bio_write(authenticate_header) # NTLM Challenge Response and Server Public Key Validation ts_request = TSRequest() ts_request.fromString(tls_credssp.recv(8192)) challenge_token = ts_request['negoTokens'] server_cert = tls_credssp.get_peer_certificate() # not using channel bindings #certificate_digest = base64.b16decode(server_cert.digest('SHA256').replace(':', '')) ## channel_binding_structure = gss_channel_bindings_struct() ## channel_binding_structure['application_data'] = "tls-server-end-point:" + certificate_digest public_key = HttpCredSSPAuth._get_rsa_public_key(server_cert) # The _RSAPublicKey must be 'wrapped' using the negotiated GSSAPI mechanism and send to the server along with # the final SPNEGO token. This step of the CredSSP protocol is designed to thwart 'man-in-the-middle' attacks # Build and encrypt the response to the server ts_request = TSRequest() ts_request['negoTokens'] = context_generator.send(challenge_token) public_key_encrypted, signature = context.wrap_message(public_key) ts_request['pubKeyAuth'] = signature + public_key_encrypted tls_credssp.send(ts_request.getData()) enc_type3 = tls_credssp.bio_read(8192) http_auth_response = yield self._set_credssp_header(response.request, enc_type3) # TLS decrypt the response, then ASN decode and check the error code auth_response = self._get_credssp_header(http_auth_response) if not auth_response or auth_response is None: raise Exception("The remote host rejected the challenge response") tls_credssp.bio_write(auth_response) ts_request = TSRequest() ts_request.fromString(tls_credssp.recv(8192)) # TODO: Validate server cert? #a = ts_request['pubKeyAuth'] # print ":".join("{:02x}".format(ord(c)) for c in a) # 4. Send the Credentials to be delegated, these are encrypted with both NTLM v2 and then by TLS tsp = TSPasswordCreds() tsp['domain'] = self.domain tsp['username'] = self.username tsp['password'] = self.password tsc = TSCredentials() tsc['type'] = 1 tsc['credentials'] = tsp.getData() ts_request = TSRequest() ts_request['authInfo'] = context.wrap_message(tsc.getData()) tls_credssp.send(ts_request.getData()) final = tls_credssp.bio_read(8192) http_response = yield self._set_credssp_header(response.request, final) if http_response.status_code == 401: raise Exception('Authentication Failed')