Detection rules › Kusto
AWS Security Hub - Detect CloudTrail trails lacking KMS encryption
This query detects AWS CloudTrail trails that are not configured to use server-side encryption with a customer managed KMS key using AWS Security Hub control CloudTrail.2 findings. Unencrypted CloudTrail logs increase the risk of unauthorized access to sensitive audit data at rest.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Defense Impairment | |
| Impact |
Rule body
id: 9c2f6c3b-7fd8-4c5a-9d9d-3c4f9e6a7b21
name: AWS Security Hub - Detect CloudTrail trails lacking KMS encryption
description: |
This query detects AWS CloudTrail trails that are not configured to use server-side encryption with a customer managed KMS key using AWS Security Hub control CloudTrail.2 findings.
Unencrypted CloudTrail logs increase the risk of unauthorized access to sensitive audit data at rest.
severity: Medium
status: Available
requiredDataConnectors:
- connectorId: AWSSecurityHub
dataTypes:
- AWSSecurityHubFindings
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
- Impact
- DefenseEvasion
relevantTechniques:
- T1565.001
- T1562.008
tags:
- CIS AWS Foundations Benchmark v1.4.0
- CIS AWS Foundations Benchmark v1.2.0
- NIST 800-53 r5
- PCI DSS v3.2.1
query: |
AWSSecurityHubFindings
| where RecordState == "ACTIVE" and ComplianceStatus == "FAILED"
| where tostring(AwsSecurityFindingGeneratorId) == "security-control/CloudTrail.2"
or tostring(ComplianceSecurityControlId) == "CloudTrail.2"
| mv-expand Resource = Resources
| where tostring(Resource.Type) == "AwsCloudTrailTrail"
| extend TrailId = tostring(Resource.Id)
| summarize TimeGenerated = max(TimeGenerated)
by AwsAccountId, AwsRegion, AwsSecurityFindingTitle, AwsSecurityFindingDescription,
AwsSecurityFindingId, ComplianceSecurityControlId, TrailId
entityMappings:
- entityType: Account
fieldMappings:
- identifier: Name
columnName: AwsAccountId
- identifier: CloudAppAccountId
columnName: AwsAccountId
- entityType: CloudApplication
fieldMappings:
- identifier: Name
columnName: TrailId
customDetails:
ComplianceControlId: ComplianceSecurityControlId
Region: AwsRegion
FindingId: AwsSecurityFindingId
alertDetailsOverride:
alertDisplayNameFormat: "AWS CloudTrail trail {{TrailId}} lacks KMS encryption"
alertDescriptionFormat: "AWS CloudTrail trail ({{TrailId}}) lacks customer-managed KMS encryption for Account {{AwsAccountId}}."
version: 1.0.0
kind: Scheduled
Stages and Predicates
Stage 1: source
AWSSecurityHubFindings
Stage 2: where
| where RecordState == "ACTIVE" and ComplianceStatus == "FAILED"
Stage 3: where
| where tostring(AwsSecurityFindingGeneratorId) == "security-control/CloudTrail.2"
or tostring(ComplianceSecurityControlId) == "CloudTrail.2"
Stage 4: mv-expand
| mv-expand Resource = Resources
Stage 5: where
| where tostring(Resource.Type) == "AwsCloudTrailTrail"
Stage 6: extend
| extend TrailId = tostring(Resource.Id)
Stage 7: summarize
| summarize TimeGenerated = max(TimeGenerated)
by AwsAccountId, AwsRegion, AwsSecurityFindingTitle, AwsSecurityFindingDescription,
AwsSecurityFindingId, ComplianceSecurityControlId, TrailId
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
AwsSecurityFindingGeneratorId | eq |
| field:"AwsSecurityFindingGeneratorId" kind:eq value:"security-control/CloudTrail.2" |
ComplianceSecurityControlId | eq |
| field:"ComplianceSecurityControlId" kind:eq value:"CloudTrail.2" |
ComplianceStatus | eq |
| field:"ComplianceStatus" kind:eq value:"FAILED" |
RecordState | eq |
| field:"RecordState" kind:eq value:"ACTIVE" |
Type | eq |
| field:"Type" kind:eq value:"AwsCloudTrailTrail" |
Output fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
AwsAccountId | summarize |
AwsRegion | summarize |
AwsSecurityFindingDescription | summarize |
AwsSecurityFindingId | summarize |
AwsSecurityFindingTitle | summarize |
ComplianceSecurityControlId | summarize |
TimeGenerated | summarize |
TrailId | summarize |