Detection rules › Kusto
TacitRed - Repeat Compromise Detection
This is a third-party alert feed, not a detection over modeled telemetry. The vendor product raised the finding; this rule forwards it into the SIEM. It is searchable for reference but is excluded from the detection-rule browse and the ATT&CK coverage matrix.
Detects users who have been compromised multiple times within a 7-day window. This may indicate a persistent threat or inadequate remediation. Ref: https://data443.com/tacitred-attack-surface-intelligence/
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Persistence | T1078 Valid Accounts |
Rule body kusto
id: a1b2c3d4-e5f6-7890-abcd-ef1234567890
name: TacitRed - Repeat Compromise Detection
version: 1.0.1
kind: Scheduled
description: |-
Detects users who have been compromised multiple times within a 7-day window.
This may indicate a persistent threat or inadequate remediation.
Ref: https://data443.com/tacitred-attack-surface-intelligence/
severity: High
requiredDataConnectors:
- connectorId: TacitRedThreatIntel
dataTypes:
- TacitRed_Findings_CL
queryFrequency: 1h
queryPeriod: 7d
triggerOperator: GreaterThan
triggerThreshold: 0
tactics:
- CredentialAccess
- Persistence
relevantTechniques:
- T1078
query: |-
let lookback = 7d;
TacitRed_Findings_CL
| where TimeGenerated >= ago(lookback)
| summarize
CompromiseCount = count(),
FirstSeen = min(TimeGenerated),
LastSeen = max(TimeGenerated),
Sources = make_set(source_s),
AvgConfidence = avg(confidence_d)
by email_s, domain_s
| where CompromiseCount > 1
| extend
Email = tostring(email_s),
Domain = tostring(domain_s)
| project
Email,
Domain,
CompromiseCount,
FirstSeen,
LastSeen,
Sources,
AvgConfidence
suppressionEnabled: false
incidentConfiguration:
createIncident: true
groupingConfiguration:
enabled: true
reopenClosedIncident: false
lookbackDuration: 5h
matchingMethod: Selected
groupByEntities:
- Account
suppressionDuration: 5h
eventGroupingSettings:
aggregationKind: AlertPerResult
entityMappings:
- entityType: Account
fieldMappings:
- identifier: Name
columnName: Email
- entityType: DNS
fieldMappings:
- identifier: DomainName
columnName: Domain
Stages and Predicates
Parameters
let lookback = 7d;
Stage 1: source
TacitRed_Findings_CL
Stage 2: where
| where TimeGenerated >= ago(lookback)
Stage 3: summarize
| summarize
CompromiseCount = count(),
FirstSeen = min(TimeGenerated),
LastSeen = max(TimeGenerated),
Sources = make_set(source_s),
AvgConfidence = avg(confidence_d)
by email_s, domain_s
Stage 4: where
| where CompromiseCount > 1
Stage 5: extend
| extend
Email = tostring(email_s),
Domain = tostring(domain_s)
Stage 6: project
| project
Email,
Domain,
CompromiseCount,
FirstSeen,
LastSeen,
Sources,
AvgConfidence
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.
| Field | Kind | Values |
|---|---|---|
CompromiseCount | gt |
|
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.
| Field | Source |
|---|---|
AvgConfidence | project |
CompromiseCount | project |
Domain | project |
Email | project |
FirstSeen | project |
LastSeen | project |
Sources | project |