Skip to content

Identity

Introduction

The IdentityMgr class of the identity module allows you to interact with the Recorded Future Identity module to view the latest identity exposures and credential leaks happening in the domains you are monitoring.

See the API Reference for internal details of the module.

Notes

To use this module, you must:

  • Have a token with permissions for the Identity module.
  • Ensure the Identity module is configured in your organization.

Additionally, if your organization allows it, you may be able to view passwords in clear text.

Examples

Warning

The following examples demonstrate how to use this module. Be sure to add appropriate error handling as needed; all possible errors for each method or function are listed in the API Reference page.

Additionally, you must configure the RF_TOKEN environment variable before getting started. For instructions, see Learn.

1: Retrieve details of recently exposed accounts and indicate if the password is in clear text

Tip

To run this example, you will need to change the domain queried by search_credentials to one of the domains configured in your Recorded Future enterprise.

In this example, we search for all workforce accounts within our organization, specifically monitoring the domain norsegods.online. The search_credentials function is used to find the latest exposed credentials, with the Email argument filtering for only those credentials associated with internal accounts.

If any credentials are found, we use the lookup_credentials method with subjects_login set to the results from search_credentials. This approach conveniently combines both steps to retrieve detailed information for each exposed identity.

Next, we extract the required data from the payload. Since an identity may have multiple leaked credentials, we iterate through each one to gather the relevant information.

Finally, all values are added to a table for clearer presentation.

To run this example you will first need to add the rich package to your virtual environment:

pip install rich
from psengine.identity import IdentityMgr
from rich.console import Console
from rich.table import Table

console = Console()
table = Table(title='Discovered Credentials')

table.add_column('Subject')
table.add_column('Password Properties')
table.add_column('Is Password Clear', justify='center')

mgr = IdentityMgr()
credentials = mgr.search_credentials(
    'norsegods.online', 'Email'
)

if len(credentials):
    detailed_identities = mgr.lookup_credentials(
        subjects_login=credentials
    )

    for identity in detailed_identities:
        for cred in identity.credentials:
            properties = ', '.join(
                cred.exposed_secret.details.properties
            )
            is_clear = (
                'Yes'
                if cred.exposed_secret.effectively_clear
                else 'No'
            )

            table.add_row(
                cred.subject, properties, is_clear
            )

console.print(table)

After running the sample code, the output would look like this:

1
2
3
4
5
6
7
8
                                                   Discovered Credentials
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┓
┃ Subject                               ┃ Password Properties                                              ┃ Is Password Clear ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━┩
│ example@norsegods.online              │ Letter, Number, LowerCase, AtLeast10Characters                   │         Yes       │
│ example@norsegods.online              │ Letter, Number, LowerCase, AtLeast10Characters                   │         Yes       │
│ example2@norsegods.online             │ Letter, Number, LowerCase, AtLeast10Characters                   │         Yes       │
└───────────────────────────────────────┴──────────────────────────────────────────────────────────────────┴───────────────────┘

2: View the clear text password of an exposed user

Tip

To run this example you will need to change the email queried by lookup_credentials to one of the emails that has been compromised from the domains you are monitoring. Your token also needs access to the Identity Module.

In this example, we check whether the user +2@norsegods.online has a leaked clear text password, and if so, we print it. The main purpose is to demonstrate how to access and use the clear text password if it needs to be sent to another tool, such as Active Directory, Okta, etc..

The password saved in clear_text_value is not a plain string; if saved as is in a log file, for example with:

LOG.info(cred.exposed_secret.details)

the log will be saved with a line looking like:

properties=['Letter', 'Number', 'LowerCase', 'AtLeast8Characters'] rank=None clear_text_value=ClearTextPassword('exam********') clear_text_hint='ex'

We did this purposefully to avoid secrets being accidentally leaked again.

To view the clear text password you need to use the get_secret_value method of the clear_text_value object.

The clear text password can be seen only if your organization has been configured to see it.

from psengine.identity import IdentityMgr

mgr = IdentityMgr()

identities = mgr.lookup_credentials('+2@norsegods.online')
for identity in identities:
    for cred in identity.credentials:
        if (
            details := cred.exposed_secret.details
        ) and details.clear_text_value:
            print(
                details.clear_text_value.get_secret_value()
            )

3: Search for an exposed password without sending it

Tip

To run this example your token needs access to the Identity Module.

This example focuses on finding if a password has been likely exploited or not. We can use the lookup_password method to see:

  • if the beginning of the hash of a password has been compromised
  • if the full hash of the password has been compromised

We are going to use the hash_prefix in conjunction with the type of algorithm used to produce the hash to see if the credential has been exposed. This is an example of a one-off password lookup, but the same method accepts a list of tuples like:

1
2
3
4
passwords = [
    ('995bb852c775d6', 'ntlm'),
    ('8985b89acb97b011913c8b7f57e298d2', 'md5'),
]

The return value is always a list of PasswordLookup; we can safely index the first result to get the exposure_status.

1
2
3
4
5
6
7
8
from psengine.identity import IdentityMgr

identity_mgr = IdentityMgr()

password_lookup = identity_mgr.lookup_password(
    hash_prefix='8e9a96e', algorithm='sha256'
)
print(password_lookup[0].exposure_status)

Running this example should print Common, meaning this password hash prefix is a commonly used password.