Detection rules › Panther

GitHub Web Hook Modified

Severity
informational
Log types
GitHub.Audit
Tags
GitHub, Exfiltration:Automated Exfiltration
Reference
https://docs.github.com/en/webhooks/about-webhooks
Source
github.com/panther-labs/panther-analysis

Detects when a webhook is added, modified, or deleted

MITRE ATT&CK coverage

TacticTechniques
ExfiltrationT1020 Automated Exfiltration

Rule body yaml

AnalysisType: rule
Filename: github_webhook_modified.py
RuleID: "GitHub.Webhook.Modified"
DisplayName: "GitHub Web Hook Modified"
Enabled: true
LogTypes:
  - GitHub.Audit
Tags:
  - GitHub
  - Exfiltration:Automated Exfiltration
Reports:
  MITRE ATT&CK:
    - TA0010:T1020
Reference:
  https://docs.github.com/en/webhooks/about-webhooks
  # GH audit logs for hook events don't include the type: field
  # Only type:repo webhooks are obvious due to the repo field, Org and App look the same
  # GETs to /orgs/{org}/hooks or /repos/{owner}/{repo}/hooks will return type
  # App hooks don't return type and are defined by their API endpoint
Severity: Info
Description: Detects when a webhook is added, modified, or deleted
Tests:
  - Name: GitHub - Webhook Created
    ExpectedResult: true
    Log:
      {
        "actor": "cat",
        "action": "hook.create",
        "data":
          {
            "hook_id": 111222333444555,
            "events": ["fork", "public", "pull_request", "push", "repository"],
          },
        "config": { "url": "https://fake.url" },
        "org": "my-org",
        "p_log_type": "GitHub.Audit",
        "repo": "my-org/my-repo",
        "public_repo": false,
      }
  - Name: GitHub - Webhook Deleted
    ExpectedResult: true
    Log:
      {
        "actor": "cat",
        "action": "hook.destroy",
        "data":
          {
            "hook_id": 111222333444555,
            "events": ["fork", "public", "pull_request", "push", "repository"],
          },
        "org": "my-org",
        "p_log_type": "GitHub.Audit",
        "repo": "my-org/my-repo",
        "public_repo": false,
      }
  - Name: GitHub - Non Webhook Event
    ExpectedResult: false
    Log:
      {
        "actor": "cat",
        "action": "org.invite_member",
        "org": "my-org",
        "p_log_type": "GitHub.Audit",
        "repo": "my-org/my-repo",
      }
  - Name: Github - App Webhook Created #App and Org webhooks look the same in audit logs
    ExpectedResult: true
    Log:
      {
        "action": "hook.create",
        "actor": "dog",
        "actor_id": "11112222",
        "actor_location": { "country_code": "US" },
        "business": "my-biz",
        "business_id": "9999999",
        "config":
          {
            "content_type": "json",
            "insecure_ssl": "0",
            "url": "https://fake.url/",
          },
        "hook_id": "111222333444555",
        "integration": "My Cool Github Integration",
        "name": "webhook",
        "operation_type": "create",
        "org": "my-org",
        "org_id": 9999999,
        "p_log_type": "GitHub.Audit",
      }

Detection logic

Condition

action starts_with "hook."

Indicators

Each row is a field, operator, and value that the rule matches. The corpus column counts how many other rules in the catalog look for the same combination: high numbers point to widely-used, community-vetted indicators. Blank or 1 shows that the indicator is specific to this rule.

FieldKindValues
actionstarts_with
  • hook.

Output fields

Fields the rule emits when it matches. Chronicle authors list these in the outcome block; they appear on the detection and $risk_score drives alerting. Sentinel / Defender XDR rules build them up through project / summarize / extend stages. Sentinel maps these into alert fields via entityMappings and customDetails; Defender XDR custom detections surface them as alert fields directly.

FieldSource
action
actor
actor_locationactor_location.country_code
org
repo
user