Detection rules › Kusto

ContraForce - Machine credential activity

Status
available
Severity
medium
Time window
1d
Source
github.com/Azure/Azure-Sentinel

'Identifies service-account and machine-credential lifecycle activity in the ContraForce workspace: service accounts created or deleted, credentials created, regenerated or revoked, and API client secret regenerations. Machine credentials grant standing programmatic access, so unexpected lifecycle events can indicate persistence being established or an attempt to rotate credentials out from under their legitimate owner.'

MITRE ATT&CK coverage

Rule body

id: 8a2c6e94-1b5d-4f7a-b3e8-2c9d4f6a1e52
name: ContraForce - Machine credential activity
description: |
  'Identifies service-account and machine-credential lifecycle activity in the ContraForce
  workspace: service accounts created or deleted, credentials created, regenerated or revoked,
  and API client secret regenerations. Machine credentials grant standing programmatic access,
  so unexpected lifecycle events can indicate persistence being established or an attempt to
  rotate credentials out from under their legitimate owner.'
severity: Medium
requiredDataConnectors:
  - connectorId: ContraForceEvents
    dataTypes:
      - ContraForceEvents_CL
queryFrequency: 5m
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
status: Available
tactics:
  - Persistence
  - CredentialAccess
relevantTechniques:
  - T1098
  - T1136
query: |
  ContraForceEvents_CL
  | where ingestion_time() > ago(5m)
  | where ActivityType in ("ServiceAccountCreated", "ServiceAccountDeleted", "ServiceAccountCredentialCreated", "ServiceAccountCredentialRegenerated", "ServiceAccountCredentialRevoked", "ApiClientSecretRegenerated")
  | extend Meta = parse_json(Metadata)
  | project TimeGenerated, EventId, CfWorkspaceId, ActivityType, ActivityAction,
            ActorName, ActorEmail, TargetResourceType, TargetResourceId, TargetResourceName, Metadata
eventGroupingSettings:
  aggregationKind: AlertPerResult
alertDetailsOverride:
  alertDisplayNameFormat: 'ContraForce machine credential activity: {{ActivityType}} on {{TargetResourceName}}'
  alertDescriptionFormat: '{{ActorName}} performed {{ActivityType}} on {{TargetResourceName}}.'
customDetails:
  EventId: EventId
  ActorEmail: ActorEmail
  TargetResourceId: TargetResourceId
  CfWorkspaceId: CfWorkspaceId
incidentConfiguration:
  createIncident: true
  groupingConfiguration:
    enabled: true
    reopenClosedIncident: false
    lookbackDuration: PT2H
    matchingMethod: Selected
    groupByCustomDetails:
      - EventId
version: 1.0.0
kind: Scheduled

Stages and Predicates

Stage 1: source

ContraForceEvents_CL

Stage 2: where

| where ingestion_time() > ago(5m)

Stage 3: where

| where ActivityType in ("ServiceAccountCreated", "ServiceAccountDeleted", "ServiceAccountCredentialCreated", "ServiceAccountCredentialRegenerated", "ServiceAccountCredentialRevoked", "ApiClientSecretRegenerated")

Stage 4: extend

| extend Meta = parse_json(Metadata)

Stage 5: project

| project TimeGenerated, EventId, CfWorkspaceId, ActivityType, ActivityAction,
          ActorName, ActorEmail, TargetResourceType, TargetResourceId, TargetResourceName, Metadata

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
ActivityTypein
  • ApiClientSecretRegenerated
  • ServiceAccountCreated
  • ServiceAccountCredentialCreated
  • ServiceAccountCredentialRegenerated
  • ServiceAccountCredentialRevoked
  • ServiceAccountDeleted
field:"ActivityType" kind:in

Output fields

These fields are emitted when the rule matches.

FieldSource
ActivityActionproject
ActivityTypeproject
ActorEmailproject
ActorNameproject
CfWorkspaceIdproject
EventIdproject
Metadataproject
TargetResourceIdproject
TargetResourceNameproject
TargetResourceTypeproject
TimeGeneratedproject