Skip to content

Commit

Permalink
[New Hunt] Add Initial Okta Hunting Queries (#4064)
Browse files Browse the repository at this point in the history
* adding new Okta hunting queries

* query format changes

* adding docs

* added query for mfa bombing

* adding remainder hunting queries

* adjusted incorrect hunt

* updated queries

* updated queries based on Samir's feedback

* removed failed login eval

* updated docs

(cherry picked from commit 9181c00)
  • Loading branch information
terrancedejesus authored and github-actions[bot] committed Sep 16, 2024
1 parent ec92d4f commit a6bd8df
Show file tree
Hide file tree
Showing 28 changed files with 1,204 additions and 2 deletions.
15 changes: 15 additions & 0 deletions hunting/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,20 @@ Here are the queries currently available:
- [STS Suspicious Federated Temporary Credential Request](./aws/docs/sts_suspicious_federated_temporary_credential_request.md) (ES|QL)


## docs
- [Rapid MFA Deny Push Notifications (MFA Bombing)](./okta/docs/docs/credential_access_mfa_bombing_push_notications.md) (ES|QL)
- [Rapid Reset Password Requests for Different Users](./okta/docs/docs/credential_access_rapid_reset_password_requests_for_different_users.md) (ES|QL)
- [Failed OAuth Access Token Retrieval via Public Client App](./okta/docs/docs/defense_evasion_failed_oauth_access_token_retrieval_via_public_client_app.md) (ES|QL)
- [Multiple Application SSO Authentication from the Same Source](./okta/docs/docs/defense_evasion_multiple_application_sso_authentication_repeat_source.md) (ES|QL)
- [OAuth Access Token Granted for Public Client App from Multiple Client Addresses](./okta/docs/docs/defense_evasion_multiple_client_sources_reported_for_oauth_access_tokens_granted.md) (ES|QL)
- [Rare Occurrence of OAuth Access Token Granted to Public Client App](./okta/docs/docs/defense_evasion_rare_oauth_access_token_granted_by_application.md) (ES|QL)
- [Identify High Average of Failed Daily Authentication Attempts](./okta/docs/docs/initial_access_higher_than_average_failed_authentication.md) (ES|QL)
- [Successful Impossible Travel Sign-On Events](./okta/docs/docs/initial_access_impossible_travel_sign_on.md) (ES|QL)
- [Password Spraying from Repeat Source](./okta/docs/docs/initial_access_password_spraying_from_repeat_source.md) (ES|QL)
- [Multi-Factor Authentication (MFA) Push Notification Bombing](./okta/docs/docs/persistence_multi_factor_push_notification_bombing.md) (ES|QL)
- [Rare Occurrence of Domain with User Authentication Events](./okta/docs/docs/persistence_rare_domain_with_user_authentication.md) (ES|QL)


## linux
- [Network Connections with Low Occurrence Frequency for Unique Agent ID](./linux/docs/command_and_control_via_network_connections_with_low_occurrence_frequency_for_unique_agents.md) (ES|QL)
- [Unusual File Downloads from Source Addresses](./linux/docs/command_and_control_via_unusual_file_downloads_from_source_addresses.md) (ES|QL)
Expand Down Expand Up @@ -58,6 +72,7 @@ Here are the queries currently available:

## llm
- [AWS Bedrock LLM Denial-of-Service or Resource Exhaustion](./llm/docs/aws_bedrock_dos_resource_exhaustion_detection.md) (ES|QL)
- [AWS Bedrock LLM Ignore Previous Prompt Detection](./llm/docs/aws_bedrock_ignore_previous_prompt_detection.md) (ES|QL)
- [AWS Bedrock LLM Latency Anomalies](./llm/docs/aws_bedrock_latency_anomalies_detection.md) (ES|QL)
- [AWS Bedrock LLM Sensitive Content Refusals](./llm/docs/aws_bedrock_sensitive_content_refusal_detection.md) (ES|QL)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
- **UUID:** `131e5887-463a-46a1-a44e-b96361bc6cbc`
- **Integration:** [aws_bedrock.invocation](https://docs.elastic.co/integrations/aws_bedrock)
- **Language:** `[ES|QL]`
- **Source File:** [AWS Bedrock LLM Sensitive Content Refusals](../queries/aws_bedrock_ignore_previous_prompt_detection.toml)
- **Source File:** [AWS Bedrock LLM Ignore Previous Prompt Detection](../queries/aws_bedrock_ignore_previous_prompt_detection.toml)

## Query

Expand All @@ -33,7 +33,7 @@ from logs-aws_bedrock.invocation-*

## Notes

- Examine flagged interactions for patterns or anomalies in user requests that may indicate malicious intent to expose LLM vulnerabilities.
- Examine flagged interactions for patterns or anomalies in user requests that may indicate malicious intent to expose LLM vulnerabilities
- Regularly review and update the phrases that trigger ignore previous prompt attacks to adapt to new ethical guidelines and compliance requirements.
- Ensure that data logs contain enough detail to provide context around the refusal, which will aid in subsequent investigations by security teams.

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Identify High Average of Failed Daily Authentication Attempts

---

## Metadata

- **Author:** Elastic
- **Description:** This hunting query identifies when the average number of failed daily authentication attempts is higher than normal in Okta. Adversaries may attempt to brute force user credentials to gain unauthorized access to accounts. This query calculates the average number of daily failed authentication attempts for each user and identifies when the average is higher than normal.

- **UUID:** `c8a35a26-71f1-11ef-9c4e-f661ea17fbcc`
- **Integration:** [okta](https://docs.elastic.co/integrations/okta)
- **Language:** `[ES|QL]`
- **Source File:** [Identify High Average of Failed Daily Authentication Attempts](../queries/credential_access_hgher_than_average_failed_authentication.toml)

## Query

```sql
from logs-okta*
| where @timestamp > NOW() - 7 day

// truncate the timestamp to daily intervals
| eval target_time_window = DATE_TRUNC(1 days, @timestamp)
| where

// filter for invalid credential authentication events
event.action == "user.session.start"
and okta.outcome.result == "FAILURE"
and okta.outcome.reason == "INVALID_CREDENTIALS"

// add a count of 1 for each failed login
| eval failed_login_count = 1

| stats
// count the number of daily failed logins for each day and user
failed_daily_logins = count(*) by target_time_window, okta.actor.alternate_id

| stats
// calculate the average number of daily failed logins for each day
avg_daily_logins = avg(failed_daily_logins) by target_time_window

// sort the results by the average number of daily failed logins in descending order
| sort avg_daily_logins desc
```

## Notes

- Pivot to users by only keeping the first stats statement where `okta.actor.alternate_id` is the targeted accounts.
- Pivot for successful logins from the same source IP by searching for `event.action` equal to `user.session.start` or `user.authentication.verify` where the outcome is `SUCCESS`.
- User agents can be used to identify anomalous behavior, such as a user agent that is not associated with a known application or user.
- Another `WHERE` count can be added to the query if activity has been baseline to filter out known behavior.

## MITRE ATT&CK Techniques

- [T1078.004](https://attack.mitre.org/techniques/T1078/004)

## License

- `Elastic License v2`
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Rapid MFA Deny Push Notifications (MFA Bombing)

---

## Metadata

- **Author:** Elastic
- **Description:** This hunting query identifies MFA bombing attacks in Okta. Adversaries may attempt to flood a user with multiple MFA push notifications to disrupt operations or gain unauthorized access to accounts. This query identifies when a user has more than 5 MFA deny push notifications in a 10 minute window.

- **UUID:** `223451b0-6eca-11ef-a070-f661ea17fbcc`
- **Integration:** [okta](https://docs.elastic.co/integrations/okta)
- **Language:** `[ES|QL]`
- **Source File:** [Rapid MFA Deny Push Notifications (MFA Bombing)](../queries/credential_access_mfa_bombing_push_notications.toml)

## Query

```sql
from logs-okta*
| where @timestamp > NOW() - 7 day

// Truncate the timestamp to 10 minute windows
| eval target_time_window = DATE_TRUNC(10 minutes, @timestamp)

// Filter for MFA deny push notifications
| where event.action == "user.mfa.okta_verify.deny_push"

// Count the number of MFA deny push notifications for each user in each 10 minute window
| stats deny_push_count = count(*) by target_time_window, okta.actor.alternate_id

// Filter for users with more than 5 MFA deny push notifications
| where deny_push_count >= 5
```

## Notes

- `okta.actor.alternate_id` is the targeted user account.
- Pivot and search for `event.action` is `user.authentication.auth_via_mfa` to determine if the target user accepted the MFA push notification.
- If a MFA bombing attack is suspected, both username and password are required prior to MFA push notifications. Thus the credentials are likely compromised.

## MITRE ATT&CK Techniques

- [T1621](https://attack.mitre.org/techniques/T1621)

## License

- `Elastic License v2`
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Password Spraying from Repeat Source

---

## Metadata

- **Author:** Elastic
- **Description:** This hunting query identifies password spraying attacks in Okta where the same source IP attempts to authenticate to multiple accounts with invalid credentials. Adversaries may attempt to use a single source IP to avoid detection and bypass account lockout policies.

- **UUID:** `1c2d2b08-71ee-11ef-952e-f661ea17fbcc`
- **Integration:** [okta](https://docs.elastic.co/integrations/okta)
- **Language:** `[ES|QL]`
- **Source File:** [Password Spraying from Repeat Source](../queries/credential_access_password_spraying_from_repeat_source.toml)

## Query

```sql
from logs-okta*
| where @timestamp > NOW() - 7 day

// truncate the timestamp to daily intervals
| eval target_time_window = DATE_TRUNC(1 days, @timestamp)
| where

// filter for invalid credential events
event.action == "user.session.start"
and okta.outcome.result == "FAILURE"
and okta.outcome.reason == "INVALID_CREDENTIALS"
| stats
// count the distinct number of targeted accounts
target_count = count_distinct(okta.actor.alternate_id),

// count the number of invalid credential events for each source IP
source_count = count(*) by target_time_window, okta.client.ip

// filter for source IPs with more than 5 invalid credential events
| where target_count >= 5
```

## Notes

- `okta.actor.alternate_id` are the targeted accounts.
- Pivot for successful logins from the same source IP by searching for `event.action` equal to `user.session.start` or `user.authentication.verify` where the outcome is `SUCCESS`.
- User agents can be used to identify anomalous behavior, such as a user agent that is not associated with a known application or user.
- The `target_count` can be adjusted depending on the organization's account lockout policy or baselined behavior.

## MITRE ATT&CK Techniques

- [T1078.004](https://attack.mitre.org/techniques/T1078/004)

## License

- `Elastic License v2`
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Rapid Reset Password Requests for Different Users

---

## Metadata

- **Author:** Elastic
- **Description:** This hunting query identifies rapid reset password requests for different users in Okta. Adversaries may attempt to reset passwords for multiple users in rapid succession to gain unauthorized access to accounts or disrupt operations. This query identifies when the source user is different from the target user in reset password events and filters for users with more than 15 reset password attempts.

- **UUID:** `c784106e-6ae8-11ef-919d-f661ea17fbcc`
- **Integration:** [okta](https://docs.elastic.co/integrations/okta)
- **Language:** `[ES|QL]`
- **Source File:** [Rapid Reset Password Requests for Different Users](../queries/credential_access_rapid_reset_password_requests_for_different_users.toml)

## Query

```sql
from logs-okta.system*
| where @timestamp > NOW() - 7 day

// Filter for reset password events where the source user is different from the target user
| where event.dataset == "okta.system" and event.action == "user.account.reset_password" and source.user.full_name != user.target.full_name

// Extract relevant fields
| keep @timestamp, okta.actor.alternate_id, okta.debug_context.debug_data.dt_hash, user.target.full_name, okta.outcome.result

// Count the number of reset password attempts for each user
| stats
user_count = count_distinct(user.target.full_name),
reset_counts = by okta.actor.alternate_id, source.user.full_name, okta.debug_context.debug_data.dt_hash

// Filter for more than 10 unique users and more than 15 reset password attempts by the source
| where user_count > 10 and reset_counts > 15
```

## Notes

- `okta.actor.alternate_id` is the potentially compromised account
- An API access token may have been compromised, where okta.actor.alternate_id reflects the owner
- To identify a list of tokens this user created, search for the `okta.actor.alternate_id` where `event.action` is `system.api_token*` which may require a larger time window

## MITRE ATT&CK Techniques

- [T1098.001](https://attack.mitre.org/techniques/T1098/001)

## License

- `Elastic License v2`
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Failed OAuth Access Token Retrieval via Public Client App

---

## Metadata

- **Author:** Elastic
- **Description:** This hunting query identifies when a public client app fails to retrieve an OAuth access token using client credentials because of an uauthorized scope. Adversaries may attempt to retrieve access tokens using client credentials to bypass user authentication and access resources. This query identifies when a public client app fails to retrieve an access token using client credentials and scopes that are not implicitly granted.

- **UUID:** `0b936024-71d9-11ef-a9be-f661ea17fbcc`
- **Integration:** [okta](https://docs.elastic.co/integrations/okta)
- **Language:** `[ES|QL]`
- **Source File:** [Failed OAuth Access Token Retrieval via Public Client App](../queries/defense_evasion_failed_oauth_access_token_retrieval_via_public_client_app.toml)

## Query

```sql
from logs-okta.system*
| where @timestamp > NOW() - 7 day
| where
event.dataset == "okta.system"

// filter on failed access token grant requests where source is a public client app
and event.action == "app.oauth2.as.token.grant"
and okta.actor.type == "PublicClientApp"
and okta.outcome.result == "FAILURE"

// filter out known Okta and Datadog actors
and not (
okta.actor.display_name LIKE "Okta%"
or okta.actor.display_name LIKE "Datadog%"
)

// filter for scopes that are not implicitly granted
and okta.outcome.reason == "no_matching_scope"
```

## Notes

- Review `okta.debug_context.debug_data.flattened.grantType` to identify if the grant type is `client_credentials`
- Ignore `okta.debug_context.debug_data.flattened.requestedScopes` values that indicate read-only access
- Review `okta.actor.display_name` to identify the public client app that attempted to retrieve the access token. This may help identify the compromised client credentials.
- Pivot for successful access token retrieval by the same public client app by searching `event.action` equal to `app.oauth2.as.token.grant.access_token` where the display name is the same.

## MITRE ATT&CK Techniques

- [T1550.001](https://attack.mitre.org/techniques/T1550/001)

## License

- `Elastic License v2`
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Multiple Application SSO Authentication from the Same Source

---

## Metadata

- **Author:** Elastic
- **Description:** This hunting query identifies when a user authenticates to multiple applications using Single Sign-On (SSO) from the same source. Adversaries may attempt to authenticate to multiple applications using SSO to gain unauthorised access to sensitive data or resources. Adversaries also rely on refresh tokens to maintain access to applications and services. This query identifies when a source IP authenticates to more than 15 applications using SSO within a 5-minute window.

- **UUID:** `03bce3b0-6ded-11ef-9282-f661ea17fbcc`
- **Integration:** [okta](https://docs.elastic.co/integrations/okta)
- **Language:** `[ES|QL]`
- **Source File:** [Multiple Application SSO Authentication from the Same Source](../queries/defense_evasion_multiple_application_sso_authentication_repeat_source.toml)

## Query

```sql
from logs-okta*
| eval target_time_window = DATE_TRUNC(5 minutes, @timestamp)

// truncate the timestamp to a 5-minute window
| where @timestamp > now() - 7 day

// filter for SSO authentication events where the authentication step is 0
// filter on request URI string '/app/' to identify applications for a user
| where
event.action == "user.authentication.sso"
and okta.authentication_context.authentication_step == 0
and okta.debug_context.debug_data.request_uri RLIKE "(.*)/app/(.*)"

// dissect the request URI to extract the target application
| dissect okta.debug_context.debug_data.request_uri"%{?}/app/%{target_application}/"

// count the number of unique applications per source IP and user in a 5-minute window
| stats application_count = count_distinct(target_application), window_count = count(*) by target_time_window, source.ip, okta.actor.alternate_id

// filter for at least 15 distinct applications authenticated from a single source IP
| where application_count > 15
```

## Notes

- `okta.debug_context.debug_data.dt_hash` field can be used to identify the device token hash used for authentication. This can be used to pivot for additional activity from the same device.
- `okta.debug_context.debug_data.flattened` contains additional information such as request ID, trace ID, sign-on mode and more to review for anomalies in the authentication flow.
- `okta.request.ip_chain` can be used to understand more about the source address, which is potentially useful for profiling.
- If `okta.security_context.is_proxy` is `true`, then an adversary may be attempting to mask their true source behind a proxy or VPN.

## MITRE ATT&CK Techniques

- [T1550.001](https://attack.mitre.org/techniques/T1550/001)

## License

- `Elastic License v2`
Loading

0 comments on commit a6bd8df

Please sign in to comment.