def _fix_tshark_widechar_issue(layer) -> (str, str): if hasattr(layer, "authorization") and layer.authorization.startswith("NTLM "): # HTTP header dirty fix ntlm_bytes = base64.b64decode(layer.authorization[5:]) username_offset = int(layer.ntlmssp_string_offset.all_fields[1].show) domain_offset = int(layer.ntlmssp_string_offset.all_fields[0].show) username_length = int(layer.ntlmssp_string_length.all_fields[1].show) domain_length = int(layer.ntlmssp_string_length.all_fields[0].show) username = ntlm_bytes[username_offset:username_offset + username_length].replace(b"\x00", b"").decode() domain = ntlm_bytes[domain_offset:domain_offset + domain_length].replace(b"\x00", b"").decode() return username, domain else: # Not able to find a fix logger.error("The username or domain are only 1 character long, probably because of wide characters, " "investigate manually.") return "UNKNOWN", "UNKNOWN"
def process_pcap(filename: str, must_inspect_strings=False, tshark_filter=None, debug=False, decode_as=None) -> SessionList: global _sessions logger.DEBUG_MODE = debug _sessions = SessionList() pcap = pyshark.FileCapture(filename, display_filter=tshark_filter, decode_as=decode_as) logger.info("Processing packets in '{}'".format(filename)) if debug: pcap.set_debug() start_time = time.time() for packet in pcap: try: _process_packet(packet, must_inspect_strings) except MalformedPacketException as e: logger.error(str(e) + ", extractor will keep going") except Exception: traceback.print_exc() logger.error( "An exception occurred but extractor will keep going.") _sessions.process_sessions_remaining_content() logger.info("Processed in {0:.3f} seconds.".format(time.time() - start_time)) pcap.close() return _sessions
def active_processing(interface: str, must_inspect_strings=False, tshark_filter=None, debug=False, decode_as=None, pcap_output=None): global _sessions logger.DEBUG_MODE = debug _sessions = SessionList() _sessions.manage_outdated_sessions() signal.signal(signal.SIGINT, signal_handler) live = pyshark.LiveCapture(interface=interface, bpf_filter=tshark_filter, decode_as=decode_as, output_file=pcap_output) logger.info("Listening on {}...".format(interface)) if debug: live.set_debug() try: for packet in live.sniff_continuously(): try: _process_packet(packet, must_inspect_strings) except MalformedPacketException as e: logger.error(str(e) + ", extractor will keep going") except Exception: traceback.print_exc() logger.error( "An exception occurred but extractor will keep going.") except TSharkCrashException: logger.error("tshark crashed :( Please report the following error :") traceback.print_exc() signal_handler(None, None)
def analyse(session: Session, layer: Layer) -> bool: current_creds = session.credentials_being_built if hasattr(layer, "request_uri"): extension = layer.request_uri.split(".")[-1] if extension in HTTP_IGNORED_EXTENSIONS: return False if hasattr(layer, "request_full_uri") and layer.request_full_uri.startswith( "http://ocsp."): # Ignore Certificate Status Protocol return False 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) # We return false to prevent the manager from validating the credentials being built return False # 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) # We return false to prevent the manager from validating the credentials being built return False 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)) return True return False
manager.active_processing(args.listen, must_inspect_strings=string_inspection, tshark_filter=ip_filter, debug=args.debug, decode_as=decode_map, pcap_output=args.listen_output) exit(0) for pcap in args.pcapfiles: try: manager.process_pcap(pcap, must_inspect_strings=string_inspection, tshark_filter=ip_filter, debug=args.debug, decode_as=decode_map) except Exception as e: error_str = str(e) if error_str.startswith("[Errno"): # Clean error message errno_end_index = error_str.find("]") + 2 error_str = error_str[errno_end_index:] logger.error(error_str) else: traceback.print_exc() if logger.OUTPUT_FILE: logger.OUTPUT_FILE.close()