In the ever-evolving world of cybersecurity, staying steps ahead of potential threats is paramount. With identity becoming a key for an organization’s security program, we increasingly rely on Identity providers (IdP) like Okta for identity and access management, and for federating access to cloud services, systems, and critical SaaS applications. Therefore, the logs produced by these systems become a critical source of information that can help you detect and eliminate threats before they wreak havoc.
This blog post is your compass across a wide range of available Okta logs. Whether you’re a seasoned security professional or just getting started in the field, this step-by-step guide will empower you to turn raw data into actionable insights. We’ll explore:
- Each Okta audit log, learning how to analyze and extract critical information from
- How to uncover hidden threats, analyze their patterns, and respond effectively. From detection of brute force and MFA fatigue attempts to impossible traveler and privilege escalation techniques
- A set of free tools the Rezonate team has provided you to collect, analyze, hunt, and detect identity threats faster and easier.
Understanding Okta Audit Logs
Okta’s System Log API records various system events related to an organization, providing an audit trail that can be used to understand platform activity and diagnose problems. The System Log API gives near real-time, read-only access, capturing a wide range of data types and the exact structure of each change. That being said, some data points are agnostic and appear in each log record.
Here is the log structure scheme, as defined in the Okta Documentation:
Every property in this log could be useful in certain use cases, but we highlighted some properties that you should focus on for most investigations and hunting scenarios:
UUID | Unique identifier for the event |
Published | Event time |
Event Type | Describe the type of the event, from a list of ~850 event types |
Actor | Describe the entity (user, app, client, etc.) that acts. It includes details like ID, type of actor, alternative ID (which is the user’s email address), and display name |
Client | Describes the client that issues the request that triggers an event. It provides contextual information about the user, such as HTTP user agent, geographical context, IP address, device type |
Target | Describes the entity that an actor acts on, such as an app user or a sign-in token. It also includes details like ID, type, alternative ID, and display name. Note that in some events, there could be more than one Target object, in these cases, it’s best to find the relevant target based on its type (AppInstance, AppUser, etc..) |
Authentication Context | Provides context about the credentials provider and authentication type of the connection. Includes the externalSessionId which is the Session ID of the operating user. |
Security Context | Include context regarding the IP Address of the client. Useful data points within this object are isp (Internet Provider that the request was sent from) and asOrg (the organization that is associated with the asn) |
Debug Context | Include detailed, per event, context with additional information such as device hash (DtHash) or ThreatSuspected |
Outcome | Include the result for the event (such as Login request), in the Result field and the reason for this result in the Reason field. |
Accessing Okta Audit Logs
Okta keeps the data accessible for customers with a retention of 90 days, and during this period there are primarily two ways to access it:
1. Okta Admin Console
Via the Okta Admin Console, Administrative roles, enabled for management of policies, users, groups, and “Audit Log” reports, can use the interface by clicking “System Log” in the reporting menu:
Alternatively, the web interface can be accessed directly through the following URL
(replace OKTA_DOMAIN with your unique okta domain name)
https://{OKTA_DOMAIN}-admin.okta.com/report/system_log_2
Through the web interface, we can apply different filters on the event time or any of its properties, and see the results, and several statistics, directly from the console.
For example, in the query below we can see all of the activity against one specific application in the tenant – In this case, it’s AWS Client VPN. You can also see the different actors that performed the operations involving this target application.
On top of the basic Search panel it is also possible to add combinations of filters for more specific criteria. In the example below, we are looking for all events performed by a specific user, against a specific application, which resulted in ALLOW. This can be achieved by clicking the “Advanced Filters”.
After applying filters, it’s possible to either examine the details of each event or to export the filtered logs to a CSV file (by clicking on the Download CSV button). Note that this feature is limited to 200,000 results, so for bigger exports, the Okta System Log API is preferred.
2. Okta Admin Console
The Okta System Log API is the programmatic counterpart of the System Log UI, and it offers the ability to execute more advanced queries and filters against the Okta logs. Operating through this interface requires either OAuth integration with the okta.logs.read scope or Read-only API Key.
Here is an example of an API call, selecting all events of a specific type (user.session.end):
GET /api/v1/logs?filter=eventType eq "user.session.end" HTTP/1.1
Host: {OKTA_DOMAIN}
Accept: application/json
Content-Type: application/json
Authorization: SSWS {{apikey}}
The most common use case of operating through the API Interface would be to export batch data in real-time to another system, such as streaming logs into a SIEM or any other security product, to monitor and conduct introspection and audit
One of the biggest advantages of exporting the data with the System Log API is to correlate the collected logs with other data sources, adding critical context and completeness of data making the advanced investigation a lot easier.
3. Exporting The Logs
As mentioned, there is more than one way to get your hands on the relevant Okta logs and perform your threat-hunting actions on them. Exporting through the Admin Console is easy, yet size-limited while exporting the data through the API could be more tricky for beginners. To get around this limit, we have created a basic tool that allows you to export Okta logs into a file, based on a time frame. It can be downloaded directly from the Rezonate github repository.
Let the Hunt Begin
After we have exported the logs through one of the methods, we can get to work and start analyzing the data to start identifying potential risks and threats. For the hunting process, you can use any data analytics solution or database based on your preferences, as long as it supports filtering and grouping of data.
In this section, we will guide you through some of the top-relevant threat scenarios to look out for, explaining them, marking the relevant Okta events, aligning to the specific MITRE ATT&CK technique, and including our own query in PostgreSQL query syntax.
Important to highlight that some of the hunting queries may have false positives, depending on the environment, and may need some adjustments to reduce noisy results.
Scenario 1 – Brute Force on an Okta User
A brute force attack on an Okta user involves an attacker repeatedly trying different passwords in an attempt to eventually guess correctly and gain unauthorized access. To hunt for any occurrence of this scenario, you can search for an actor that performed more than X failed login attempts on at least Y target user, failing or ending up with a successful login. In cases of failure, the activity may result in a user’s lockage, or Okta blocking the client IP. The same logic can be applied to two different types of events:
- user.session.start – Search for traditional Brute Force attack
- user.authentication.auth_via_richclient – Search for Brute Force attack that uses legacy authentication protocols. Legacy authentication does not support MFA and is thus being used to guess passwords on a large scale
Relevant Okta Events | user.session.start user.authentication.auth_via_richclient |
Query | — Get users who failed to login from the same IP address at least 5 times select count(id), “clientIpAddress”, “actorAlternateId”, min(time) as “firstEvent”, max(time) as “lastEvent” from okta_logs where “eventType” =’user.session.start’ and “actionResult”=’FAILURE’ and “resultReason” in (‘INVALID_CREDENTIALS’, ‘LOCKED_OUT’) and “time” > now() -interval ‘1 day’ group by “clientIpAddress”, “actorAlternateId” having count(id) >= 5 order by count desc — For Each result, check if the source IP address managed to login to the target user AFTER the “lastEvent” time |
MITRE Technique | Credential Access | Brute Force | ATT&CK T1110 |
It’s also worth mentioning that based on the tenant behavioral configuration Okta can also enrich each sign-in attempt with additional fields that add more context such as:
- Threat Suspected
- New Device
- New IP Address
- New Geo Location (Country\City\State)
Including these enrichments in the query can help reduce false positives and focus on the more relevant events.
Scenario 2 – MFA Push Notifications Fatigue
Okta MFA Push Notification Fatigue refers to user exhaustion or annoyance resulting from frequent multi-factor authentication (MFA) push notifications sent by Okta for verification purposes. In this scenario, we assume that an adversary has already compromised user credentials and start flooding the legitimate user with Push notifications, with the hope that the user will approve one of them by mistake. To hunt for this threat scenario, you can search for more than X MFA push notifications, within a short period of time, originating from the same IP address.
A successful MFA fatigue will also generate a user.authentication.auth_via_mfa event. This event will be logged after the targeted user was tricked to allow suspicious access.
Relevant Okta Events | system.push.send_factor_verify_push user.authentication.auth_via_mfa user.mfa.okta_verify.deny_push |
Query | — Generic select count(id), “clientIpAddress”, “actorAlternateId”, min(time) as “firstEvent”, max(time) as “lastEvent” from audit_log_okta_idp_entity where “eventType” =’system.push.send_factor_verify_push’ and “time” > now() -interval ‘X hour’ group by “clientIpAddress”, “actorAlternateId” having count(id) >= 5 — configurable number of MFA attempts order by count desc — Find FAILED MFA fatigue attempts that were denied by the user select count(id), “clientIpAddress”, “actorAlternateId”, min(time) as “firstEvent”, max(time) as “lastEvent” from audit_log_okta_idp_entity where “eventType” =’user.mfa.okta_verify.deny_push’ and “time” > now() -interval ’24 days’ group by “clientIpAddress”, “actorAlternateId” having count(id) >= 5 order by count desc |
MITRE Technique | Credential Access | Multi-Factor Authentication Request Generation | ATT&CK T1621 |
Scenario 3 – Okta ThreatInsight Detection
Okta ThreatInsight is a security module that aggregates sign-in activities meta-data across the Okta customer base to analyze and detect potentially malicious IP addresses and prevent credential-based attacks. It is also a great starting point to find an initial indication for identifying targeted attacks against specific identities in the organization’s directory.
Relevant Okta Events | security.threat.detected |
Query | select min(time) as “first_event”, max(time) as “last_event”, “actorName”, “actorType”, “actorAlternateId”, “eventType”, “threatDetections” from audit_log_okta_idp_entity aloie where “eventType” =’security.threat.detected’ group by “actorName”, “actorType”, “actorAlternateId”, “eventType”, “threatDetections” |
MITRE Technique | Credential Access | Brute Force | ATT&CK T1110 |
Scenario 4 – Okta Session Hijacking
A Session Hijacking attack refers to a situation in which an attacker was able to get his hand on the browser cookies of an authenticated Okta user. This risk is mostly involving targeted attacks and includes either malware infection on the user endpoint or a man-in-a-middle (MITM) attack that hijacks the user’s traffic. (read more in this Okta Article). Okta’s dtHash serves as a useful tool for identifying stolen Okta sessions.
Okta’s dtHash, also known as the “de-identified token hash,” is a cryptographic hash function utilized to safeguard user identifiers within Okta sessions. Its purpose is to mitigate the risk of sensitive user information being compromised in the event of a data breach or unauthorized access to Okta’s portal or applications. For our hunting, we will search for a stolen Okta user’s session that is being utilized in a different geographical location. We will detect it by searching for a dtHash that has been used from multiple geo-locations.
Important Note – To enhance the effectiveness of detection, the session length limit plays a vital role. Okta recommends customers set a session length limit of 2 hours. It is worth noting that increasing the length limit raises the possibility of encountering false positives in the detection process.
Relevant Okta Events | Every Okta event |
Query | select count(distinct “clientCountry”), “actorAlternateId”, “dtHash” from audit_log_okta_idp_entity where “dtHash” is not null group by “actorAlternateId”,”dtHash” having count(distinct “clientCountry”) >1 |
MITRE Technique | Collection | Browser Session Hijacking | ATT&CK T1185 |
Scenario 5 – Okta Privilege Escalation via Impersonation
In this threat scenario, an Okta application administrator could impersonate another user by modifying an existing application assignment, specifically by editing the ‘User Name’ field used by Okta to identify users in the destination application. This manipulation allows the administrator to authenticate themselves as a different user in any federated application, presenting a risk of privilege escalation, especially in critical SaaS applications like AWS IAM Identity Center.
Relevant Okta Events | Application.user_membership.change_username |
Query | select * from audit_log_okta_idp_entity aloie where “eventType” =’application.user_membership.change_username’ — For each result, check the target application. If the target application is relevant for this detection, the target AppUser is the field that we need to validate. An impersonation configuration was set if there’s a mismatch between the targetName and the targetAlternateId. |
MITRE Technique | Persistence | Account Manipulation | ATT&CK T1098 |
Scenario 6 – Phishing Attempt (Blocked by FastPass)
FastPass is Okta’s passwordless solution designed to minimize friction for the end-user during the login process while protecting against real-time phishing attacks. By adding additional layers of context to the login process (such as managed device information) it allows Okta to identify potentially suspicious authentication flows and it automatically blocks them, generating an indicative log in the audit. We can use this event result to identify potentially compromised credentials of Okta identities.
Relevant Okta Events | User.authentication.auth_via_mfa |
Query | select * from audit_log_okta_idp_entity aloie where “eventType” =’user.authentication.auth_via_mfa’ and “actionResult” =’FAILURE’ and “actionResult” = ‘FastPass declined phishing attempt’ |
MITRE Technique | Initial Access | Phishing | ATT&CK T1566 |
Scenario 7 – Okta Impossible Traveler
Within the realm of threat hunting, the concept of the “impossible traveler” denotes a detection method employed to uncover compromised identities. Specifically, it involves identifying instances where an identity records successful login events from two distinct geographical locations within a brief time span, which may suggest a compromise.
To identify potentially compromised identities, conduct a search for users who have experienced successful sign-in events from different geographical locations within a short timeframe. It is recommended to exclude VPN and proxy addresses from the analysis to focus on genuine geographic variations and to avoid false positives.
If pre-configured properly, you can also use Okta’s velocity within the triage process to elevate the suspicion level of a particular sign-in location over others.
Relevant Okta Events | User.session.start |
Query | select count(distinct “clientCountry”), “actorAlternateId” from audit_log_okta_idp_entity aloie where “eventType” =’user.session.start’ and “time” > now() -interval ‘1day’ group by “actorAlternateId” having count(distinct “clientCountry”) > 1 |
MITRE Technique | Initial Access | Valid Accounts | ATT&CK T1078 |
Scenario 8 – Cleartext Credentials Transfer Using SCIM
The SCIM (System for Cross-domain Identity Management) protocol is a standardized method for managing user identities and provisioning them across different systems and applications. It simplifies user management by providing a common framework for creating, updating, and deleting user accounts, as well as managing user attributes and group memberships, across various platforms. One of Okta’s features allows setting a sync workflow, pushing any password changes to a target SCIM application. Configuring this requires Admin privileges to the Okta Console, so most likely to be a legitimate operation, yet, on rare occasions could be part of a hostile password-stealing attack by an insider.
To detect this, we can search for the credentials export activity, and check that all of the target applications are legitimate and intended.
Relevant Okta Events | app.user_management.push_okta_password_update |
Query | select * from audit_log_okta_idp_entity where “eventType” =’app.user_management.push_okta_password_update’ |
MITRE Technique | Credential Access | Exploitation for Credential Access | ATT&CK T1212 |
Scenario 9 – Application Access Brute Force
When an attacker gains access to a compromised Okta user, they may attempt to use Okta’s portal to connect to various trusted applications. However, the attacker’s attempts to access multiple apps can be denied by authentication policy requirements that have not been satisfied, such as the absence of MFA. An attacker may try to access different applications one by one, until finding those that allow him to operate without additional factors or conditions.
To identify this behavior we will search for a user who has experienced multiple failed access attempts to different applications within a short time frame. This could raise a red flag and require a follow-up investigation of the user’s activity.
Relevant Okta Events | application.policy.sign_on.deny_accesst |
Query | select count(targets.”targetId”), logs.”actorAlternateId”, logs.”clientIpAddress”, logs.”actorAlternateId” from audit_log_okta_idp_entity logs, audit_log_target_okta_idp_entity targets where “eventType”=’application.policy.sign_on.deny_access’ and targets.”auditLogId” = logs.”id” and targets.”targetType” = ‘AppInstance’ and “time” > now() -interval ‘1 month’ group by “clientIpAddress”, “actorAlternateId” having count(targets.”targetId”) >= 5 order by count desc |
MITRE Technique | Credential Access | Exploitation for Credential Access | ATT&CK T1212 |
On top of the scenarios mentioned above, there are more interesting events that can be used to hunt for threats in an Okta environment. These events are harder to rely on since they require having a deeper context of the regular activities in the organization to differentiate the legitimate operations from those that may be part of an attack.
For example, an API Token created by an administrative user. It could be malicious or legitimate, and requires triage for a verdict:
- Why did the user create this API key?
- Is it part of any task associated with an active project? If not,
- Was it really the user, or is it a persistent action by a hostile actor?
Okta Event Type | Definition | MITRE ATT&CK |
user.session.access_admin_app | Okta admin | T1078 |
system.api_token.create | Administrative API Token Created | T1098.001 |
user.account.privilege.grantgroup.privilege.grant | Administrative Privileges Assignment | N/A |
user.mfa.factor.* | MFA Changes | T1556 |
system.idp.lifecycle.create system.agent.ad.create | Addition of external IdP | T1556 |
policy.rule.* policy.lifecycle.* application.policy.* | Authentication Policy Changes. | T1556 |
network_zone.rule.disabled zone.* | Changes to Network Zones | T1556 |
user.account.report_suspicious_activity_by_enduser | Suspicious Activity Reported | N/A |
user.mfa.attempt_bypass | Attempt to Bypass MFA | N/A |
security.request.blocked | Access from a Known-Bad IP was Blocked | N/A |
user.session.impersonation.initiate | Okta Impersonation Session Started | N/A |
To see how Rezonate can help detect risks and threats across your Okta infrastructure, contact us for more information or request a free demo.
Like this article? Follow us on LinkedIn.