Okta Threat Hunting: Auditing Okta Logs Part 2

Update Note

Due to the recent events at MGM, which included the compromise of MGM’s Okta tenant, and the surge in attacks of Okta Admins,  we have updated the threat-hunting article, adding a few relevant queries to increase visibility surrounding compromised administrators, and detection of ransom groups that tend to perform aggressive steps to cause maximum disruption to their target and prevent recovery attempts.
To read our first Blog Post Okta Logs Decoded: Unveiling Identity Threats Through Threat Hunting, click here

Let the Hunt Continue 

Scenario 1 – User Account Hijack

Social engineering for initial access is on the rise. These techniques are usually simple and do not require much technical knowledge. Attacks such as phishing, MFA relay, or even buying credentials online may help attackers compromise user accounts.

Usually, when an adversary compromises a user, gaining persistent access to that account is essential. To do so, the adversary may change the user’s password and enroll a new MFA device, and in some cases even delete the original user’s factors.
The following query identifies user accounts that performed a series of actions from an IP address that is not being used often by the organization, during a short period of time – which might suggest that these accounts are compromised. The actions that this query searches for are:

  • Self-password reset
  • MFA enrollment
  • MFA deletion 

Relevant Okta Events:

  • user.mfa.factor.activate
  • user.mfa.factor.deactivate
  • user.account.reset_password
  • user.session.start
  • device.user.add

Okta Log Query

-- User Account Hijack
-- You can use the "actorAlternateId" filter to focus on administrators
select "clientIpAddress", "clientCountry", "actorAlternateId", min(time) as first_event, max(time) as last_event, count(distinct "eventType") as unique_events, 
count(id) as event_count, array_agg(distinct "eventType") as events, extract(EPOCH FROM max("time")) - extract(epoch from min("time")) as duration_epoch
from audit_log_okta_idp_entity aloie 
where "eventType" in ('user.mfa.factor.activate', 'user.mfa.factor.deactivate', 'user.account.reset_password', 'user.session.start', 'device.user.add')
and "actionResult" = 'SUCCESS'
and time > now() -interval '1 week'
--and "actorAlternateId" in ('admin1', 'admin2', ...)
group by "clientIpAddress", "clientCountry", "actorAlternateId"
having count(distinct "eventType") >= 3

MITRE Technique: Initial Access | Social Engineering and Phishing | ATT&CK T1566


Scenario 2 – Rogue Administrator Tenant Takeover

When an adversary successfully compromises an administrator they might try to block access to the rest of the administrators in the organization to strengthen their hold on the tenant and ensure that no one can reverse their actions.

In such a scenario, the rogue admin might try to revoke administrative privileges or disable multiple user accounts.

Use the following queries to detect the described scenario.

Relevant Okta Events:

  • user.lifecycle.deactivate
  • user.lifecycle.suspend
  • user.account.privilege.revoke
  • group.account.privilege.revoke

Okta Log Query 1

-- Multiple users disabled or deactivated by a single user
select "clientIpAddress", "clientCountry", "actorAlternateId", min(time) as first_event, max(time) as last_event,
count(distinct "targetAlternateId") filter (where "eventType"='user.lifecycle.suspend') as unique_suspended_users,
count(distinct "targetAlternateId") filter (where "eventType"='user.lifecycle.deactivate') as unique_deactivated_users
from (select aloie.time ,aloie."clientIpAddress", aloie."clientCountry", aloie."actorAlternateId",aloie."eventType", altoie."targetAlternateId" 
	from audit_log_okta_idp_entity aloie, audit_log_target_okta_idp_entity altoie 
	where "eventType" in ('user.lifecycle.deactivate', 'user.lifecycle.suspend')
	and aloie."actionResult" = 'SUCCESS'
	and aloie.id = altoie."auditLogId") base
group by "clientIpAddress", "clientCountry", "actorAlternateId"
having (count(distinct "targetAlternateId") filter (where "eventType"='user.lifecycle.suspend') > 1 or count(distinct "targetAlternateId") filter (where "eventType"='user.lifecycle.deactivate') > 1)

Okta Log Query 2

-- Multiple admin privileges revoked
select "clientIpAddress", "clientCountry", "actorAlternateId", min(time) as first_event, max(time) as last_event,
count(distinct "targetAlternateId") filter (where "eventType"='user.account.privilege.revoke') as revoked_users,
count(distinct "targetAlternateId") filter (where "eventType"='group.account.privilege.revoke') as revoked_groups
from (select aloie.time ,aloie."clientIpAddress", aloie."clientCountry", aloie."actorAlternateId",aloie."eventType", altoie."targetAlternateId" 
	from audit_log_okta_idp_entity aloie, audit_log_target_okta_idp_entity altoie 
	where "eventType" in ('user.account.privilege.revoke', 'group.account.privilege.revoke')
	and aloie."actionResult" = 'SUCCESS'
	and aloie.id = altoie."auditLogId") base
group by "clientIpAddress", "clientCountry", "actorAlternateId"
having (count(distinct "targetAlternateId") filter (where "eventType"='user.account.privilege.revoke') > 1 or count(distinct "targetAlternateId") filter (where "eventType"='group.account.privilege.revoke') > 1)

MITRE Technique: Impact | Account Access Removal | ATT&CK T1531

Scenario 3 – Authentication Policy Downgrade

When an adevrary successfully compromises an administrator account, they may downgrade the tenant’s authentication requirement to ease their access to the tenant. Policy changes are not events that are triggered frequently since these are sensitive events that occur when the organization updates their authentication requirements. We can use these event to hunt for an adversary that made multiple changes to authentication policies and rules with the following query.

Relevant Okta Events:

  • policy.lifecycle.update
  • policy.rule.update
  • policy.rule.add

Okta Log Query

-- Multiple authentication policy and rules changes
select "clientIpAddress", "clientCountry", "actorAlternateId", min(time) as first_event, max(time) as last_event,
count(distinct "targetAlternateId") filter (where "eventType"='policy.lifecycle.update') as unique_policies_updated,
count(distinct "targetAlternateId") filter (where "eventType"='policy.rule.update') as unique_policy_rules_updated,
count(distinct "targetAlternateId") filter (where "eventType"='policy.rule.add') as unique_policy_rules_created,
count(id) as event_count
from (select aloie.id, aloie.time ,aloie."clientIpAddress", aloie."clientCountry", aloie."actorAlternateId",aloie."eventType", altoie."targetAlternateId" 
	from audit_log_okta_idp_entity aloie, audit_log_target_okta_idp_entity altoie 
	where "eventType" in ('policy.lifecycle.update', 'policy.rule.update', 'policy.rule.add')
	and aloie."actionResult" = 'SUCCESS'
	and aloie.id = altoie."auditLogId") base
group by "clientIpAddress", "clientCountry", "actorAlternateId"
having count(id) >= 3

MITRE Technique: Persistence | Modify Authentication Process | ATT&CK T1556

Scenario 4 – Authentication Via Proxy 

Adversaries will try to disguise their origin IP addresses using proxy solutions. When a user uses a proxy for authentication, Okta marks the sign-in as such. Monitor administrators that are logging in via proxy to detect suspicious administrator sign-ins.

Relevant Okta Events:

  • user.session.start

Okta Log Query

-- Proxy Authentication
select "clientIpAddress", "clientCountry", "actorAlternateId", min(time) as first_event, max(time) as last_event, age(max(time), min(time)) as duration,
count(id) as event_count
from audit_log_okta_idp_entity aloie 
where "eventType" ='user.session.start' 
and "actorAlternateId" in ('admin1', 'admin2', ...)
and "isProxy" = true
and "actionResult" = 'SUCCESS'
group by "clientIpAddress", "clientCountry", "actorAlternateId"

MITRE Technique: Initial Access | Proxy Usage | ATT&CK T1090

2 Additional Queries For Administrative Okta Governance

Okta Log Query 1 – Access to Okta Admin App from Rare Locations

Monitor access to the Okta admin app from rare IP addresses and search for unauthorized access to the Okta Admin app.

Relevant Okta Events:

  • user.session.access_admin_app

Okta Log Query

-- Admin app access from non-oranizational IP addresses
with org_ips as (SELECT count("timebucket"),"clientIpAddress", "clientCountry"
                                FROM (
                                        SELECT DATE_TRUNC('day', "time") AS TimeBucket, COUNT(distinct "actorAlternateId") AS "userCount",  "clientIpAddress", "clientCountry"
                                        FROM audit_log_okta_idp_entity
                                        WHERE "actionResult" = 'SUCCESS'
                                        AND "time" > now() -interval '1 week'
                                        GROUP BY TimeBucket, "clientIpAddress", "clientCountry"
                                        HAVING COUNT(distinct "actorAlternateId") > 2
                                        ) subquery
                                GROUP BY "clientIpAddress", "clientCountry"
                                HAVING count("timebucket") > 1)
select time, "clientIpAddress", "clientCountry", "actorAlternateId", "eventType"  from audit_log_okta_idp_entity aloie
where "eventType" ='user.session.access_admin_app'
and aloie."clientIpAddress" not in (select distinct "clientIpAddress" from org_ips)
order by time desc

MITRE Technique: https://attack.mitre.org/techniques/T1078/

Okta Log Query 2 – Admin Sign-In With Abnormal Client Characteristics

Note – The following query is relevant only for tenants who use Okta’s behavior detections in their session policies.
Use Okta’s sign-in behavior enrichments to detect suspicious sign-ins to Okta administrators.  

Relevant Azure AD Event Source

  • Azure AD Directory Audit Logs

Okta Log Query

-- Admin Sign-In With Abnormal Client Characteristics
select time, "clientIpAddress", "clientCountry", "actorAlternateId", "eventType"  from audit_log_okta_idp_entity aloie
where "eventType" ='user.session.start' and "actionResult"='SUCCESS'
and "actorAlternateId" in ('admin1', 'admin2', ...)
and "clientBehaviorVelocity" = true 
and "clientBehaviorNewIP" = true 
and "clientBehaviorNewDevice" = true 
and "clientBehaviorNewCountry" = true 
and "clientBehaviorNewGeoLocation" = true 
order by time desc

MITRE Technique: https://attack.mitre.org/techniques/T1078/

Learn More

Discover more Okta Security best practices to Implement Now with Rezonate.

Rezonate was recognized as a 2023 Gartner® Cool Vendor™ in Identity-First Security.  Learn More.