AnalysisType: rule
Filename: okta_anonymizing_vpn_login.py
RuleID: "Okta.Anonymizing.VPN.Login"
DisplayName: "Okta Sign-In from VPN Anonymizer"
Enabled: true
LogTypes:
- Okta.SystemLog
Reports:
MITRE ATT&CK:
- TA0006:T1556 # Modify Authentication Process
Severity: Medium
Description: >
A user is attempting to sign-in to Okta from a known VPN anonymizer. The threat actor would access the compromised account using anonymizing proxy services.
Runbook: >
Restrict this access to trusted Network Zones and deny access from anonymizing proxies in policy using a Dynamic Network Zone.
Reference: >
https://sec.okta.com/articles/2023/08/cross-tenant-impersonation-prevention-and-detection
DedupPeriodMinutes: 360 # 6 hours
Threshold: 1
Tests:
- Name: Other Event
ExpectedResult: false
Log:
actor:
alternateId: homer.simpson@duff.com
displayName: Homer Simpson
id: 00abc123
type: User
authenticationcontext:
authenticationStep: 0
externalSessionId: 100-abc-9999
client:
device: Computer
geographicalContext:
city: Springfield
country: United States
geolocation:
lat: 20
lon: -25
postalCode: "12345"
state: Ohio
ipAddress: 1.3.2.4
userAgent:
browser: CHROME
os: Mac OS X
rawUserAgent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36
zone: "null"
debugcontext:
debugData:
requestId: AbCdEf12G
requestUri: /api/v1/users/AbCdEfG/lifecycle/reset_factors
url: /api/v1/users/AbCdEfG/lifecycle/reset_factors?
displaymessage: Authentication of user via MFA
eventtype: user.session.start
legacyeventtype: core.user.factor.attempt_fail
outcome:
reason: INVALID_CREDENTIALS
result: FAILURE
published: "2022-06-22 18:18:29.015"
request:
ipChain:
- geographicalContext:
city: Springfield
country: United States
geolocation:
lat: 20
lon: -25
postalCode: "12345"
state: Ohio
ip: 1.3.2.4
version: V4
securitycontext:
asNumber: 701
asOrg: verizon
domain: verizon.net
isProxy: false
isp: verizon
severity: INFO
target:
- alternateId: peter.griffin@company.com
displayName: Peter Griffin
id: 0002222AAAA
type: User
transaction:
detail: {}
id: ABcDeFgG
type: WEB
uuid: AbC-123-XyZ
version: "0"
- Name: Anonymizing Proxy Used
ExpectedResult: true
Log:
actor:
alternateId: homer.simpson@duff.com
displayName: Homer Simpson
id: 00abc123
type: User
authenticationcontext:
authenticationStep: 0
externalSessionId: 100-abc-9999
client:
device: Computer
geographicalContext:
city: Springfield
country: United States
geolocation:
lat: 20
lon: -25
postalCode: "12345"
state: Ohio
ipAddress: 1.3.2.4
userAgent:
browser: CHROME
os: Mac OS X
rawUserAgent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36
zone: "null"
debugcontext:
debugData:
requestId: AbCdEf12G
requestUri: /api/v1/users/AbCdEfG/lifecycle/reset_factors
url: /api/v1/users/AbCdEfG/lifecycle/reset_factors?
displaymessage: Authentication of user via MFA
eventtype: user.session.start
legacyeventtype: core.user.factor.attempt_fail
outcome:
reason: FastPass declined phishing attempt
result: FAILURE
published: "2022-06-22 18:18:29.015"
request:
ipChain:
- geographicalContext:
city: Springfield
country: United States
geolocation:
lat: 20
lon: -25
postalCode: "12345"
state: Ohio
ip: 1.3.2.4
version: V4
securitycontext:
asNumber: 701
asOrg: verizon
domain: anonymous.org
isProxy: true
isp: verizon
severity: INFO
target:
- alternateId: peter.griffin@company.com
displayName: Peter Griffin
id: 0002222AAAA
type: User
transaction:
detail: {}
id: ABcDeFgG
type: WEB
uuid: AbC-123-XyZ
version: "0"
- Name: Apple Private Relay Used
ExpectedResult: true
Log:
actor:
alternateId: homer.simpson@duff.com
displayName: Homer Simpson
id: 00abc123
type: User
authenticationcontext:
authenticationStep: 0
externalSessionId: 100-abc-9999
client:
device: Computer
geographicalContext:
city: Springfield
country: United States
geolocation:
lat: 20
lon: -25
postalCode: "12345"
state: Ohio
ipAddress: 1.3.2.4
userAgent:
browser: CHROME
os: Mac OS X
rawUserAgent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36
zone: "null"
debugcontext:
debugData:
requestId: AbCdEf12G
requestUri: /api/v1/users/AbCdEfG/lifecycle/reset_factors
url: /api/v1/users/AbCdEfG/lifecycle/reset_factors?
displaymessage: Authentication of user via MFA
eventtype: user.session.start
legacyeventtype: core.user.factor.attempt_fail
outcome:
reason: FastPass declined phishing attempt
result: FAILURE
p_enrichment:
ipinfo_privacy:
client.ipAddress:
hosting: true
p_match: 1.2.3.4
proxy: false
relay: true
service: Apple Private Relay
tor: false
vpn: false
published: "2022-06-22 18:18:29.015"
request:
ipChain:
- geographicalContext:
city: Springfield
country: United States
geolocation:
lat: 20
lon: -25
postalCode: "12345"
state: Ohio
ip: 1.3.2.4
version: V4
securitycontext:
asNumber: 701
asOrg: verizon
domain: anonymous.org
isProxy: true
isp: verizon
severity: INFO
target:
- alternateId: peter.griffin@company.com
displayName: Peter Griffin
id: 0002222AAAA
type: User
transaction:
detail: {}
id: ABcDeFgG
type: WEB
uuid: AbC-123-XyZ
version: "0"
# ------ paired body: okta_anonymizing_vpn_login.py ------
from panther_okta_helpers import okta_alert_context
def rule(event):
return event.get("eventType") == "user.session.start" and event.deep_get(
"securityContext", "isProxy", default=False
)
def title(event):
ip_context = {}
client = event.get("client", default={})
security_context = event.get("securityContext", default={})
if client.get("ipAddress"):
ip_context["IP"] = client.get("ipAddress")
for key, source_value in [
{"ASO", security_context.get("asOrg")},
{"ISP", security_context.get("isp")},
{"Domain", security_context.get("domain")},
]:
if source_value:
ip_context[key] = source_value
if service := event.deep_get("p_enrichment", "ipinfo_privacy", "client.ipAddress", "service"):
ip_context["Service"] = service
return (
f"{event.deep_get('actor', 'displayName', default='<displayName-not-found>')} "
f"<{event.deep_get('actor', 'alternateId', default='alternateId-not-found')}> "
f"attempted to sign-in from anonymizing VPN - {ip_context}"
)
def alert_context(event):
return okta_alert_context(event)
def severity(event):
# If the user is using Apple Private Relay, demote the severity to INFO
if (
event.deep_get("p_enrichment", "ipinfo_privacy", "client.ipAddress", "service")
== "Apple Private Relay"
):
return "INFO"
# Return Medium by default
return "MEDIUM"