Detection rules › Panther
Panther rules: box
Box Access Granted
#A user granted access to their box account to Box technical support from account settings.
Detection logic
def rule(event):
return event.get("event_type") == "ACCESS_GRANTED"
def title(event):
return (
f"User [{event.deep_get('created_by', 'name', default='<UNKNOWN_USER>')}] granted "
f"access to their account"
)
Rule specification
AnalysisType: rule
Filename: box_access_granted.py
RuleID: "Box.Access.Granted"
DisplayName: "Box Access Granted"
Enabled: true
LogTypes:
- Box.Event
Tags:
- Box
Severity: Low
Description: >
A user granted access to their box account to Box technical support from account settings.
Reference: https://support.box.com/hc/en-us/articles/7039943421715-Enabling-and-Disabling-Access-for-Box-Support
Runbook: >
Investigate whether the user purposefully granted access to their account.
SummaryAttributes:
- p_any_ip_addresses
Stages and Predicates
Fires on Box.Event events when the condition below holds.
Condition
event_typeisACCESS_GRANTED
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event_type | eq |
| field:"event_type" kind:eq value:"ACCESS_GRANTED" |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field | Source |
|---|---|
name | created_by.name |
Response runbook
Investigate whether the user purposefully granted access to their account.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"additional_details": "{\"key\": \"value\"}",
"created_by": {
"id": "12345678",
"login": "cat@example",
"name": "Bob Cat",
"type": "user"
},
"event_type": "ACCESS_GRANTED",
"source": {
"id": "12345678",
"login": "user@example",
"name": "Bob Cat",
"type": "user"
},
"type": "event"
}
Box Content Workflow Policy Violation
#A user violated the content workflow policy.
Detection logic
POLICY_VIOLATIONS = {
"CONTENT_WORKFLOW_UPLOAD_POLICY_VIOLATION",
"CONTENT_WORKFLOW_SHARING_POLICY_VIOLATION",
}
def rule(event):
return event.get("event_type") in POLICY_VIOLATIONS
def title(event):
return (
f"User [{event.deep_get('created_by', 'name', default='<UNKNOWN_USER>')}] "
f"violated a content workflow policy."
)
Rule specification
AnalysisType: rule
Filename: box_policy_violation.py
RuleID: "Box.Content.Workflow.Policy.Violation"
DisplayName: "Box Content Workflow Policy Violation"
Enabled: true
LogTypes:
- Box.Event
Tags:
- Box
Severity: Low
Description: >
A user violated the content workflow policy.
Reference: https://support.box.com/hc/en-us/articles/360043692594-Creating-a-Security-Policy
Runbook: >
Investigate whether the user continues to violate the policy and take measure to ensure they understand policy.
SummaryAttributes:
- event_type
Stages and Predicates
Fires on Box.Event events when the condition below holds.
Condition
event_typeis one ofCONTENT_WORKFLOW_UPLOAD_POLICY_VIOLATION,CONTENT_WORKFLOW_SHARING_POLICY_VIOLATION
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event_type | in |
| field:"event_type" kind:in |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field | Source |
|---|---|
name | created_by.name |
Response runbook
Investigate whether the user continues to violate the policy and take measure to ensure they understand policy.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"additional_details": "{\"key\": \"value\"}",
"created_by": {
"id": "12345678",
"login": "cat@example",
"name": "Bob Cat",
"type": "user"
},
"event_type": "CONTENT_WORKFLOW_UPLOAD_POLICY_VIOLATION",
"source": {
"id": "12345678",
"login": "user@example",
"type": "user"
},
"type": "event"
}
Box event triggered by unknown or external user
#An external user has triggered a box enterprise event.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Exfiltration |
Detection logic
DOMAINS = {
# "@example.com"
}
def rule(event):
# Check that all events are triggered by internal users
if event.get("event_type") not in ("FAILED_LOGIN", "SHIELD_ALERT"):
user = event.get("created_by", {})
# user id 2 indicates an anonymous user
if user.get("id", "") == "2":
return True
if DOMAINS:
return bool(
user.get("login") and not any(user.get("login", "").endswith(x) for x in DOMAINS)
)
return False
def title(event):
return (
f"External user [{event.deep_get('created_by', 'login', default='<UNKNOWN_USER>')}] "
f"triggered a box event."
)
Rule specification
AnalysisType: rule
Filename: box_event_triggered_externally.py
RuleID: "Box.Event.Triggered.Externally"
DisplayName: "Box event triggered by unknown or external user"
Enabled: false
LogTypes:
- Box.Event
Tags:
- Box
- Exfiltration:Exfiltration Over Web Service
- Configuration Required
Reports:
MITRE ATT&CK:
- TA0010:T1567
Severity: Medium
Description: >
An external user has triggered a box enterprise event.
Reference: https://support.box.com/hc/en-us/articles/8391393127955-Using-the-Enterprise-Event-Stream
Runbook: >
Investigate whether this user's activity is expected.
SummaryAttributes:
- ip_address
Threshold: 10
DedupPeriodMinutes: 60
Stages and Predicates
Fires on Box.Event events when all of the conditions below hold.
Condition
event_typeis not one ofFAILED_LOGIN,SHIELD_ALERTany of:
created_by.idis2created_by.loginis 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 | in | FAILED_LOGIN, SHIELD_ALERT | excludes:event_type field:"event_type" value:"FAILED_LOGIN" field:"event_type" value:"SHIELD_ALERT" |
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
created_by.id | eq |
| field:"created_by.id" kind:eq value:"2" |
created_by.login | is_not_null | field:"created_by.login" kind:is_not_null |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field | Source |
|---|---|
login | created_by.login |
Response runbook
Investigate whether this user's activity is expected.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"created_by": {
"id": "2",
"name": "Unknown User",
"type": "user"
},
"event_type": "PREVIEW",
"ip_address": "1.2.3.4",
"type": "event"
}
Box Large Number of Downloads
#A user has exceeded the threshold for number of downloads within a single time frame.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Exfiltration |
Detection logic
def rule(event):
return event.get("event_type") == "DOWNLOAD"
def title(event):
return (
f"User [{event.deep_get('created_by', 'login', default='<UNKNOWN_USER>')}] "
f"exceeded threshold for number of downloads in the configured time frame."
)
Rule specification
AnalysisType: rule
Filename: box_user_downloads.py
RuleID: "Box.Large.Number.Downloads"
DisplayName: "Box Large Number of Downloads"
Enabled: true
LogTypes:
- Box.Event
Tags:
- Box
- Exfiltration:Exfiltration Over Web Service
Reports:
MITRE ATT&CK:
- TA0010:T1567
Severity: Low
Description: >
A user has exceeded the threshold for number of downloads within a single time frame.
Reference: https://support.box.com/hc/en-us/articles/360043697134-Download-Files-and-Folders-from-Box
Runbook: >
Investigate whether this user's download activity is expected. Investigate the cause of this download activity.
SummaryAttributes:
- ip_address
Threshold: 100
DedupPeriodMinutes: 60
Stages and Predicates
Fires on Box.Event events when the condition below holds.
Condition
event_typeisDOWNLOAD
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event_type | eq |
| field:"event_type" kind:eq value:"DOWNLOAD" |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field | Source |
|---|---|
login | created_by.login |
Response runbook
Investigate whether this user's download activity is expected. Investigate the cause of this download activity.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"additional_details": "{\"key\": \"value\"}",
"created_by": {
"id": "12345678",
"login": "cat@example",
"name": "Bob Cat",
"type": "user"
},
"event_type": "DOWNLOAD",
"source": {
"id": "12345678",
"login": "user@example",
"name": "Bob Cat",
"type": "user"
},
"type": "event"
}
Box Large Number of Permission Changes
#A user has exceeded the threshold for number of folder permission changes within a single time frame.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Privilege Escalation |
Detection logic
PERMISSION_UPDATE_EVENT_TYPES = {
"CHANGE_FOLDER_PERMISSION",
"ITEM_SHARED_CREATE",
"ITEM_SHARED",
"SHARE",
}
def rule(event):
return event.get("event_type") in PERMISSION_UPDATE_EVENT_TYPES
def title(event):
return (
f"User [{event.deep_get('created_by', 'login', default='<UNKNOWN_USER>')}]"
f" exceeded threshold for number of permission changes in the configured time frame."
)
Rule specification
AnalysisType: rule
Filename: box_user_permission_updates.py
RuleID: "Box.Large.Number.Permission.Updates"
DisplayName: "Box Large Number of Permission Changes"
Enabled: true
LogTypes:
- Box.Event
Tags:
- Box
- Privilege Escalation:Abuse Elevation Control Mechanism
Reports:
MITRE ATT&CK:
- TA0004:T1548
Severity: Low
Description: >
A user has exceeded the threshold for number of folder permission changes within a single time frame.
Reference: https://support.box.com/hc/en-us/articles/360043697254-Understanding-Folder-Permissions
Runbook: >
Investigate whether this user's activity is expected.
SummaryAttributes:
- ip_address
Threshold: 100
DedupPeriodMinutes: 60
Stages and Predicates
Fires on Box.Event events when the condition below holds.
Condition
event_typeis one ofCHANGE_FOLDER_PERMISSION,ITEM_SHARED_CREATE,ITEM_SHARED,SHARE
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event_type | in |
| field:"event_type" kind:in |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field | Source |
|---|---|
login | created_by.login |
Response runbook
Investigate whether this user's activity is expected.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"additional_details": "{\"key\": \"value\"}",
"created_by": {
"id": "12345678",
"login": "cat@example",
"name": "Bob Cat",
"type": "user"
},
"event_type": "CHANGE_FOLDER_PERMISSION",
"source": {
"id": "12345678",
"login": "user@example",
"name": "Bob Cat",
"type": "user"
},
"type": "event"
}
Box New Login
#A user logged in from a new device.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Initial Access |
Detection logic
def rule(event):
# ADD_LOGIN_ACTIVITY_DEVICE
# detect when a user logs in from a device not previously seen
return event.get("event_type") == "ADD_LOGIN_ACTIVITY_DEVICE"
def title(event):
return (
f"User [{event.deep_get('created_by', 'name', default='<UNKNOWN_USER>')}] "
f"logged in from a new device."
)
Rule specification
AnalysisType: rule
Filename: box_new_login.py
RuleID: "Box.New.Login"
DisplayName: "Box New Login"
Enabled: true
LogTypes:
- Box.Event
Tags:
- Box
- Initial Access:Valid Accounts
Reports:
MITRE ATT&CK:
- TA0001:T1078
Severity: Info
CreateAlert: false
Description: >
A user logged in from a new device.
Reference: https://support.box.com/hc/en-us/articles/360043691914-Controlling-Devices-Used-to-Access-Box
Runbook: >
Investigate whether this is a valid user login.
SummaryAttributes:
- ip_address
Stages and Predicates
Fires on Box.Event events when the condition below holds.
Condition
event_typeisADD_LOGIN_ACTIVITY_DEVICE
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event_type | eq |
| field:"event_type" kind:eq value:"ADD_LOGIN_ACTIVITY_DEVICE" |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field | Source |
|---|---|
name | created_by.name |
Response runbook
Investigate whether this is a valid user login.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"additional_details": "{\"key\": \"value\"}",
"created_by": {
"id": "12345678",
"login": "cat@example",
"name": "Bob Cat",
"type": "user"
},
"event_type": "ADD_LOGIN_ACTIVITY_DEVICE",
"source": {
"id": "12345678",
"login": "user@example",
"type": "user"
},
"type": "event"
}
Box Shield Detected Anomalous Download Activity
#A user's download activity has altered significantly.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Exfiltration |
Detection logic
from panther_base_helpers import deep_get
from panther_box_helpers import box_parse_additional_details
def rule(event):
if event.get("event_type") != "SHIELD_ALERT":
return False
alert_details = box_parse_additional_details(event).get("shield_alert", {})
if alert_details.get("rule_category", "") == "Anomalous Download":
if alert_details.get("risk_score", 0) > 50:
return True
return False
def title(event):
details = box_parse_additional_details(event)
description = deep_get(details, "shield_alert", "alert_summary", "description")
if description:
return description
return (
f"Anomalous download activity triggered by user "
f"[{event.deep_get('created_by', 'name', default='<UNKNOWN_USER>')}]."
)
Rule specification
AnalysisType: rule
Filename: box_anomalous_download.py
RuleID: "Box.Shield.Anomalous.Download"
DisplayName: "Box Shield Detected Anomalous Download Activity"
Enabled: true
LogTypes:
- Box.Event
Tags:
- Box
- Exfiltration:Exfiltration Over Web Service
Reports:
MITRE ATT&CK:
- TA0010:T1567
Severity: High
Description: >
A user's download activity has altered significantly.
Reference: https://developer.box.com/guides/events/shield-alert-events/
Runbook: >
Investigate whether this was triggered by expected user download activity.
SummaryAttributes:
- event_type
- ip_address
Stages and Predicates
Fires on Box.Event events when the condition below holds.
Condition
event_typeisSHIELD_ALERT
This rule also runs imperative logic the parser cannot express as a filter. The conditions above are the structured part it could extract.
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event_type | eq |
| field:"event_type" kind:eq value:"SHIELD_ALERT" |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field | Source |
|---|---|
name | created_by.name |
Response runbook
Investigate whether this was triggered by expected user download activity.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"additional_details": "{\"shield_alert\":{\"rule_category\":\"Anomalous Download\",\"risk_score\":77,\"alert_summary\":{\"description\":\"Significant increase in download content week over week, 9999% (50.00 MB) more than last week.\"}}}",
"created_by": {
"id": "12345678",
"login": "bob@example",
"name": "Bob Cat",
"type": "user"
},
"event_type": "SHIELD_ALERT",
"source": {
"id": "12345678",
"login": "bob@example",
"name": "Bob Cat",
"type": "user"
},
"type": "event"
}
Box Shield Suspicious Alert Triggered
#A user login event or session event was tagged as medium to high severity by Box Shield.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Initial Access |
Detection logic
from panther_base_helpers import deep_get
from panther_box_helpers import box_parse_additional_details
SUSPICIOUS_EVENT_TYPES = {
"Suspicious Locations",
"Suspicious Sessions",
}
def rule(event):
if event.get("event_type") != "SHIELD_ALERT":
return False
alert_details = box_parse_additional_details(event).get("shield_alert", {})
if alert_details.get("rule_category", "") in SUSPICIOUS_EVENT_TYPES:
if alert_details.get("risk_score", 0) > 50:
return True
return False
def title(event):
details = box_parse_additional_details(event)
description = deep_get(details, "shield_alert", "alert_summary", "description", default="")
if description:
return description
return (
f"Shield medium to high risk, suspicious event alert triggered for user "
f"[{deep_get(details, 'shield_alert', 'user', 'email', default='<UNKNOWN_USER>')}]"
)
Rule specification
AnalysisType: rule
Filename: box_suspicious_login_or_session.py
RuleID: "Box.Shield.Suspicious.Alert"
DisplayName: "Box Shield Suspicious Alert Triggered"
Enabled: true
LogTypes:
- Box.Event
Tags:
- Box
- Initial Access:Valid Accounts
Reports:
MITRE ATT&CK:
- TA0001:T1078
Severity: High
Description: >
A user login event or session event was tagged as medium to high severity by Box Shield.
Reference: https://developer.box.com/guides/events/shield-alert-events/
Runbook: >
Investigate whether this was triggered by an expected user event.
SummaryAttributes:
- event_type
- ip_address
Stages and Predicates
Fires on Box.Event events when the condition below holds.
Condition
event_typeisSHIELD_ALERT
This rule also runs imperative logic the parser cannot express as a filter. The conditions above are the structured part it could extract.
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event_type | eq |
| field:"event_type" kind:eq value:"SHIELD_ALERT" |
Response runbook
Investigate whether this was triggered by an expected user event.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"additional_details": "{\"shield_alert\":{\"rule_category\":\"Suspicious Locations\",\"risk_score\":60,\"user\":{\"email\":\"bob@example\"}}}",
"created_by": {
"id": "12345678",
"login": "bob@example",
"name": "Bob Cat",
"type": "user"
},
"event_type": "SHIELD_ALERT",
"source": {
"id": "12345678",
"type": "user"
},
"type": "event"
}
Box Untrusted Device Login
#A user attempted to login from an untrusted device.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Initial Access |
Detection logic
def rule(event):
# DEVICE_TRUST_CHECK_FAILED
# detect when a user attempts to login from an untrusted device
return event.get("event_type") == "DEVICE_TRUST_CHECK_FAILED"
def title(event):
return (
f"User [{event.deep_get('created_by', 'name', default='<UNKNOWN_USER>')}] "
f"attempted to login from an untrusted device."
)
Rule specification
AnalysisType: rule
Filename: box_untrusted_device.py
RuleID: "Box.Untrusted.Device"
DisplayName: "Box Untrusted Device Login"
Enabled: true
LogTypes:
- Box.Event
Tags:
- Box
- Initial Access:Valid Accounts
Reports:
MITRE ATT&CK:
- TA0001:T1078
Severity: Info
CreateAlert: false
Description: >
A user attempted to login from an untrusted device.
Reference: https://support.box.com/hc/en-us/articles/360044194993-Setting-Up-Device-Trust-Security-Requirements
Runbook: >
Investigate whether this is a valid user attempting to login to box.
SummaryAttributes:
- ip_address
Stages and Predicates
Fires on Box.Event events when the condition below holds.
Condition
event_typeisDEVICE_TRUST_CHECK_FAILED
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event_type | eq |
| field:"event_type" kind:eq value:"DEVICE_TRUST_CHECK_FAILED" |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field | Source |
|---|---|
name | created_by.name |
Response runbook
Investigate whether this is a valid user attempting to login to box.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"additional_details": "{\"key\": \"value\"}",
"created_by": {
"id": "12345678",
"login": "cat@example",
"name": "Bob Cat",
"type": "user"
},
"event_type": "DEVICE_TRUST_CHECK_FAILED",
"source": {
"id": "12345678",
"login": "user@example",
"type": "user"
},
"type": "event"
}
Malicious Content Detected
#Box has detect malicious content, such as a virus.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Execution |
Detection logic
from panther_base_helpers import deep_get
from panther_box_helpers import box_parse_additional_details
def rule(event):
# enterprise malicious file alert event
if event.get("event_type") == "FILE_MARKED_MALICIOUS":
return True
# Box Shield will also alert on malicious content
if event.get("event_type") != "SHIELD_ALERT":
return False
alert_details = box_parse_additional_details(event).get("shield_alert", {})
if alert_details.get("rule_category", "") == "Malicious Content":
if alert_details.get("risk_score", 0) > 50:
return True
return False
def title(event):
if event.get("event_type") == "FILE_MARKED_MALICIOUS":
return (
f"File [{event.deep_get('source', 'item_name', default='<UNKNOWN_FILE>')}], owned by "
f"[{event.deep_get('source', 'owned_by', 'login', default='<UNKNOWN_USER>')}], "
f"was marked malicious."
)
alert_details = box_parse_additional_details(event).get("shield_alert", {})
# pylint: disable=line-too-long
return (
f"File [{deep_get(alert_details, 'user', 'email', default='<UNKNOWN_USER>')}], owned by "
f"[{deep_get(alert_details, 'alert_summary', 'upload_activity', 'item_name', default='<UNKNOWN_FILE>')}], "
f"was marked malicious."
)
Rule specification
AnalysisType: rule
Filename: box_malicious_content.py
RuleID: "Box.Malicious.Content"
DisplayName: "Malicious Content Detected"
Enabled: true
LogTypes:
- Box.Event
Tags:
- Box
- Execution:User Execution
Reports:
MITRE ATT&CK:
- TA0002:T1204
Severity: High
Description: >
Box has detect malicious content, such as a virus.
Reference: >
https://developer.box.com/guides/events/shield-alert-events/
Runbook: >
Investigate whether this is a false positive or if the virus needs to be contained appropriately.
SummaryAttributes:
- event_type
Stages and Predicates
Fires on Box.Event events when any of the conditions below holds.
Condition
any of:
event_typeisFILE_MARKED_MALICIOUSevent_typeisSHIELD_ALERT
This rule also runs imperative logic the parser cannot express as a filter. The conditions above are the structured part it could extract.
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event_type | eq |
| field:"event_type" kind:eq |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field | Source |
|---|---|
item_name | source.item_name |
login | source.owned_by.login |
Response runbook
Investigate whether this is a false positive or if the virus needs to be contained appropriately.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"additional_details": "{\"key\": \"value\"}",
"created_by": {
"id": "12345678",
"login": "cat@example",
"name": "Bob Cat",
"type": "user"
},
"event_type": "FILE_MARKED_MALICIOUS",
"source": {
"item_id": "123456789012",
"item_name": "bad_file.pdf",
"item_type": "file",
"owned_by": {
"id": "12345678",
"login": "cat@example",
"name": "Bob",
"type": "user"
},
"parent": {
"etag": "1",
"id": "12345",
"name": "Parent_Folder",
"sequence_id": "2",
"type": "folder"
}
},
"type": "event"
}