Slack Enterprise Key Management Unenrolled


Description

Detects when Slack Enterprise Key Management (EKM) is unenrolled, removing customer-controlled encryption and reverting to Slack-managed keys. EKM allows organizations to store encryption keys externally (e.g., AWS KMS), ensuring data remains protected even from Slack infrastructure compromise. Unenrollment exposes all workspace data to decryption by Slack systems and violates compliance requirements for regulated industries.

Query · python

from panther_slack_helpers import slack_alert_context


def rule(event):
    # Only alert on the `ekm_unenrolled` action
    return event.get("action") == "ekm_unenrolled"


def title(event):
    actor = event.deep_get("actor", "user", "email", default="<UNKNOWN_ACTOR>")
    workspace = event.deep_get("context", "location", "domain", default="<UNKNOWN_WORKSPACE>")
    return (
        f"Slack: Workspace [{workspace}] unenrolled from Enterprise Key Management "
        f"by [{actor}] - Customer-controlled encryption disabled"
    )


def alert_context(event):
    return slack_alert_context(event)

Analyst notes

  1. Query Slack audit logs for all actions by actor.user.email in the 30 days around the EKM unenrollment to identify other suspicious administrative actions such as data exports, workspace settings changes, user privilege escalations, or API token creations
  2. Check if the unenrollment occurred outside normal business hours or from an unusual context.ip_address or geographic location that doesn't match the actor's typical access patterns
  3. Search Slack audit logs for data export events, file downloads, or external sharing modifications during the period when EKM was unenrolled to assess potential data exposure while customer-controlled encryption was disabled
Raw source Slack Enterprise Key Management Unenrolled · Panther Python
Esc
Published by panther-labs/panther-analysis ↗, licensed under Apache 2.0 ↗. Reproduced here unmodified.
AnalysisType: rule
Filename: slack_ekm_unenrolled.py
RuleID: "Slack.AuditLogs.EKMUnenrolled"
DisplayName: "Slack Enterprise Key Management Unenrolled"
Enabled: true
LogTypes:
  - Slack.AuditLogs
Tags:
  - Slack
  - Defense Evasion
  - Weaken Encryption
  - Compliance
  - Data Protection
Reports:
  MITRE ATT&CK:
    - TA0005:T1600
    - TA0009:T1530
    - TA0010:T1567
Severity: Critical
Description: >
  Detects when Slack Enterprise Key Management (EKM) is unenrolled, removing customer-controlled encryption and reverting to Slack-managed keys. EKM allows organizations to store encryption keys externally (e.g., AWS KMS), ensuring data remains protected even from Slack infrastructure compromise. Unenrollment exposes all workspace data to decryption by Slack systems and violates compliance requirements for regulated industries.
Reference: https://slack.com/intl/en-gb/help/articles/360019110974-Slack-Enterprise-Key-Management
Runbook: |
  1. Query Slack audit logs for all actions by actor.user.email in the 30 days around the EKM unenrollment to identify other suspicious administrative actions such as data exports, workspace settings changes, user privilege escalations, or API token creations
  2. Check if the unenrollment occurred outside normal business hours or from an unusual context.ip_address or geographic location that doesn't match the actor's typical access patterns
  3. Search Slack audit logs for data export events, file downloads, or external sharing modifications during the period when EKM was unenrolled to assess potential data exposure while customer-controlled encryption was disabled
DedupPeriodMinutes: 60
Threshold: 1
SummaryAttributes:
  - p_any_ip_addresses
  - p_any_emails
Tests:
  - Name: EKM Unenrolled
    ExpectedResult: true
    Log:
      {
        "action": "ekm_unenrolled",
        "actor":
          {
            "type": "user",
            "user":
              {
                "email": "user@example.com",
                "id": "A012B3CDEFG",
                "name": "username",
                "team": "T01234N56GB",
              },
          },
        "context":
          {
            "ip_address": "1.2.3.4",
            "location":
              {
                "domain": "test-workspace",
                "id": "T01234N56GB",
                "name": "test-workspace",
                "type": "workspace",
              },
            "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36",
          },
      }
  - Name: User Logout
    ExpectedResult: false
    Log:
      {
        "action": "user_logout",
        "actor":
          {
            "type": "user",
            "user":
              {
                "email": "user@example.com",
                "id": "W012J3FEWAU",
                "name": "primary-owner",
                "team": "T01234N56GB",
              },
          },
        "context":
          {
            "ip_address": "1.2.3.4",
            "location":
              {
                "domain": "test-workspace-1",
                "id": "T01234N56GB",
                "name": "test-workspace-1",
                "type": "workspace",
              },
            "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36",
          },
        "date_create": "2022-07-28 15:22:32",
        "entity":
          {
            "type": "user",
            "user":
              {
                "email": "user@example.com",
                "id": "W012J3FEWAU",
                "name": "primary-owner",
                "team": "T01234N56GB",
              },
          },
        "id": "72cac009-9eb3-4dde-bac6-ee49a32a1789",
      }


# ------ paired body: slack_ekm_unenrolled.py ------

from panther_slack_helpers import slack_alert_context


def rule(event):
    # Only alert on the `ekm_unenrolled` action
    return event.get("action") == "ekm_unenrolled"


def title(event):
    actor = event.deep_get("actor", "user", "email", default="<UNKNOWN_ACTOR>")
    workspace = event.deep_get("context", "location", "domain", default="<UNKNOWN_WORKSPACE>")
    return (
        f"Slack: Workspace [{workspace}] unenrolled from Enterprise Key Management "
        f"by [{actor}] - Customer-controlled encryption disabled"
    )


def alert_context(event):
    return slack_alert_context(event)

Detection rules belong to the projects that publish them and remain under their own licenses. This site indexes and links to them; it claims no rights in them.