Detection rules › Panther
Panther rules: zoom
Zoom All Meetings Secured With One Option Disabled
#A Zoom User turned off your organization's requirement that all meetings are secured with one security option.
Detection logic
def rule(event):
operation_detail = event.get("operation_detail", "<NO_OPS_DETAIL>")
operation_flag = (
"Require that all meetings are secured with one security option: from On to Off"
)
return (
event.get("action", "<NO_ACTION>") == "Update"
and event.get("category_type", "<NO_CATEGORY_TYPE>") == "Account"
and operation_flag in operation_detail
)
def title(event):
return (
f"Zoom User [{event.get('operator', '<NO_OPERATOR>')}] turned off your organization's "
f"requirement to secure all meetings with one security option."
)
Rule specification
AnalysisType: rule
Description: A Zoom User turned off your organization's requirement that all meetings are secured with one security option.
DisplayName: "Zoom All Meetings Secured With One Option Disabled"
Enabled: true
Filename: zoom_all_meetings_secured_with_one_option_disabled.py
Runbook: Confirm this user acted with valid business intent and determine whether this activity was authorized.
Reference: https://support.zoom.com/hc/en/article?id=zm_kb&sysparm_article=KB0059862
Severity: Medium
DedupPeriodMinutes: 60
LogTypes:
- Zoom.Operation
RuleID: "Zoom.All.Meetings.Secured.With.One.Option.Disabled"
Threshold: 1
Stages and Predicates
Fires on Zoom.Operation events when all of the conditions below hold.
Condition
actionisUpdatecategory_typeisAccountoperation_detailcontainsRequire that all meetings are secured with one security option: from On to Off
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
action | eq |
| field:"action" kind:eq value:"Update" |
category_type | eq |
| field:"category_type" kind:eq value:"Account" |
operation_detail | contains |
| field:"operation_detail" kind:contains value:"Require that all meetings are secured with one security option: from On to Off" |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field |
|---|
operator |
Response runbook
Confirm this user acted with valid business intent and determine whether this activity was authorized.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"action": "Update",
"category_type": "Account",
"operation_detail": "Security - Require that all meetings are secured with one security option: from On to Off",
"operator": "example@example.io",
"time": "2022-12-16 18:15:38"
}
Zoom Automatic Sign Out Disabled
#A Zoom User turned off your organization's setting to automatically sign users out after a specified period of time.
Detection logic
def rule(event):
operation_detail = event.get("operation_detail", "<NO_OPS_DETAIL>")
operation_flag = "Automatically sign users out after a specified time: from On to Off"
return (
event.get("action", "<NO_ACTION>") == "Update"
and event.get("category_type", "<NO_CATEGORY_TYPE>") == "Account"
and operation_flag in operation_detail
)
def title(event):
return (
f"Zoom User [{event.get('operator', '<NO_OPERATOR>')}] turned off your organization's "
f"setting to automatically sign users out after a specified time."
)
Rule specification
AnalysisType: rule
Description: A Zoom User turned off your organization's setting to automatically sign users out after a specified period of time.
DisplayName: "Zoom Automatic Sign Out Disabled"
Enabled: true
Filename: zoom_automatic_sign_out_disabled.py
Reference: https://support.zoom.us/hc/en-us/articles/115005756143-Changing-account-security-settings#:~:text=Users%20need%20to%20sign%20in,of%205%20to%20120%20minutes
Runbook: Confirm this user acted with valid business intent and determine whether this activity was authorized.
Severity: Medium
DedupPeriodMinutes: 60
LogTypes:
- Zoom.Operation
RuleID: "Zoom.Automatic.Sign.Out.Disabled"
Threshold: 1
Stages and Predicates
Fires on Zoom.Operation events when all of the conditions below hold.
Condition
actionisUpdatecategory_typeisAccountoperation_detailcontainsAutomatically sign users out after a specified time: from On to Off
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
action | eq |
| field:"action" kind:eq value:"Update" |
category_type | eq |
| field:"category_type" kind:eq value:"Account" |
operation_detail | contains |
| field:"operation_detail" kind:contains value:"Automatically sign users out after a specified time: from On to Off" |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field |
|---|
operator |
Response runbook
Confirm this user acted with valid business intent and determine whether this activity was authorized.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"action": "Update",
"category_type": "Account",
"operation_detail": "Security - Automatically sign users out after a specified time: from On to Off",
"operator": "example@example.io",
"time": "2022-12-16 18:20:42"
}
Zoom Meeting Passcode Disabled
#Meeting passcode requirement has been disabled from usergroup
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Collection |
Detection logic
from panther_zoom_helpers import get_zoom_usergroup_context as get_context
def rule(event):
if event.get("category_type") != "User Group":
return False
context = get_context(event)
changed = "Passcode" in context.get("Change", "")
disabled = context.get("DisabledSetting", False)
return changed and disabled
def title(event):
context = get_context(event)
return f"Group {context['GroupName']} passcode requirement disabled by {event.get('operator')}"
Rule specification
AnalysisType: rule
Filename: zoom_operation_passcode_disabled.py
RuleID: "Zoom.PasscodeDisabled"
DisplayName: "Zoom Meeting Passcode Disabled"
Enabled: true
LogTypes:
- Zoom.Operation
Tags:
- Zoom
- Collection:Video Capture
Severity: Low
Description: >
Meeting passcode requirement has been disabled from usergroup
Reports:
MITRE ATT&CK:
- TA0009:T1125
Reference: https://support.zoom.us/hc/en-us/articles/360033559832-Zoom-Meeting-and-Webinar-passcodes
Runbook: >
Follow up with user or Zoom admin to ensure this meeting room's use case does not allow a passcode.
SummaryAttributes:
- p_any_emails
Stages and Predicates
Fires on Zoom.Operation events when the condition below holds.
Condition
category_typeisUser Group
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 |
|---|---|---|---|
category_type | eq |
| field:"category_type" kind:eq value:"User Group" |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field |
|---|
operator |
Response runbook
Follow up with user or Zoom admin to ensure this meeting room's use case does not allow a passcode.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"action": "Update",
"category_type": "User Group",
"operation_detail": "Edit Group Springfield - Personal Meeting ID (PMI) Passcode: from On to Off",
"operator": "homer@panther.io",
"p_log_type": "Zoom.Operation",
"time": "2021-11-17 00:37:24Z"
}
Zoom New Meeting Passcode Required Disabled
#A Zoom User turned off your organization's setting to require passcodes for new meetings.
Detection logic
def rule(event):
operation_detail = event.get("operation_detail", "<NO_OPS_DETAIL>")
operation_flag = "Security - Require a passcode when scheduling new meetings: from On to Off"
return all(
[
event.get("action", "<NO_ACTION>") == "Update",
event.get("category_type", "<NO_CATEGORY_TYPE>") == "Account",
operation_flag == operation_detail,
]
)
def title(event):
return (
f"Zoom User [{event.get('operator', '<NO_OPERATOR>')}] turned off your organization's "
f"setting to require passcodes for new meetings."
)
Rule specification
AnalysisType: rule
Description: A Zoom User turned off your organization's setting to require passcodes for new meetings.
DisplayName: "Zoom New Meeting Passcode Required Disabled"
Enabled: true
Filename: zoom_new_meeting_passcode_required_disabled.py
Runbook: Confirm this user acted with valid business intent and determine whether this activity was authorized.
Reference: https://support.zoom.com/hc/en/article?id=zm_kb&sysparm_article=KB0063160#:~:text=Since%20September%202022%2C%20Zoom%20requires,enforced%20for%20all%20free%20accounts
Severity: Medium
DedupPeriodMinutes: 60
LogTypes:
- Zoom.Operation
RuleID: "Zoom.New.Meeting.Passcode.Required.Disabled"
Threshold: 1
Stages and Predicates
Fires on Zoom.Operation events when all of the conditions below hold.
Condition
actionisUpdatecategory_typeisAccountoperation_detailisSecurity - Require a passcode when scheduling new meetings: from On to Off
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
action | eq |
| field:"action" kind:eq value:"Update" |
category_type | eq |
| field:"category_type" kind:eq value:"Account" |
operation_detail | eq |
| field:"operation_detail" kind:eq value:"Security - Require a passcode when scheduling new meetings: from On to Off" |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field |
|---|
operator |
Response runbook
Confirm this user acted with valid business intent and determine whether this activity was authorized.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"action": "Update",
"category_type": "Account",
"operation_detail": "Security - Require a passcode when scheduling new meetings: from On to Off",
"operator": "example@example.io",
"time": "2022-12-16 18:22:17"
}
Zoom Sign In Method Modified
#A Zoom User modified your organizations sign in method.
Detection logic
def rule(event):
operation_detail = event.get("operation_detail", "<NO_OPS_DETAIL>")
operation_flag = "Sign-in Methods - Allow users to sign in with "
setting_flag = "from Off to On"
return all(
[
event.get("action", "<NO_ACTION>") == "Update",
event.get("category_type", "<NO_CATEGORY_TYPE>") == "Account",
operation_detail.startswith(operation_flag),
operation_detail.endswith(setting_flag),
]
)
def title(event):
# string manipulation to grab service that allows sign-in from the operation detail
# and clean it up a bit
service_detail = ""
operation_detail = event.get("operation_detail", "<NO_OPS_DETAIL>")
operation_flag = "Sign-in Methods - Allow users to sign in with "
setting_flag = "from Off to On"
if operation_detail.startswith(operation_flag) and operation_detail.endswith(setting_flag):
service_detail = (
event.get("operation_detail", "<NO_OPS_DETAIL>").split("with")[1].split(":")[0].strip()
)
return (
f"Zoom User [{event.get('operator', '<NO_OPERATOR>')}] modified your organization's "
f"sign in methods to allow users to sign in with [{service_detail}]."
)
Rule specification
AnalysisType: rule
Description: A Zoom User modified your organizations sign in method.
DisplayName: "Zoom Sign In Method Modified"
Enabled: true
Filename: zoom_sign_in_method_modified.py
Runbook: Confirm this user acted with valid business intent and determine whether this activity was authorized.
Reference: https://support.zoom.com/hc/en/article?id=zm_kb&sysparm_article=KB0067602#:~:text=Go%20to%20the%20Zoom%20site,click%20Link%20and%20Sign%20In
Severity: Medium
DedupPeriodMinutes: 60
LogTypes:
- Zoom.Operation
RuleID: "Zoom.Sign.In.Method.Modified"
Threshold: 1
Stages and Predicates
Fires on Zoom.Operation events when all of the conditions below hold.
Condition
actionisUpdatecategory_typeisAccountoperation_detailstarts with"Sign-in Methods - Allow users to sign in with "operation_detailends withfrom Off to On
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
action | eq |
| field:"action" kind:eq value:"Update" |
category_type | eq |
| field:"category_type" kind:eq value:"Account" |
operation_detail | ends_with |
| field:"operation_detail" kind:ends_with value:"from Off to On" |
operation_detail | starts_with |
| field:"operation_detail" kind:starts_with value:"Sign-in Methods - Allow users to sign in with " |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field |
|---|
operator |
Response runbook
Confirm this user acted with valid business intent and determine whether this activity was authorized.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"action": "Update",
"category_type": "Account",
"operation_detail": "Sign-in Methods - Allow users to sign in with Google: from Off to On",
"operator": "example@example.io",
"time": "2022-12-16 18:20:07"
}
Zoom Sign In Requirements Changed
#A Zoom User changed your organization's sign in requirements.
Detection logic
def rule(event):
operation_detail = event.get("operation_detail", "<NO_OPS_DETAIL>")
operation_flag_one = "Sign-In Password Requirement"
operation_flag_two = "On to Off"
return all(
[
event.get("action", "<NO_ACTION>") == "Update",
event.get("category_type", "<NO_CATEGORY_TYPE>") == "Account",
operation_flag_one in operation_detail,
operation_flag_two in operation_detail,
]
)
def title(event):
return (
f"Zoom User [{event.get('operator', '<NO_OPERATOR>')}] changed your organization's "
f"sign in requirements [{event.get('operation_detail', '<NO_OPS_DETAIL>')}]."
)
Rule specification
AnalysisType: rule
Description: "A Zoom User changed your organization's sign in requirements. "
DisplayName: "Zoom Sign In Requirements Changed"
Enabled: true
Filename: zoom_sign_in_requirements_changed.py
Runbook: Confirm this user acted with valid business intent and determine whether this activity was authorized.
Reference: https://support.zoom.com/hc/en/article?id=zm_kb&sysparm_article=KB0061263
Severity: Medium
DedupPeriodMinutes: 60
LogTypes:
- Zoom.Operation
RuleID: "Zoom.Sign.In.Requirements.Changed"
SummaryAttributes:
- operation_detail
Threshold: 1
Stages and Predicates
Fires on Zoom.Operation events when all of the conditions below hold.
Condition
actionisUpdatecategory_typeisAccountoperation_detailcontainsSign-In Password Requirementoperation_detailcontainsOn to Off
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
action | eq |
| field:"action" kind:eq value:"Update" |
category_type | eq |
| field:"category_type" kind:eq value:"Account" |
operation_detail | contains |
| field:"operation_detail" kind:contains |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field |
|---|
operator |
operation_detail |
Response runbook
Confirm this user acted with valid business intent and determine whether this activity was authorized.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"action": "Update",
"category_type": "Account",
"operation_detail": "Sign-In Password Requirement - Include at least 1 letter: from On to Off - Include at least 1 number: from On to Off - Include both uppercase and lowercase characters: from On to Off",
"operator": "example@example.io",
"time": "2022-12-16 18:21:29"
}
Zoom Two Factor Authentication Disabled
#A Zoom User disabled your organization's setting to sign in with Two-Factor Authentication.
Detection logic
def rule(event):
operation_detail = event.get("operation_detail", "<NO_OPS_DETAIL>")
operation_flag = "Security - Sign in with Two-Factor Authentication: from On to Off"
return all(
[
event.get("action", "<NO_ACTION>") == "Update",
event.get("category_type", "<NO_CATEGORY_TYPE>") == "Account",
operation_detail == operation_flag,
]
)
def title(event):
return (
f"Zoom User [{event.get('operator', '<NO_OPERATOR>')}] disabled your organization's "
f"setting to sign in with Two-Factor Authentication."
)
Rule specification
AnalysisType: rule
Description: A Zoom User disabled your organization's setting to sign in with Two-Factor Authentication.
DisplayName: "Zoom Two Factor Authentication Disabled"
Enabled: true
Filename: zoom_two_factor_authentication_disabled.py
Runbook: Confirm this user acted with valid business intent and determine whether this activity was authorized.
Reference: https://support.zoom.com/hc/en/article?id=zm_kb&sysparm_article=KB0066054
Severity: Medium
DedupPeriodMinutes: 60
LogTypes:
- Zoom.Operation
RuleID: "Zoom.Two.Factor.Authentication.Disabled"
Threshold: 1
Stages and Predicates
Fires on Zoom.Operation events when all of the conditions below hold.
Condition
actionisUpdatecategory_typeisAccountoperation_detailisSecurity - Sign in with Two-Factor Authentication: from On to Off
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
action | eq |
| field:"action" kind:eq value:"Update" |
category_type | eq |
| field:"category_type" kind:eq value:"Account" |
operation_detail | eq |
| field:"operation_detail" kind:eq value:"Security - Sign in with Two-Factor Authentication: from On to Off" |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field |
|---|
operator |
Response runbook
Confirm this user acted with valid business intent and determine whether this activity was authorized.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"action": "Update",
"category_type": "Account",
"operation_detail": "Security - Sign in with Two-Factor Authentication: from On to Off",
"operator": "example@example.io",
"time": "2022-12-16 18:20:35"
}
Zoom User Promoted to Privileged Role
#A Zoom user was promoted to a privileged role.
Detection logic
import re
from panther_base_helpers import EMAIL_REGEX
PRIVILEGED_ROLES = ("Admin", "Co-Owner", "Owner", "Billing Admin")
def extract_values(event):
operator = event.get("operator", "<operator-not-found>")
operation_detail = event.get("operation_detail", "")
email = re.search(EMAIL_REGEX, operation_detail)[0] or "<email-not-found>"
fromto = re.findall(r"from ([-\s\w]+) to ([-\s\w]+)", operation_detail) or [
("<from-role-not-found>", "<to-role-not-found>")
]
from_role, to_role = fromto[0] or ("<role-not-found>", "<role-not-found>")
return operator, email, from_role, to_role
def rule(event):
if (
"Update" in event.get("action", "")
and event.get("category_type") == "User"
and event.get("operation_detail", "").startswith("Change Role")
):
_, _, from_role, to_role = extract_values(event)
return to_role in PRIVILEGED_ROLES and from_role not in PRIVILEGED_ROLES
return False
def title(event):
operator, email, from_role, to_role = extract_values(event)
return (
f"Zoom: [{email}]'s role was changed from [{from_role}] " f"to [{to_role}] by [{operator}]."
)
Rule specification
AnalysisType: rule
Description: A Zoom user was promoted to a privileged role.
DisplayName: "Zoom User Promoted to Privileged Role"
Enabled: true
Filename: zoom_user_promoted_to_privileged_role.py
Reference: https://support.zoom.com/hc/en/article?id=zm_kb&sysparm_article=KB0064983
Severity: Medium
DedupPeriodMinutes: 60
LogTypes:
- Zoom.Operation
RuleID: "Zoom.User.Promoted.to.Privileged.Role"
Threshold: 1
Stages and Predicates
Fires on Zoom.Operation events when all of the conditions below hold.
Condition
actioncontainsUpdatecategory_typeisUseroperation_detailstarts withChange Role
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 |
|---|---|---|---|
action | contains |
| field:"action" kind:contains value:"Update" |
category_type | eq |
| field:"category_type" kind:eq value:"User" |
operation_detail | starts_with |
| field:"operation_detail" kind:starts_with value:"Change Role" |
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"action": "Batch Update",
"category_type": "User",
"operation_detail": "Change Role - homer.simpson@duff.io: from User to Co-Owner",
"operator": "admin-test%1223+123@duff.dev.co",
"time": "2022-07-05 20:28:48"
}