Detection rules › Panther

Panther rules: cb

Carbon Black Admin Role Granted

#
Severity
high
Log types
CarbonBlack.Audit
Tags
Privilege Escalation, Account Manipulation
Reference
docs.vmware.com
Source
github.com/panther-labs/panther-analysis

Detects when a user is granted Admin or Super Admin permissions.

MITRE ATT&CK coverage

TacticTechniques
Privilege Escalation

Detection logic

PREFIXES = ("Updated grant: ", "Created grant: ")


def rule(event):
    desc = event.get("description", "")
    return all(
        [
            event.get("requestUrl", "").startswith("/access/"),
            any(desc.startswith(prefix) for prefix in PREFIXES),
            "Admin" in desc,
        ]
    )


def title(event):
    user = event.get("loginName", "<NO_USERNAME_FOUND>")
    ip_addr = event.get("clientIp", "<NO_IP_FOUND>")
    desc = event.get("description", "<NO_DESCRIPTION_FOUND>")
    return f"{user} [{ip_addr}] {desc}"


def severity(event):
    if "Super Admin" in event.get("description", ""):
        return "CRITICAL"
    return "HIGH"

Rule specification

AnalysisType: rule
RuleID: "CarbonBlack.Audit.Admin.Grant"
LogTypes:
  - CarbonBlack.Audit
Description: "Detects when a user is granted Admin or Super Admin permissions."
DisplayName: "Carbon Black Admin Role Granted"
Enabled: true
Filename: cb_audit_admin_grant.py
Severity: High
Tags:
  - Privilege Escalation
  - Account Manipulation
Reports:
  MITRE ATT&CK:
    - TA0004:T1098
Reference: https://docs.vmware.com/en/VMware-Carbon-Black-Cloud/services/carbon-black-cloud-user-guide/GUID-CF5ACD2C-A534-46C8-AE06-E1884DB37B58.html
Threshold: 1
DedupPeriodMinutes: 60

Stages and Predicates

Fires on CarbonBlack.Audit events when all of the conditions below hold.

Condition

  • requestUrl starts with /access/
  • any of:
    • description starts with "Updated grant: "
    • description starts with "Created grant: "
  • description contains Admin

Indicators

These rows show field, operator, and value matches.

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

Field
loginName
clientIp
description

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "clientIp": "12.34.56.78",
  "description": "Created grant: psc:cnn:A1234567:BC1234567890 with role Super Admin",
  "eventId": "66443924833011eeac3cb393f3d07f9f",
  "eventTime": "2023-11-14 20:57:19.186000000",
  "flagged": false,
  "loginName": "bob.ross@acme.com",
  "orgName": "acme.com",
  "requestUrl": "/access/v2/orgs/A1234567/grants",
  "verbose": false
}

Carbon Black API Key Created or Retrieved

#
Severity
medium
Log types
CarbonBlack.Audit
Tags
Persistence, Create Account
Reference
docs.vmware.com
Source
github.com/panther-labs/panther-analysis

Detects when a user creates a new API key or retrieves an existing key.

MITRE ATT&CK coverage

TacticTechniques
Persistence

Detection logic

PATTERNS = (
    " retrieved secret for API ID ",
    "Added API ID ",
    "Regenerated API key for API ID ",
    "Updated API ID ",
)


def rule(event):
    desc = event.get("description", "")
    return any(pattern in desc for pattern in PATTERNS)


def title(event):
    user = event.get("loginName", "<NO_USERNAME_FOUND>")
    ip_addr = event.get("clientIp", "<NO_IP_FOUND>")
    desc = event.get("description", "<NO_DESCRIPTION_FOUND>")
    return f"{user} [{ip_addr}] {desc}"

Rule specification

AnalysisType: rule
RuleID: "CarbonBlack.Audit.API.Key.Created.Retrieved"
LogTypes:
  - CarbonBlack.Audit
Description: "Detects when a user creates a new API key or retrieves an existing key."
DisplayName: "Carbon Black API Key Created or Retrieved"
Enabled: true
Filename: cb_audit_api_key_created_retrieved.py
Severity: Medium
Tags:
  - Persistence
  - Create Account
Reports:
  MITRE ATT&CK:
    - TA0003:T1136
Reference: https://docs.vmware.com/en/VMware-Carbon-Black-Cloud/services/carbon-black-cloud-user-guide/GUID-F3816FB5-969F-4113-80FC-03981C65F969.html
Threshold: 1
DedupPeriodMinutes: 60

Stages and Predicates

Fires on CarbonBlack.Audit events when any of the conditions below holds.

Condition

  • any of:
    • description contains " retrieved secret for API ID "
    • description contains "Added API ID "
    • description contains "Regenerated API key for API ID "
    • description contains "Updated API ID "

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
descriptioncontains
  • retrieved secret for API ID
  • Added API ID
  • Regenerated API key for API ID
  • Updated API ID
field:"description" kind:contains

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

Field
loginName
clientIp
description

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "clientIp": "12.34.56.78",
  "description": "User bob.ross@acme.com retrieved secret for API ID JFDNIPS464 in org 12345",
  "eventId": "66443924833011eeac3cb393f3d07f9f",
  "eventTime": "2023-11-14 20:57:19.186000000",
  "flagged": false,
  "loginName": "bob.ross@acme.com",
  "orgName": "acme.com",
  "verbose": false
}

Carbon Black Data Forwarder Stopped

#
Severity
high
Log types
CarbonBlack.Audit
Tags
Defense Evasion, Impair Defenses, Disable or Modify Cloud Logs
Reference
docs.vmware.com
Source
github.com/panther-labs/panther-analysis

Detects when a user disables or deletes a Data Forwarder.

MITRE ATT&CK coverage

Detection logic

ACTION = ""


def rule(event):
    # pylint: disable=global-statement
    global ACTION
    if not event.get("requestUrl", "").startswith("/data_forwarder/"):
        return False
    desc = event.get("description", "")
    if desc.startswith("Deleted Config: "):
        ACTION = "Deleted"
        return True
    if desc.startswith("Updated Config: ") and '"enabled":false' in desc:
        ACTION = "Disabled"
        return True
    return False


def title(event):
    user = event.get("loginName", "<NO_USERNAME_FOUND>")
    ip_addr = event.get("clientIp", "<NO_IP_FOUND>")
    return f"{user} [{ip_addr}] {ACTION} Data Forwarder"


def description(event):
    user = event.get("loginName")
    ip_addr = event.get("clientIp")
    desc = event.get("description")
    return f"{user} [{ip_addr}] {desc}"

Rule specification

AnalysisType: rule
RuleID: "CarbonBlack.Audit.Data.Forwarder.Stopped"
LogTypes:
  - CarbonBlack.Audit
Description: "Detects when a user disables or deletes a Data Forwarder."
DisplayName: "Carbon Black Data Forwarder Stopped"
Enabled: true
Filename: cb_audit_data_forwarder_stopped.py
Severity: High
Tags:
  - Defense Evasion
  - Impair Defenses
  - Disable or Modify Cloud Logs
Reports:
  MITRE ATT&CK:
    - TA0005:T1562.008
Reference: https://docs.vmware.com/en/VMware-Carbon-Black-Cloud/services/carbon-black-cloud-user-guide/GUID-E8D33F72-BABB-4157-A908-D8BBDB5AF349.html
Threshold: 1
DedupPeriodMinutes: 60

Stages and Predicates

Fires on CarbonBlack.Audit events when all of the conditions below hold.

Condition

  • requestUrl starts with /data_forwarder/
  • any of:
    • description starts with "Deleted Config: "
    • all of:
      • description starts with "Updated Config: "
      • description contains "enabled":false

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.

FieldKindValuesSearch
descriptioncontains
  • "enabled":false
field:"description" kind:contains
descriptionstarts_with
  • Deleted Config:
  • Updated Config:
field:"description" kind:starts_with
requestUrlstarts_with
  • /data_forwarder/
field:"requestUrl" kind:starts_with value:"/data_forwarder/"

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

Field
loginName
clientIp

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "clientIp": "12.34.56.78",
  "description": "Updated Config: {\"id\":\"b6ab1fb9-61f6-11ee-9e9b-5655adf4bf96\",\"org_key\":\"A1234567\",\"name\":\"endpoint event\",\"enabled\":false,\"s3_bucket_name\":\"carbonblackbucket\",\"s3_prefix\":\"endpoint\",\"type\":\"endpoint.event\",\"create_time\":\"2023-10-03T14:11:14Z\",\"update_time\":\"2023-11-14T19:16:43Z\"}\n",
  "eventId": "58bef441832211ee83ef1721d866b8d6",
  "eventTime": "2023-11-14 19:16:43.123000000",
  "flagged": false,
  "loginName": "bob.ross@acme.com",
  "orgName": "bob.ross@acme.com",
  "requestUrl": "/data_forwarder/v2/orgs/A1234567/configs/b6ab1fb9-61f6-11ee-9e9b-5655adf4bf96",
  "verbose": false
}

Carbon Black Log Entry Flagged

#
Severity
medium
Log types
CarbonBlack.Audit
Tags
Credential Access, Brute Force
Reference
docs.vmware.com
Source
github.com/panther-labs/panther-analysis

Detects when Carbon Black has flagged a log as important, such as failed login attempts and locked accounts.

MITRE ATT&CK coverage

TacticTechniques
Credential Access

Detection logic

def rule(event):
    return event.get("flagged", False)


def title(event):
    user = event.get("loginName", "<NO_USERNAME_FOUND>")
    ip_addr = event.get("clientIp", "<NO_IP_FOUND>")
    desc = event.get("description", "<NO_DESCRIPTION_FOUND>")
    return f"{user} [{ip_addr}] {desc}"


def severity(event):
    if event.get("description").startswith("Requested sensor update"):
        return "INFO"
    return "DEFAULT"

Rule specification

AnalysisType: rule
RuleID: "CarbonBlack.Audit.Flagged"
LogTypes:
  - CarbonBlack.Audit
Description: "Detects when Carbon Black has flagged a log as important, such as failed login attempts and locked accounts."
DisplayName: "Carbon Black Log Entry Flagged"
Enabled: true
Filename: cb_audit_flagged.py
Severity: Medium
Tags:
  - Credential Access
  - Brute Force
Reports:
  MITRE ATT&CK:
    - TA0006:T1110
Reference: https://docs.vmware.com/en/VMware-Carbon-Black-Cloud/services/carbon-black-cloud-user-guide/GUID-FB61E4E3-6431-4226-A4E3-5949FB75922B.html
Threshold: 1
DedupPeriodMinutes: 60

Stages and Predicates

Fires on CarbonBlack.Audit events when the condition below holds.

Condition

  • flagged is present

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
flaggedis_not_null
  • (no value, null check)
field:"flagged" kind:is_not_null

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

Field
loginName
clientIp
description

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "clientIp": "12.34.56.78",
  "description": "User bob.ross@acme.com retrieved secret for API ID JFDNIPS464 in org 12345",
  "eventId": "66443924833011eeac3cb393f3d07f9f",
  "eventTime": "2023-11-14 20:57:19.186000000",
  "flagged": true,
  "loginName": "bob.ross@acme.com",
  "orgName": "acme.com",
  "verbose": false
}

Carbon Black Passthrough Rule

#

This is a third-party alert feed, not a detection over modeled telemetry. Another security product raised the finding; this rule forwards or reshapes it into the SIEM. It is searchable for reference but is excluded from the detection-rule browse and the ATT&CK coverage matrix.

Severity
medium
Group by
id
Log types
CarbonBlack.AlertV2
Reference
docs.vmware.com
Source
github.com/panther-labs/panther-analysis

This rule enriches and contextualizes security alerts generated by Carbon Black. The alert title and description are dynamically updated based on data included in the alert log.

Detection logic

def rule(event):
    return event.deep_get("workflow", "changed_by") == "ALERT_CREATION"


def title(event):
    return (
        f"{event.get('attack_tactic', 'CB')}: "
        f"{event.get('device_username', '<no-user-found>')} on "
        f"{event.get('device_name', '<no-device-found>')}: "
        f"{event.get('reason', '<no-reason-found>')}"
    )


def description(event):
    return event.get("reason", "<no-reason-found>")


def severity(event):
    sev = event.get("severity")
    if sev >= 8:
        return "CRITICAL"
    if sev >= 6:
        return "HIGH"
    if sev >= 4:
        return "MEDIUM"
    if sev >= 2:
        return "LOW"
    return "INFO"


def reference(event):
    return event.get("alert_url")


def dedup(event):
    return event.get("id")

Rule specification

AnalysisType: rule
RuleID: CarbonBlack.AlertV2.Passthrough
Description: This rule enriches and contextualizes security alerts generated by Carbon Black.  The alert title and description are dynamically updated based on data included in the alert log.
DisplayName: Carbon Black Passthrough Rule
Runbook: Review the Carbon Black alert details to determine what malicious behavior was detected, and whether or not it was blocked.  Use the Reference link to view the alert in the Carbon Black console and take remediating actions if necessary.
Reference: https://docs.vmware.com/en/VMware-Carbon-Black-Cloud/services/carbon-black-cloud-user-guide/GUID-0B68199D-6411-45D1-AE0D-2AB9B7A28513.html
Enabled: true
Filename: cb_passthrough.py
LogTypes:
  - CarbonBlack.AlertV2
Severity: Medium
DedupPeriodMinutes: 30
Threshold: 1
SummaryAttributes:
  - attack_tactic
  - blocked_name
  - device_name
  - device_username
  - primary_event_id
  - reason
  - threat_id

Stages and Predicates

Fires on CarbonBlack.AlertV2 events when the condition below holds.

Condition

  • workflow.changed_by is ALERT_CREATION
Alert deduplication
repeat matches within 30m group into one alert

Indicators

These rows show field, operator, and value matches.

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

Field
attack_tactic
device_username
device_name
reason

Response runbook

Review the Carbon Black alert details to determine what malicious behavior was detected, and whether or not it was blocked. Use the Reference link to view the alert in the Carbon Black console and take remediating actions if necessary.

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "alert_notes_present": false,
  "alert_url": "https://d5.carbonblack.net/alerts?orgKey=ABCD1234&s%5Bc%5D%5Bquery_string%5D=id%3A9728f0c8-7810-fb20-15d0-343031500435",
  "attack_tactic": "TA0002",
  "backend_timestamp": "2023-10-04 08:47:36.268000000",
  "backend_update_timestamp": "2023-10-04 08:47:36.268000000",
  "blocked_effective_reputation": "TRUSTED_WHITE_LIST",
  "blocked_name": "c:\\windows\\system32\\cmd.exe",
  "blocked_sha256": "b99d61d874728edc0918ca0eb10eab93d381e7367e377406e65963366c874450",
  "childproc_cmdline": "C:\\Windows\\system32\\cmd.exe /c \"\"C:\\Users\\bob.ross\\Downloads\\u0007irreg\\AirRegNCmd.cmd\" N18906\"",
  "childproc_effective_reputation": "TRUSTED_WHITE_LIST",
  "childproc_guid": "ABCD1234-0a5089d3-00002004-00000000-1d9f69f13af9c8b",
  "childproc_name": "c:\\windows\\system32\\cmd.exe",
  "childproc_sha256": "b99d61d874728edc0918ca0eb10eab93d381e7367e377406e65963366c874450",
  "childproc_username": "DESKTOP-A1B2C3\\bob.ross",
  "detection_timestamp": "2023-10-04 08:46:44.508000000",
  "determination": {
    "change_timestamp": "2023-10-04 08:47:36.268000000",
    "value": "NONE"
  },
  "device_external_ip": "12.34.56.78",
  "device_id": 173050323,
  "device_internal_ip": "192.168.31.23",
  "device_location": "OFFSITE",
  "device_name": "DESKTOP-A1B2C3",
  "device_os": "WINDOWS",
  "device_policy": "Standard",
  "device_policy_id": 390195,
  "device_target_value": "MEDIUM",
  "device_username": "bob.ross@gmail.com",
  "first_event_timestamp": "2023-10-04 08:42:17.182000000",
  "id": "9728f0c8-7810-fb20-15d0-343031500435",
  "is_updated": false,
  "last_event_timestamp": "2023-10-04 08:45:49.524000000",
  "mdr_alert": false,
  "mdr_alert_notes_present": false,
  "org_key": "ABCD1234",
  "p_log_type": "CarbonBlack.AlertV2",
  "parent_effective_reputation": "LOCAL_WHITE",
  "parent_guid": "ABCD1234-0a5089d3-000013f8-00000000-1d9f69f13af9c8b",
  "parent_name": "c:\\windows\\explorer.exe",
  "parent_pid": 5112,
  "parent_reputation": "TRUSTED_WHITE_LIST",
  "parent_sha256": "9c06462b5d1b85517a8ed4b5754c21e6beca5c9a02e42efa8b0e1049431c2972",
  "parent_username": "DESKTOP-A1B2C3\\bob.ross",
  "policy_applied": "APPLIED",
  "primary_event_id": "8e8f7f9f629211ee87ce374372b370f0",
  "process_cmdline": "\"C:\\Windows\\System32\\WindowsPowerShell\\u000b1.0\\powershell.exe\" ",
  "process_effective_reputation": "TRUSTED_WHITE_LIST",
  "process_guid": "ABCD1234-0a5089d3-000029a8-00000000-1d9f69f13af9c8b",
  "process_issuer": [
    ""
  ],
  "process_md5": "dfd66604ca0898e8e26df7b1635b6326",
  "process_name": "c:\\windows\\system32\\windowspowershell\\u000b1.0\\powershell.exe",
  "process_pid": 10664,
  "process_publisher": [
    ""
  ],
  "process_reputation": "TRUSTED_WHITE_LIST",
  "process_sha256": "d23b67799a0da0143e395ba5db906a22ab08fac4bd5581e275b1e0f1b3fac55c",
  "process_username": "DESKTOP-A1B2C3\\bob.ross",
  "reason": "The application utweb.exe was detected running. A Terminate Policy Action was applied.",
  "reason_code": "T_POL_TERM : utweb.exe",
  "run_state": "RAN",
  "sensor_action": "ALLOW",
  "severity": 3,
  "threat_id": "f1088650549018a6dab7e582a9d3b826",
  "ttps": [
    "POLICY_TERMINATE",
    "NETWORK_ACCESS",
    "MITRE_T1059_003_WIN_CMD_SHELL",
    "ACTIVE_CLIENT",
    "INTERNATIONAL_SITE",
    "MITRE_T1059_001_POWERSHELL",
    "MITRE_T1059_CMD_LINE_OR_SCRIPT_INTER",
    "UNKNOWN_APP",
    "RUN_CMD_SHELL"
  ],
  "type": "CB_ANALYTICS",
  "version": "2.0.0",
  "workflow": {
    "change_timestamp": "2023-10-04 08:47:36.268000000",
    "changed_by": "ALERT_CREATION",
    "changed_by_type": "SYSTEM",
    "closure_reason": "NO_REASON",
    "status": "OPEN"
  }
}

Carbon Black User Added Outside Org

#
Severity
high
Log types
CarbonBlack.Audit
Tags
Persistence, Create Account
Reference
docs.vmware.com
Source
github.com/panther-labs/panther-analysis

Detects when a user from a different organization is added to Carbon Black.

MITRE ATT&CK coverage

TacticTechniques
Persistence

Detection logic

PATTERNS = ("Added user ",)


def rule(event):
    desc = event.get("description", "")
    if not any(desc.startswith(pattern) for pattern in PATTERNS):
        return False
    src_user = event.get("loginName", "")
    src_domain = src_user.split("@")[1]
    dst_user = desc.split(" ")[2]
    dst_domain = dst_user.split("@")[1]
    if src_domain != dst_domain:
        return True
    return False


def title(event):
    user = event.get("loginName", "<NO_USERNAME_FOUND>")
    ip_addr = event.get("clientIp", "<NO_IP_FOUND>")
    desc = event.get("description", "<NO_DESCRIPTION_FOUND>")
    return f"{user} [{ip_addr}] {desc}"

Rule specification

AnalysisType: rule
RuleID: "CarbonBlack.Audit.User.Added.Outside.Org"
LogTypes:
  - CarbonBlack.Audit
Description: "Detects when a user from a different organization is added to Carbon Black."
DisplayName: "Carbon Black User Added Outside Org"
Enabled: true
Filename: cb_audit_user_added_outside_org.py
Severity: High
Tags:
  - Persistence
  - Create Account
Reports:
  MITRE ATT&CK:
    - TA0003:T1136
Reference: https://docs.vmware.com/en/VMware-Carbon-Black-Cloud/services/carbon-black-cloud-user-guide/GUID-516BAF8C-A13D-4FC7-AA92-923159C13083.html
Threshold: 1
DedupPeriodMinutes: 60

Stages and Predicates

Fires on CarbonBlack.Audit events when the condition below holds.

Condition

  • description starts with "Added user "

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.

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

Field
loginName
clientIp
description

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "clientIp": "12.34.56.78",
  "description": "Added user badguy@acme.io to org 12345 (Email Invitation)",
  "eventId": "d109e568832111ee8ab2057b240e65f8",
  "eventTime": "2023-11-14 19:12:55.917000000",
  "flagged": false,
  "loginName": "bob.ross@acme.com",
  "orgName": "acme.com",
  "verbose": false
}