def analyse(session: Session, layer: Layer): current_creds = session.credentials_being_built if hasattr(layer, "request_command"): command = layer.request_command if hasattr(layer, "request_parameter"): parameter = layer.request_parameter if command == "AUTH": # TODO : handle more types of auth if parameter == "PLAIN": session["auth_process_plain"] = True elif session["auth_process_plain"]: session["auth_process_plain"] = False current_creds.username, current_creds.password = utils.parse_sasl_creds( command, "PLAIN") if current_creds.username and hasattr(layer, "response_indicator"): indicator = layer.response_indicator if indicator == "+OK": logger.found( session, "credentials found: {} -- {}".format(current_creds.username, current_creds.password)) session.validate_credentials() elif indicator == "-ERR": session.invalidate_credentials_and_clear_session()
def analyse(session: Session, layer: Layer): current_creds = session.credentials_being_built if hasattr(layer, "response_code"): code = int(layer.response_code) if code == 230 and current_creds.username: logger.found( session, "credentials found: {} -- {}".format(current_creds.username, current_creds.password)) session.validate_credentials() elif code == 430: session.invalidate_credentials_and_clear_session() elif hasattr(layer, "request_command"): command = layer.request_command if command == "USER": current_creds.username = layer.request_arg elif command == "PASS": current_creds.password = layer.request_arg
def analyse(session: Session, layer: Layer): current_creds = session.credentials_being_built if hasattr(layer, "request_command"): command = layer.request_command if command == "LOGIN": tokens = layer.request.split('"') current_creds.username = tokens[1] current_creds.password = tokens[3] # Due to an incompatibility with "old" tshark versions, we cannot use response_command :( elif hasattr(layer, "response"): command = layer.response if " LOGIN " in command: status = layer.response_status if status == "OK": logger.found( session, "credentials found: {} -- {}".format( current_creds.username, current_creds.password)) session.validate_credentials() elif status == "NO" or status == "BAD": session.invalidate_credentials_and_clear_session()
def analyse(session: Session, layer: Layer): if not hasattr(layer, "data"): return current_creds = session.credentials_being_built # Sometimes tshark returns multiple Data fields data_fields = layer.data.all_fields for data in data_fields: if session["data_being_built"] is None: session["data_being_built"] = "" session["user_being_built"] = session["pass_being_built"] = False try: data = data.binary_value.decode() except UnicodeDecodeError: continue lowered_data = data.lower().strip() for username_ask in POTENTIAL_USERNAME_ASK: if lowered_data.endswith(username_ask): session["user_being_built"] = True break else: # Yes for loops have elses ;) if lowered_data.endswith("password:"******"pass_being_built"] = True elif current_creds.password: for auth_success_msg in POTENTIAL_AUTH_SUCCESS: if auth_success_msg in lowered_data: logger.found( session, "credentials found: {} -- {}".format( current_creds.username, current_creds.password)) session.validate_credentials() return for auth_error_msg in POTENTIAL_AUTH_ERROR: if auth_error_msg in lowered_data: session.invalidate_credentials_and_clear_session() else: session["data_being_built"] += data if "\r" in session["data_being_built"] or "\n" in session[ "data_being_built"]: data_being_built = session["data_being_built"].replace("\r", "")\ .replace("\n", "")\ .replace("\x00", "") if session["user_being_built"]: username = data_being_built if _is_username_duplicated(username): username = "".join([ username[i] for i in range(0, len(username), 2) ]) current_creds.username = username session["user_being_built"] = False elif session["pass_being_built"]: current_creds.password = data_being_built session["pass_being_built"] = False session["data_being_built"] = ""
def analyse(session: Session, layer: Layer): current_creds = session.credentials_being_built if hasattr(layer, "request_uri"): extension = layer.request_uri.split(".")[-1] if extension in HTTP_IGNORED_EXTENSIONS: return # Ignore Certificate Status Protocol if hasattr(layer, "request_full_uri" ) and layer.request_full_uri.startswith("http://ocsp."): return if hasattr(layer, "authorization"): tokens = layer.authorization.split(" ") if len(tokens) == 2 and tokens[0] == "Basic": try: credentials = base64.b64decode(tokens[1]).decode() colon_index = credentials.find(":") current_creds.username = credentials[:colon_index] current_creds.password = credentials[colon_index + 1:] session[ "authorization_header_uri"] = layer.request_full_uri except UnicodeDecodeError: logger.error("HTTP Basic auth failed: " + tokens) elif len(tokens) == 2 and tokens[0] == "NTLM": pass # Already handled by the NTLMSSP module else: logger.info( session, "Authorization header found: '{}'".format( layer.authorization)) # POST parameters if hasattr(layer, "file_data"): post_content = layer.file_data if len(post_content) <= HTTP_AUTH_MAX_LOGIN_POST_LENGTH: logger.info(session, "POST data found: '{}'".format(post_content)) post_parameters = parse_qs(post_content) # We don't want to interfere with the Authorization header potentially being built credentials = Credentials() credentials.context["Method"] = "POST" credentials.context["URL"] = layer.request_full_uri logger.info(session, "context: " + str(credentials.context)) for parameter in post_parameters: if parameter in HTTP_AUTH_POTENTIAL_USERNAMES: credentials.username = post_parameters[parameter][0] elif parameter in HTTP_AUTH_POTENTIAL_PASSWORDS: credentials.password = post_parameters[parameter][0] if credentials.username: logger.found( session, "credentials found: {} -- {}".format( credentials.username, credentials.password)) session.credentials_list.append( credentials) # Don't validate those credentials return # GET parameters elif hasattr(layer, "request_uri_query"): get_parameters = parse_qs(layer.request_uri_query) # We don't want to interfere with the Authorization header potentially being built credentials = Credentials() credentials.context["Method"] = "GET" credentials.context["URL"] = layer.request_full_uri for parameter in get_parameters: if parameter in HTTP_AUTH_POTENTIAL_USERNAMES: credentials.username = get_parameters[parameter][0] elif parameter in HTTP_AUTH_POTENTIAL_PASSWORDS: credentials.password = get_parameters[parameter][0] if credentials.username: logger.found( session, "credentials found: {} -- {}".format( credentials.username, credentials.password)) logger.info(session, "context: " + str(credentials.context)) session.credentials_list.append( credentials) # Don't validate those credentials return elif hasattr(layer, "response_for_uri"): if session["authorization_header_uri"] == layer.response_for_uri: # If auth failed + prevent duplicates if layer.response_code == "401" or current_creds in session.credentials_list: session.invalidate_credentials_and_clear_session() else: logger.found( session, "basic auth credentials found: {} -- {}".format( current_creds.username, current_creds.password)) session.validate_credentials()
def analyse(session: Session, layer: Layer): current_creds = session.credentials_being_built if current_creds and hasattr(layer, "nt_status"): status = int(layer.nt_status) if status == 0: # LOGON SUCCESS logger.found( session, "{} found: {}".format(current_creds.context["version"], current_creds.hash)) session.validate_credentials() elif status == 3221225581: # LOGON FAILED session.invalidate_credentials_and_clear_session() if hasattr(layer, "ntlmssp_messagetype"): message_type = int(layer.ntlmssp_messagetype, 16) if message_type == 2: # Challenge session["challenge"] = layer.ntlmssp_ntlmserverchallenge.replace( ":", "") elif message_type == 3: # Auth username = layer.ntlmssp_auth_username domain = layer.ntlmssp_auth_domain challenge = session["challenge"] if len(username) == 1 or len(domain) == 1: username, domain = _fix_tshark_widechar_issue(layer) if not challenge: challenge = "CHALLENGE_NOT_FOUND" if domain == "NULL": domain = "" if hasattr(layer, "ntlmssp_ntlmv2_response"): current_creds.context["version"] = "NETNTLMv2" proof = layer.ntlmssp_ntlmv2_response_ntproofstr auth_ntresponse = layer.ntlmssp_ntlmv2_response[len(proof) + 1:] proof = proof.replace(":", "") auth_ntresponse = auth_ntresponse.replace(":", "") current_creds.hash = "{}::{}:{}:{}:{}".format( username, domain, session["challenge"], proof, auth_ntresponse) elif hasattr(layer, "ntlmssp_ntlmclientchallenge"): current_creds.context["version"] = "NETNTLMv1" auth_ntresponse = layer.ntlmssp_auth_ntresponse.replace( ":", "") client_challenge = layer.ntlmssp_ntlmclientchallenge.replace( ":", "").ljust(48, "0") current_creds.hash = "{}::{}:{}:{}:{}".format( username, domain, client_challenge, auth_ntresponse, challenge) else: # Unsupported NTLM format, investigate ? Found a pcap w/o ntlm client challenge field session.invalidate_credentials_and_clear_session()