Пример #1
0
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()
Пример #2
0
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
Пример #3
0
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()
Пример #4
0
def _process_packet(session: Session, packet: Packet,
                    must_inspect_strings: bool):
    """
    Processes a single packet within its context thanks to the `Session` instance.

    Parameters
    ----------
    session : Session
        The session the packet belongs to.

    packet : Packet
        To packet to be analysed.

    must_inspect_strings : bool
        Whether strings in the packet should be inspected or not. Can be pretty heavy on the CPU.
    """

    if len(packet.layers
           ) > 3:  # == tshark parsed something else than ETH, IP, TCP

        for layer in packet.layers[3:]:
            layer_name = layer.layer_name

            if hasattr(layer, "_ws_malformed_expert"):
                raise MalformedPacketException(
                    "[{}] session contains malformed packet in layer '{}'".
                    format(session, layer_name))

            # Not based on layer name, can be found in different layers
            if hasattr(layer, "nt_status") or (
                    hasattr(layer, "ntlmssp_identifier")
                    and layer.ntlmssp_identifier == "NTLMSSP"):
                session.protocol = layer_name.upper()
                ntlmssp.analyse(session, layer)

            # Analyse the layer with the appropriate parser
            if layer_name in parsers:
                session.protocol = layer_name.upper()
                parsers[layer_name].analyse(session, layer)

    if must_inspect_strings:
        strings = utils.extract_strings_splitted_on_end_of_line_from(packet)
        emails_found = extract.extract_emails(strings)
        credit_cards_found = extract.extract_credit_cards(strings)

        for email in emails_found:
            logger.info(session, "Found email address: " + email)

        for credit_card in credit_cards_found:
            logger.info(
                session,
                "Credit card '{}' found: '{}'".format(credit_card.name,
                                                      credit_card.number))
Пример #5
0
 def test_malformed(self):
     from credslayer.core import manager
     pcap = FileCapture("samples/smb-crash.pcap")
     self.assertRaises(manager.MalformedPacketException,
                       manager._process_packet, Session(pcap[8]), pcap[8],
                       False)
     pcap.close()
Пример #6
0
def analyse(session: Session, layer: Layer):

    current_creds = session.credentials_being_built

    if hasattr(layer, "name"):
        current_creds.username = layer.name

    if hasattr(layer, "simple"):
        current_creds.password = layer.simple
        session["auth_process"] = True

    if session["auth_process"] and hasattr(layer, "resultcode"):
        result_code = int(layer.resultcode)
        session["auth_process"] = False

        if result_code == 0:
            logger.found(
                session,
                "credentials found: {} -- {}".format(current_creds.username,
                                                     current_creds.password))
            session.validate_credentials()
Пример #7
0
def analyse(session: Session, layer: Layer):

    current_creds = session.credentials_being_built

    if hasattr(layer, "server_greeting"):

        if hasattr(layer, "version"):
            logger.info(session, "MySQL version: " + layer.version)

        if hasattr(layer, "salt"):
            current_creds.context["salt"] = layer.salt

        if hasattr(layer, "salt2"):
            current_creds.context["salt2"] = layer.salt2

    if hasattr(layer, "client_auth_plugin"):
        logger.info(session, "MySQL auth plugin: " + layer.client_auth_plugin)

    if hasattr(layer, "user"):
        current_creds.username = layer.user
        current_creds.hash = "".join(layer.passwd.split(":"))

    if hasattr(layer, "response_code") or hasattr(layer, "query"):

        # Yes this try except is ugly, but there's a bug before tshark 3.0 which prevents us to use response_code
        # See https://www.wireshark.org/docs/dfref/i/imap.html
        try:
            response_code = int(layer.response_code, 16)
            auth_successful = response_code == 0
        except AttributeError:
            auth_successful = hasattr(layer, "query")

        if current_creds.username and auth_successful:

            for item in current_creds.context:
                logger.found(session, "{} found: {}".format(item, current_creds.context[item]))

            logger.found(session, "credentials found: {} -- {}".format(current_creds.username, current_creds.hash))
            session.validate_credentials()
Пример #8
0
def analyse(session: Session, layer: Layer):

    current_creds = session.credentials_being_built

    if hasattr(layer, "req_command"):
        command = layer.req_command

        if hasattr(layer, "req_parameter"):
            parameter = layer.req_parameter

            if command == "AUTH":
                # TODO : handle more types of auth
                if parameter.startswith("LOGIN"):
                    session["auth_process_login"] = True
                elif parameter.startswith("PLAIN"):  # TODO: not tested, find a pcap
                    session["auth_process_plain"] = True

    if session["auth_process_login"]:
        if hasattr(layer, "auth_username"):
            username = layer.auth_username
            current_creds.username = b64decode(username).decode()

        elif hasattr(layer, "auth_password"):
            password = layer.auth_password
            current_creds.password = b64decode(password).decode()
            session["auth_process_login"] = False

    elif session["auth_process_plain"]:
        if hasattr(layer, "auth_username"):
            b64_auth = layer.auth_username
            current_creds.username, current_creds.password = utils.parse_sasl_creds(b64_auth, "PLAIN")
            session["auth_process_plain"] = False

    if hasattr(layer, "response_code"):
        response_code = int(layer.response_code)

        if response_code == 235:
            logger.found(session, "credentials found: {} -- {}".format(current_creds.username, current_creds.password))
            session.validate_credentials()
Пример #9
0
def analyse(session: Session, layer: Layer):

    current_creds = session.credentials_being_built

    if hasattr(layer, "version"):
        session.protocol = "SNMPv" + str(int(layer.version) + 1)
    elif hasattr(layer, "msgversion"):
        session.protocol = "SNMPv" + layer.msgversion
    else:
        session.protocol = "SNMPv?"

    if hasattr(layer, "community") \
            and (session["community_string"] is None or session["community_string"] != layer.community):
        current_creds.password = session["community_string"] = layer.community
        logger.found(session, "community string found: " + layer.community)
        session.validate_credentials()

    elif hasattr(layer, "msgusername") and layer.msgusername != "msgUserName: "******"username"] is None or session["username"] != layer.msgusername):
        current_creds.username = session["username"] = layer.msgusername
        logger.found(session, "username found: " + layer.msgusername)
        session.validate_credentials()
Пример #10
0
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"] = ""
Пример #11
0
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()
Пример #12
0
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()
Пример #13
0
def analyse(session: Session, layer: Layer):

    current_creds = session.credentials_being_built

    if hasattr(layer, "authtype"):
        # values signification can be found here https://www.postgresql.org/docs/8.2/protocol-message-formats.html
        auth_type = int(layer.authtype)

        if auth_type == 5:
            current_creds.context["auth_type"] = "md5"

        elif auth_type == 4:
            current_creds.context["auth_type"] = "crypt"

        elif auth_type == 3:
            current_creds.context["auth_type"] = "cleartext"

        elif auth_type == 10:
            current_creds.context["auth_type"] = "sasl"

        elif auth_type == 0 and current_creds.username:
            if current_creds.hash:
                logger.found(
                    session,
                    "credentials found ! Username: {} | Hash: {} | Salt: {}".
                    format(current_creds.username, current_creds.hash,
                           current_creds.context["salt"]))
            elif current_creds.password:
                logger.found(
                    session,
                    "credentials found ! Username: {} | Password: {}".format(
                        current_creds.username, current_creds.password))
            else:
                logger.found(
                    session,
                    "it seems that '{}' authenticated without password".format(
                        current_creds.username))

            if "database" in current_creds.context:
                logger.info("Targeting database '{}'".format(
                    current_creds.context["database"]))

            session.validate_credentials()
            return

    if hasattr(layer, "parameter_name"):

        # Sometimes tshark returns multiple fields with the same name
        parameter_names = layer.parameter_name.all_fields
        parameter_values = layer.parameter_value.all_fields

        for i in range(len(parameter_names)):

            parameter_name = parameter_names[i].show
            parameter_value = parameter_values[i].show

            if parameter_name == "user":
                current_creds.username = parameter_value

            elif parameter_name == "database":
                current_creds.context["database"] = parameter_value

            elif parameter_name == "server_version":
                logger.info(session, "PostgreSQL version: " + parameter_value)

    if hasattr(layer, "salt"):
        current_creds.context["salt"] = layer.salt.replace(":", "")

    elif hasattr(layer, "password"):

        if "auth_type" in current_creds.context and current_creds.context[
                "auth_type"] != "cleartext":
            current_creds.hash = layer.password
            auth_type = current_creds.context["auth_type"]

            # Remove the hash type from the hash string
            if current_creds.hash.startswith(auth_type):
                current_creds.hash = current_creds.hash[len(auth_type):]

        else:
            current_creds.password = layer.password