Unauthorized Scope for Public App OAuth2 Token Grant with Client Credentials

Identifies a failed OAuth 2.0 token grant attempt for a public client app using client credentials. This event is generated when a public client app attempts to exchange a client credentials grant for an OAuth 2.0 access token, but the request is denied due to the lack of required scopes. This could indicate compromised client credentials in which an adversary is attempting to obtain an access token for unauthorized scopes. This is a New Terms rule where the okta.actor.display_name field value has not been seen in the last 14 days regarding this event.

Elastic rule (View on GitHub)

 1[metadata]
 2creation_date = "2024/09/11"
 3integration = ["okta"]
 4maturity = "production"
 5updated_date = "2024/09/23"
 6
 7[rule]
 8author = ["Elastic"]
 9description = """
10Identifies a failed OAuth 2.0 token grant attempt for a public client app using client credentials. This event is
11generated when a public client app attempts to exchange a client credentials grant for an OAuth 2.0 access token, but
12the request is denied due to the lack of required scopes. This could indicate compromised client credentials in which an
13adversary is attempting to obtain an access token for unauthorized scopes. This is a [New
14Terms](https://www.elastic.co/guide/en/security/master/rules-ui-create.html#create-new-terms-rule) rule where the
15`okta.actor.display_name` field value has not been seen in the last 14 days regarding this event.
16"""
17from = "now-9m"
18index = ["filebeat-*", "logs-okta*"]
19language = "kuery"
20license = "Elastic License v2"
21name = "Unauthorized Scope for Public App OAuth2 Token Grant with Client Credentials"
22references = [
23    "https://github.blog/news-insights/company-news/security-alert-stolen-oauth-user-tokens/",
24    "https://developer.okta.com/docs/reference/api/event-types/",
25    "https://www.elastic.co/security-labs/monitoring-okta-threats-with-elastic-security",
26    "https://www.elastic.co/security-labs/starter-guide-to-understanding-okta",
27]
28risk_score = 47
29rule_id = "6649e656-6f85-11ef-8876-f661ea17fbcc"
30severity = "medium"
31tags = [
32    "Domain: SaaS",
33    "Data Source: Okta",
34    "Use Case: Threat Detection",
35    "Use Case: Identity and Access Audit",
36    "Tactic: Defense Evasion",
37]
38timestamp_override = "event.ingested"
39type = "new_terms"
40
41query = '''
42event.dataset: okta.system
43    and event.action: "app.oauth2.as.token.grant"
44    and okta.actor.type: "PublicClientApp"
45    and okta.debug_context.debug_data.flattened.grantType: "client_credentials"
46    and okta.outcome.result: "FAILURE"
47    and not okta.client.user_agent.raw_user_agent: "Okta-Integrations"
48    and not okta.actor.display_name: (Okta* or Datadog)
49    and not okta.debug_context.debug_data.flattened.requestedScopes: ("okta.logs.read" or "okta.eventHooks.read" or "okta.inlineHooks.read")
50    and okta.outcome.reason: "no_matching_scope"
51'''
52
53
54[[rule.threat]]
55framework = "MITRE ATT&CK"
56[[rule.threat.technique]]
57id = "T1550"
58name = "Use Alternate Authentication Material"
59reference = "https://attack.mitre.org/techniques/T1550/"
60[[rule.threat.technique.subtechnique]]
61id = "T1550.001"
62name = "Application Access Token"
63reference = "https://attack.mitre.org/techniques/T1550/001/"
64
65
66
67[rule.threat.tactic]
68id = "TA0005"
69name = "Defense Evasion"
70reference = "https://attack.mitre.org/tactics/TA0005/"
71
72[rule.new_terms]
73field = "new_terms_fields"
74value = ["okta.actor.display_name"]
75[[rule.new_terms.history_window_start]]
76field = "history_window_start"
77value = "now-14d"

References

Related rules

to-top