As organizations continue to shift to cloud-based or entirely cloud-native environments, incident responders now have the challenging task of researching and deciphering how each SaaS vendor can be both attacked and investigated. In this series, Mitiga incident responders share knowledge we’ve gained from our investigations and threat hunting to provide insight into the key log fields to use when investigating SaaS compromises.
For part one of this series, we will focus on Okta System Logs. The Okta System Log “records system events that are related to your organization in order to provide an audit trail that can be used to understand platform activity and to diagnose problems.1" While Okta System Logs give incident responders an opportunity for both forensic investigation and detection, there are various pitfalls and issues that they might also encounter. This blog will highlight those challenges, offer strategies to overcome them, and pseudocode to help you track sessions in Okta effectively. You can implement the pseudocode provided as an investigation function or use it as a query during an investigation. For part two on Okta threat hunting, here here.
Okta System Log Key Fields
The table below provides a list of important fields for tracking sessions, hunting, and investigating in Okta. As with many SaaS vendors, logs can change, new research may be conducted, and investigative techniques must adapt accordingly. Make sure to check back periodically for updates to this table and feel free to reach out to us if we can improve its content.
While most of these fields are accurate and perform as expected, we have found that the debugContext.debugData.risk and debugContext.debugData.deviceFingerprint fields have inaccuracies and limitations that investigators and detection engineers should be aware of. Even if you are familiar with Okta logs, we recommend reviewing the notes on these two specific fields to understand the highlighted challenges.
| Field | Description | Sample Value |
|---|---|---|
| published | Action timestamp | 2024-01-10T07:32:48.742Z |
| actor.alternateId | This reflects the actor's identity, often their email, dependent on the 'actor_type'. For 'User', it's the user's email; 'PublicClientAppEntity' defaults to 'unknown'; 'SystemPrincipal' is either 'supportuser@okta.com' or 'system@okta.com'; 'Event Hook' remains unset. 'PublicClientApp' links to 'actor.id'. |
0oae2szv32xaTYRst2p7 suspect_user@acme.com unknown supportuser@okta.com system@okta.com |
| actor.id | This reflects the actor's identity, identified by an Okta-specific identifier. | 0oae2XXXXXXXXXXst2p7 |
| actor.type | Okta actor type. |
PublicClientApp User PublicClientAppEntity SystemPrincipal Event Hook |
| client.device | Client device type. |
unknown Unknown Computer Mobile Tablet |
| client.ipAddress | Client request IP address: either IPv4 or IPv6 format. | 127.0.0.1 |
| client.userAgent.rawUserAgent | User agent of the web request used by the actor to perform an action. |
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36 Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 |
| client.userAgent.browser | Browser family identified by Okta from the user agent. |
FIREFOX CHROME unknown |
| client.zone | Client zone name, based on client.ipAddress subnet range. This is organization specific as defined by organizations admins. |
null <Custom Zone name> |
| client.geographicalContext.city | City determined by Okta based on client.ipAddress. |
Charlestown Kingston New York |
| client.geographicalContext.country | Country determined by Okta based on client.ipAddress. |
United States India Czechia |
| eventType | Event type published, as detailed in Okta's documentation: Okta Event Types.2 | system.email.mfa_reset_notification.sent_message |
| displayMessage | Event display message: A human-readable description of the eventType. | Send user MFA enrollment notification email |
| target.type | Refers to the zero or more types that the action targets. | ["AuthenticatorMethod","AuthenticatorMethod","AppInstance"] |
| target.displayName | Target.type refers to the zero or more types that the action targets. Target.type and Target.DisplayName values are ordered. Think of Target.type as the key and Target.DisplayName as the corresponding values. | ["Password","Okta Verify","Okta Dashboard"] |
| outcome.result | The result of the eventType. |
SUCCESS ALLOW CHALLENGE FAILURE null DENY |
| outcome.reason | Reason for the result. Null if it was successful, otherwise it is populated with reason. |
Sign-on policy evaluation resulted in AUTHENTICATED login_required INVALID_CREDENTIALS delivered VERIFICATION_ERROR LOCKED_OUT no_matching_policy |
| transaction.id | The ID of a series of actions, authenticated or not, that identifies events occurring together, such as a request to Okta's servers. The value will be identical to debugContext.debugData.requestId or debugContext.debugData.emailRequestId. |
f938cb7b727fe8XXXXXXXXXXXXXXXXXX 16a39fde26f5f6XXXXXXXXXXXXXXXXXX 3513cb19071ddcXXXXXXXXXXXXXXXXXX |
| securityContext.asOrg | The organization, ASN, associated with the client's IP address from which the eventType was initiated. |
cox communications amazon technologies inc. t-mobile |
| authenticationContext.externalSessionId | This ID is set following successful authentication and is unique per user session. Useful for correlating events that occurred within the same user session. |
102XXXXXXXX trsXXXXXXXX idxXXXXXXXX |
| debugContext | The debugContext field provides additional information for certain types of events where the default fields are insufficient to adequately describe the operations performed by the event. It contains valuable sub-fields, some of which have been documented in this sheet. The size and content of debugContext depend on the event type. | { debugData: { behaviors: "{New Geo-Location=NEGATIVE, New Device=BAD_REQUEST, New IP=NEGATIVE, New State=NEGATIVE, New Country=NEGATIVE, Velocity=NEGATIVE, New City=NEGATIVE}", requestId: "3513cb19071ddcXXXXXXXXXXXXXXXXXX", dtHash: "1b9cdd35a8d4f0708072ae6957324c9adf8XXXXXXXXXXXXXXXXXX", risk: "{reasons=Anomalous Device, level=HIGH}", requestUri: "/api/v1/authn", threatSuspected: "false", url: "/api/v1/authn?" } } |
| debugContext.debugData.risk | Okta performs a risk assessment for actions performed and assigns the risk level to this field. For instance, the risk level for a sign-in event might be determined by factors such as anomalous location, anomalous device, suspected threats based on Okta ThreatInsight detection, or missing cookies. While this field provides valuable information, it should be interpreted with caution. At the time of writing historical examination revealed issues, such as the error-prone nature of anomalous device detection due to limitations in device fingerprinting. Additionally, there may be bugs affecting anomalous location detection, where an IP address may appear to be from a new country despite being associated with a known city. |
{reasons=Anomalous Location, Anomalous Device, level=HIGH} null {level=LOW} |
| debugContext.debugData.behaviours | This field provides insight into the risk assessment performed by Okta, which is recorded as boolean assignments (True or False). |
{New Geo-Location=UNKNOWN, New Device=UNKNOWN, New IP=UNKNOWN, New State=UNKNOWN, New Country=UNKNOWN, Velocity=UNKNOWN, New City=UNKNOWN} {New Geo-Location=NEGATIVE, New Device=NEGATIVE, New IP=NEGATIVE, New State=NEGATIVE, New Country=NEGATIVE, Velocity=NEGATIVE, New City=NEGATIVE} |
| debugContext.debugData.factor | Authentication factor used for the action. This field is only set for "user.authentication.auth_via_mfa" events. |
SECURITY_QUESTION OKTA_VERIFY_PUSH FIDO_WEBAUTHN PASSWORD_AS_FACTOR SMS_FACTOR OKTA_SOFT_TOKEN SIGNED_NONCE |
| debugContext.debugData.factorIntent | The initial actor intent that triggered the factor. This field is present for "user.authentication.verify" and "user.authentication.auth_via_mfa" events. |
AUTHENTICATION CREDENTIAL_ENROLLMENT CREDENTIAL_MODIFY ENROLLMENT LOGIN RECOVERY UNLOCK_ACCOUNT |
| debugContext.debugData.requestId | The ID of a request, which identifies events occurring together as part of an operation (e.g., a request to Okta's servers). The value will be identical to transaction.id or debugContext.debugData.emailRequestId. It's recommended to use transaction.id. |
f938cb7b727fe8XXXXXXXXXXXXXXXXXX 16a39fde26f5f6XXXXXXXXXXXXXXXXXX 3513cb19071ddcXXXXXXXXXXXXXXXXXX |
| debugContext.debugData.emailRequestId | If an action results in a "system.email.delivery" event, the transaction.id value of this event is recorded in this field. The value will be identical to transaction.id or debugContext.debugData.requestId. |
f938cb7b727fe8XXXXXXXXXXXXXXXXXX 16a39fde26f5f6XXXXXXXXXXXXXXXXXX 3513cb19071ddcXXXXXXXXXXXXXXXXXX |
| debugContext.debugData.authnRequestId | Unique authentication request ID. The value may or may not be identical to transaction.id, debugContext.debugData.requestId, or debugContext.debugData.emailRequestId. |
f938cb7b727fe8XXXXXXXXXXXXXXXXXX 16a39fde26f5f6XXXXXXXXXXXXXXXXXX 3513cb19071ddcXXXXXXXXXXXXXXXXXX |
| debugContext.debugData.dtHash | Based on available documentation, this field appears to represent the device token hash. While the exact calculation method is unclear, it seems to be a SHA256 hash. Overlap across multiple user accounts is possible. This field serves as a good indicator when targeting a single account to identify potential theft of session tokens. |
9def5cf1c6bbb852021970f8a60cd176810XXXXXXXXXXXXXXXXXX a57f0562fbf22edf89a6028abfcfb688a0fXXXXXXXXXXXXXXXXXX 1b9cdd35a8d4f0708072ae6957324c9adf8XXXXXXXXXXXXXXXXXX |
| debugContext.debugData.deviceFingerprint | This field is intended to represent a unique device ID. However, significant overlap is observed, and there is no clear pattern regarding its calculation. Documentation lacks clarity on the calculation method, suggesting that different tools may set it differently. It could be based solely on the user agent or utilize other browser-based fingerprinting techniques, such as cookies, device information, and IPs. When used for investigation, it's important to note the common overlaps in this field. While it might appear that multiple users are using the same device, caution is advised. It's recommended to combine this information with other indicators to track malicious activity. |
a9e2d1bbb4b46dd0a33b801c5f0a3c38 c74eee4d09815fa3a9d42c97a23d71e2 4beb8a4ca5af2388fc0e1ebdaeb11f46 |
| debugContext.debugData.deviceCategory | This field is set for system.push.send_factor_verify_push events. It specifies the device type where the MFA response was received/responded to. |
SmartPhone_Android SmartPhone_IPhone |
Session Tracking
In the event of a compromise to an Okta account, it's recommended to use the fields to track all actions performed by the threat actor in a session, covering both authenticated and pre-authentication stages, as well as actions initiated by the Okta system itself.
- authenticationContext.externalSessionId
- transaction.id
- debugContext.debugData.emailRequestId
- debugContext.debugData.authnRequestId
To ensure a thorough investigation, it's also advised to identify all unique identifiers within these fields associated with confirmed malicious events and use them as pivot points for further analysis. It's important to recognize that transaction.id and debugContext.debugData.emailRequestId will always share identical values, whereas the debugContext.debugData.authnRequestId might only occasionally match.
Upon identifying any specific values assigned to these fields, we recommend employing the following filter logic for isolating malicious activity:
- Match malicious authenticationContext.externalSessionId values with authenticationContext.externalSessionId.
- OR
- Match malicious values of transaction.id, debugContext.debugData.emailRequestId, and debugContext.debugData.authnRequestId to transaction.id, debugContext.debugData.emailRequestId, or debugContext.debugData.authnRequestId
Example pseudo code:
Those who are fortunate may not be compromised and only need to review logs for detection engineering. However, during an investigation of a compromise, every piece of information is crucial in building a comprehensive picture. If there are issues with certain fields that you are unaware of, it can significantly sidetrack the investigation and impact the severity assessment of the incident.
We aim to continuously update this page as changes occur, providing the security community with thorough reference materials and insights necessary for confident investigations. We plan to cover other vendors and log sources in the upcoming months, ensuring you have the documentation needed to respond to threats effectively.
