Detection rules › Panther
Panther rules: onelogin
OneLogin Active Login Activity
#Multiple user accounts logged in from the same ip address.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Lateral Movement |
Detection logic
from panther_base_helpers import is_ip_in_network
# Safelist for IP Subnets to ignore in this ruleset
# Each entry in the list should be in CIDR notation
# This should include any source ip addresses
# that are shared among users such as:
# proxy servers, the public corporate ip space,
# scanner ips etc
SHARED_IP_SPACE = [
"192.168.0.0/16",
]
def rule(event):
# Pre-filter: event_type_id = 5 is login events.
if (
str(event.get("event_type_id")) != "5"
or not event.get("ipaddr")
or not event.get("user_id")
):
return False
# We expect to see multiple user logins from these shared, common ip addresses
if is_ip_in_network(event.get("ipaddr"), SHARED_IP_SPACE):
return False
return True
def unique(event):
return str(event.get("user_id", ""))
def dedup(event):
return event.get("ipaddr", "<UNKNOWN_IP>")
def title(event):
return (
f"Unusual logins in OneLogin for multiple users from ip "
f"[{event.get('ipaddr', '<UNKNOWN_IP>')}]"
)
Rule specification
AnalysisType: rule
Filename: onelogin_active_login_activity.py
RuleID: "OneLogin.ActiveLoginActivity"
DisplayName: "OneLogin Active Login Activity"
Enabled: true
LogTypes:
- OneLogin.Events
Tags:
- OneLogin
- Lateral Movement:Use Alternate Authentication Material
Severity: Medium
Reports:
MITRE ATT&CK:
- TA0008:T1550
Threshold: 3
DedupPeriodMinutes: 720
Description: Multiple user accounts logged in from the same ip address.
Reference: https://support.onelogin.com/kb/4271392/user-policies
Runbook: Investigate whether multiple user's logging in from the same ip address is expected. Determine if this ip address should be added to the SHARED_IP_SPACE array.
SummaryAttributes:
- account_id
- user_name
- user_id
Stages and Predicates
Fires on OneLogin.Events events when all of the conditions below hold.
Condition
event_type_idis5ipaddris presentuser_idis present
This rule also runs imperative logic the parser cannot express as a filter. The conditions above are the structured part it could extract.
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
event_type_id | ne | 5 | excludes:event_type_id field:"event_type_id" value:"5" |
ipaddr | is_null | excludes:ipaddr | |
user_id | is_null | excludes:user_id |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field |
|---|
ipaddr |
Response runbook
Investigate whether multiple user's logging in from the same ip address is expected. Determine if this ip address should be added to the SHARED_IP_SPACE array.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"actor_user_id": 123456,
"actor_user_name": "Bob Cat",
"event_type_id": "5",
"ipaddr": "203.0.113.55",
"user_id": 123456,
"user_name": "Bob Cat"
}
OneLogin Authentication Factor Removed
#A user removed an authentication factor or otp device.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Persistence | |
| Defense Impairment | |
| Credential Access |
Detection logic
def rule(event):
# verify this is a auth factor being removed
# event id 24 is otp device deregistration
# event id 172 is a user deleted an authentication factor
return str(event.get("event_type_id")) == "24" or str(event.get("event_type_id")) == "172"
def dedup(event):
return event.get("user_name", "<UNKNOWN_USER>")
def title(event):
if str(event.get("event_type_id")) == "172":
return (
f"A user [{event.get('user_name', '<UNKNOWN_USER>')}] removed an authentication "
f"factor [{event.get('authentication_factor_description', '<UNKNOWN_AUTH_FACTOR>')}]"
)
return (
f"A user [{event.get('user_name', '<UNKNOWN_USER>')}] deactivated an otp device "
f"[{event.get('otp_device_name', '<UNKNOWN_OTP_DEVICE>'),}]"
)
Rule specification
AnalysisType: rule
Filename: onelogin_remove_authentication_factor.py
RuleID: "OneLogin.AuthFactorRemoved"
DisplayName: "OneLogin Authentication Factor Removed"
Enabled: true
LogTypes:
- OneLogin.Events
Tags:
- OneLogin
- Identity & Access Management
- Defense Evasion:Modify Authentication Process
Reports:
MITRE ATT&CK:
- TA0005:T1556
Severity: Low
Description: >
A user removed an authentication factor or otp device.
Reference: https://onelogin.service-now.com/kb_view_customer.do?sysparm_article=KB0010426
Runbook: >
Investigate whether this was an intentional action and if other multifactor devices exist.
SummaryAttributes:
- account_id
- event_type_id
- user_name
- user_id
- authentication_factor_description
- otp_device_name
Stages and Predicates
Fires on OneLogin.Events events when any of the conditions below holds.
Condition
any of:
event_type_idis24event_type_idis172
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event_type_id | eq |
| field:"event_type_id" kind:eq |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field |
|---|
user_name |
authentication_factor_description |
otp_device_name |
Response runbook
Investigate whether this was an intentional action and if other multifactor devices exist.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"actor_user_id": 123456,
"actor_user_name": "Bob Cat",
"authentication_factor_description": "2FA Name",
"event_type_id": "172",
"user_id": 123456,
"user_name": "Bob Cat"
}
OneLogin Failed High Risk Login
#A OneLogin attempt with a high risk factor (>50) resulted in a failed authentication.
Detection logic
def rule(event):
# check risk associated with this event
if event.get("risk_score", 0) > 50:
# a failed authentication attempt with high risk
return str(event.get("event_type_id")) == "6"
return False
def title(event):
return f"A user [{event.get('user_name', '<UNKNOWN_USER>')}] failed a high risk login attempt"
Rule specification
AnalysisType: rule
Filename: onelogin_high_risk_failed_login.py
RuleID: "OneLogin.HighRiskFailedLogin"
DisplayName: "OneLogin Failed High Risk Login"
Enabled: true
LogTypes:
- OneLogin.Events
Tags:
- OneLogin
Severity: Low
Description: A OneLogin attempt with a high risk factor (>50) resulted in a failed authentication.
Reference: https://resources.onelogin.com/OneLogin_RiskBasedAuthentication-WP-v5.pdf
Runbook: Investigate why this user login is tagged as high risk as well as whether this was caused by expected user activity.
SummaryAttributes:
- account_id
- user_name
- user_id
Stages and Predicates
Fires on OneLogin.Events events when all of the conditions below hold.
Condition
risk_scoreis greater than50event_type_idis6
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event_type_id | eq |
| field:"event_type_id" kind:eq value:"6" |
risk_score | gt |
| field:"risk_score" kind:gt value:"50" |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field |
|---|
user_name |
Response runbook
Investigate why this user login is tagged as high risk as well as whether this was caused by expected user activity.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"actor_user_id": 123456,
"actor_user_name": "Bob Cat",
"event_type_id": "6",
"risk_score": 55,
"user_id": 123456,
"user_name": "Bob Cat"
}
OneLogin High Risk Failed Login WITH Successful Login
#A OneLogin user successfully logged in after a failed high-risk login attempt.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Initial Access |
Rule specification
AnalysisType: correlation_rule
RuleID: "OneLogin.HighRiskFailedLogin.WITH.SuccessfulLogin"
DisplayName: "OneLogin High Risk Failed Login WITH Successful Login"
Enabled: false
Severity: Medium
Description: A OneLogin user successfully logged in after a failed high-risk login attempt.
Reference: https://resources.onelogin.com/OneLogin_RiskBasedAuthentication-WP-v5.pdf
Runbook: Investigate whether this was caused by expected user activity.
Reports:
MITRE ATT&CK:
- TA0001:T1078 # Valid Accounts
Detection:
- Group:
- ID: HighRiskFailedLogin
RuleID: OneLogin.HighRiskFailedLogin
- ID: SuccessfulLogin
RuleID: OneLogin.Login
MatchCriteria:
field_name:
- GroupID: HighRiskFailedLogin
Match: user_name
- GroupID: SuccessfulLogin
Match: user_name
LookbackWindowMinutes: 1800
Schedule:
RateMinutes: 1440
TimeoutMinutes: 5
Stages and Predicates
Fires when the steps below all occur within 30h, correlated by user_name. Each step needs one match unless a higher minimum is shown.
Stage 1: step HighRiskFailedLogin
References detection OneLogin Failed High Risk Login.
Stage 2: step SuccessfulLogin
References detection Signal - OneLogin Login.
Response runbook
Investigate whether this was caused by expected user activity.
OneLogin Multiple Accounts Deleted
#Possible Denial of Service detected. Threshold for user account deletions exceeded.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Impact |
Detection logic
def rule(event):
# filter events; event type 17 is a user deleted
return str(event.get("event_type_id")) == "17"
def title(event):
return (
f"User [{event.get('actor_user_name', '<UNKNOWN_USER>')}] "
f"has exceeded the user account deletion threshold"
)
Rule specification
AnalysisType: rule
Filename: onelogin_threshold_accounts_deleted.py
RuleID: "OneLogin.ThresholdAccountsDeleted"
DisplayName: "OneLogin Multiple Accounts Deleted"
Enabled: true
LogTypes:
- OneLogin.Events
Tags:
- OneLogin
- Impact:Account Access Removal
Severity: Medium
Reports:
MITRE ATT&CK:
- TA0040:T1531
Description: >
Possible Denial of Service detected. Threshold for user account deletions exceeded.
Threshold: 10
DedupPeriodMinutes: 10
Reference: https://en.wikipedia.org/wiki/Denial-of-service_attack
Runbook: Determine if this is normal user-cleanup activity.
SummaryAttributes:
- account_id
- user_name
- user_id
Stages and Predicates
Fires on OneLogin.Events events when the condition below holds.
Condition
event_type_idis17
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event_type_id | eq |
| field:"event_type_id" kind:eq value:"17" |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field |
|---|
actor_user_name |
Response runbook
Determine if this is normal user-cleanup activity.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"actor_user_id": 654321,
"actor_user_name": " Lion",
"event_type_id": "17",
"user_id": 123456,
"user_name": "Bob Cat"
}
OneLogin Multiple Accounts Modified
#Possible Denial of Service detected. Threshold for user account password changes exceeded.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Impact |
Detection logic
def rule(event):
# filter events; event type 11 is an actor_user changed user password
return str(event.get("event_type_id")) == "11"
def title(event):
return (
f"User [{event.get('actor_user_name', '<UNKNOWN_USER>')}] has exceeded the user"
f" account password change threshold"
)
Rule specification
AnalysisType: rule
Filename: onelogin_threshold_accounts_modified.py
RuleID: "OneLogin.ThresholdAccountsModified"
DisplayName: "OneLogin Multiple Accounts Modified"
Enabled: true
LogTypes:
- OneLogin.Events
Tags:
- OneLogin
- Impact:Account Access Removal
Severity: Medium
Reports:
MITRE ATT&CK:
- TA0040:T1531
Description: >
Possible Denial of Service detected. Threshold for user account password changes exceeded.
Threshold: 10
DedupPeriodMinutes: 10
Reference: https://en.wikipedia.org/wiki/Denial-of-service_attack
Runbook: Determine if this is normal user-cleanup activity.
SummaryAttributes:
- account_id
- user_name
- user_id
Stages and Predicates
Fires on OneLogin.Events events when the condition below holds.
Condition
event_type_idis11
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event_type_id | eq |
| field:"event_type_id" kind:eq value:"11" |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field |
|---|
actor_user_name |
Response runbook
Determine if this is normal user-cleanup activity.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"actor_user_id": 654321,
"actor_user_name": "Mountain Lion",
"event_type_id": "11",
"user_id": 123456,
"user_name": "Bob Cat"
}
OneLogin Password Access
#User accessed another user's application password
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Credential Access |
Detection logic
def rule(event):
# Filter events; event type 240 is actor_user revealed user's app password
if (
str(event.get("event_type_id")) != "240"
or not event.get("actor_user_id")
or not event.get("user_id")
):
return False
# Determine if actor_user accessed another user's password
return event.get("actor_user_id") != event.get("user_id")
def dedup(event):
return event.get("actor_user_name") + ":" + event.get("app_name", "<UNKNOWN_APP>")
def title(event):
return (
f"A user [{event.get('actor_user_name', '<UNKNOWN_USER>')}] accessed another user's "
f"[{event.get('user_name', '<UNKNOWN_USER>')}] "
f"[{event.get('app_name', '<UNKNOWN_APP>')}] password"
)
Rule specification
AnalysisType: rule
Filename: onelogin_password_accessed.py
RuleID: "OneLogin.PasswordAccess"
DisplayName: "OneLogin Password Access"
Enabled: true
LogTypes:
- OneLogin.Events
Tags:
- OneLogin
- Credential Access:Unsecured Credentials
Reports:
MITRE ATT&CK:
- TA0006:T1552
Severity: Medium
Description: >
User accessed another user's application password
Reference: https://onelogin.service-now.com/kb_view_customer.do?sysparm_article=KB0010598
Runbook: >
Investigate whether this was authorized access.
SummaryAttributes:
- account_id
- user_name
- user_id
Stages and Predicates
Fires on OneLogin.Events events when all of the conditions below hold.
Condition
event_type_idis240actor_user_idis presentuser_idis presentactor_user_iddiffers from fielduser_id
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
actor_user_id | is_null | excludes:actor_user_id | |
event_type_id | ne | 240 | excludes:event_type_id field:"event_type_id" value:"240" |
user_id | is_null | excludes:user_id |
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
actor_user_id | cross_field_compare |
| field:"actor_user_id" kind:cross_field_compare value:"user_id" |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field |
|---|
actor_user_name |
user_name |
app_name |
Response runbook
Investigate whether this was authorized access.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"actor_user_id": 654321,
"actor_user_name": "Mountain Lion",
"event_type_id": "240",
"user_id": 123456,
"user_name": "Bob Cat"
}
OneLogin User Assumed Another User
#User assumed another user account
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Lateral Movement |
Detection logic
def rule(event):
# check that this is a user assumption event; event id 3
return str(event.get("event_type_id")) == "3" and event.get(
"actor_user_id", "UNKNOWN_USER"
) != event.get("user_id", "UNKNOWN_USER")
def title(event):
return (
f"A user [{event.get('actor_user_name', '<UNKNOWN_USER>')}] assumed another user "
f"[{event.get('user_name', '<UNKNOWN_USER>')}] account"
)
Rule specification
AnalysisType: rule
Filename: onelogin_user_assumed.py
RuleID: "OneLogin.UserAssumption"
DisplayName: "OneLogin User Assumed Another User"
Enabled: true
LogTypes:
- OneLogin.Events
Tags:
- OneLogin
- Lateral Movement:Use Alternate Authentication Material
Reports:
MITRE ATT&CK:
- TA0008:T1550
Severity: Low
Description: User assumed another user account
Reference: https://onelogin.service-now.com/kb_view_customer.do?sysparm_article=KB0010594#:~:text=Prerequisites,Actions%20and%20select%20Assume%20User.
Runbook: >
Investigate whether this was authorized access.
SummaryAttributes:
- account_id
- user_name
- user_id
Stages and Predicates
Fires on OneLogin.Events events when all of the conditions below hold.
Condition
event_type_idis3actor_user_iddiffers from fielduser_id
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
actor_user_id | cross_field_compare |
| field:"actor_user_id" kind:cross_field_compare value:"user_id" |
event_type_id | eq |
| field:"event_type_id" kind:eq value:"3" |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field |
|---|
actor_user_name |
user_name |
Response runbook
Investigate whether this was authorized access.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"actor_user_id": 654321,
"actor_user_name": "Mountain Lion",
"event_type_id": "3",
"user_id": 123456,
"user_name": "Bob Cat"
}
OneLogin User Locked
#User locked or suspended from their account.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Credential Access |
Detection logic
def rule(event):
# check for a user locked event
# event 531 and 553 are user lock events via api
# event 551 is user suspended via api
return str(event.get("event_type_id")) in ["531", "553", "551"]
def title(event):
return (
f"A user [{event.get('user_name', '<UNKNOWN_USER>')}] was locked or suspended via api call"
)
Rule specification
AnalysisType: rule
Filename: onelogin_user_account_locked.py
RuleID: "OneLogin.UserAccountLocked"
DisplayName: "OneLogin User Locked"
Enabled: true
LogTypes:
- OneLogin.Events
Tags:
- OneLogin
- Credential Access:Brute Force
Reports:
MITRE ATT&CK:
- TA0006:T1110
Severity: Low
Description: >
User locked or suspended from their account.
Reference: https://onelogin.service-now.com/kb_view_customer.do?sysparm_article=KB0010420
Runbook: >
Investigate whether this was caused by expected action.
SummaryAttributes:
- account_id
- event_type_id
- user_name
- user_id
Stages and Predicates
Fires on OneLogin.Events events when the condition below holds.
Condition
event_type_idis one of531,553,551
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event_type_id | in |
| field:"event_type_id" kind:in |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field |
|---|
user_name |
Response runbook
Investigate whether this was caused by expected action.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"actor_user_id": 123456,
"actor_user_name": "Bob Cat",
"event_type_id": "531",
"user_id": 123456,
"user_name": "Bob Cat"
}
OneLogin User Password Changed
#A user password was updated.
Detection logic
def rule(event):
# check that this is a password change event;
# event id 11 is actor_user changed password for user
# Normally, admin's may change a user's password (event id 211)
return str(event.get("event_type_id")) == "11"
def title(event):
return (
f"A user [{event.get('user_name', '<UNKNOWN_USER>')}] password changed by user "
f"[{event.get('actor_user_name', '<UNKNOWN_USER>')}]"
)
Rule specification
AnalysisType: rule
Filename: onelogin_password_changed.py
RuleID: "OneLogin.PasswordChanged"
DisplayName: "OneLogin User Password Changed"
Enabled: true
LogTypes:
- OneLogin.Events
Tags:
- OneLogin
- Identity & Access Management
Severity: Info
Description: >
A user password was updated.
Reference: https://onelogin.service-now.com/kb_view_customer.do?sysparm_article=KB0010510
Runbook: >
Investigate whether this was an authorized action.
SummaryAttributes:
- account_id
- user_name
- user_id
Stages and Predicates
Fires on OneLogin.Events events when the condition below holds.
Condition
event_type_idis11
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event_type_id | eq |
| field:"event_type_id" kind:eq value:"11" |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field |
|---|
user_name |
actor_user_name |
Response runbook
Investigate whether this was an authorized action.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"actor_user_id": 123456,
"actor_user_name": "Bob Cat",
"event_type_id": "11",
"user_id": 123456,
"user_name": "Bob Cat"
}
Signal - OneLogin Login
#A OneLogin user successfully logged in.
Detection logic
def rule(event):
if str(event.get("event_type_id")) == "5":
return True
return False
def title(event):
return f"A user [{event.get('user_name', '<UNKNOWN_USER>')}] successfully logged in"
Rule specification
AnalysisType: rule
Filename: onelogin_login.py
RuleID: "OneLogin.Login"
DisplayName: "Signal - OneLogin Login"
Enabled: true
CreateAlert: false
LogTypes:
- OneLogin.Events
Tags:
- OneLogin
Severity: Info
Description: A OneLogin user successfully logged in.
Reference: https://resources.onelogin.com/OneLogin_RiskBasedAuthentication-WP-v5.pdf
Stages and Predicates
Fires on OneLogin.Events events when the condition below holds.
Condition
event_type_idis5
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event_type_id | eq |
| field:"event_type_id" kind:eq value:"5" |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field |
|---|
user_name |
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"actor_user_id": 123456,
"actor_user_name": "Bob Cat",
"event_type_id": "5",
"user_id": 123456,
"user_name": "Bob Cat"
}