Skip to content

Build1 publisher2 min readPublished

A resource-by-resource AWS audit passes an account with GuardDuty disabled

In HackerOne report #3022516 the trail was multi-region, the metric filter for unauthorised API calls existed and the alarm published to an SNS topic, while threat_detection.enabled read false. Turning it on costs one CLI call.

The Engineer · Build desk

Illustration accompanying A resource-by-resource AWS audit passes an account with GuardDuty disabled

What happened

  • A researcher examined an AWS account and asked whether the threat-detection layer was on, a question the write-up says configuration audits mostly skip; the case is HackerOne report #3022516.
  • The published snapshot shows a multi-region trail, a metric filter for unauthorized_api_calls, and an alarm wired to arn:aws:sns:us-east-1:123456789012:security-alerts.
  • In the same snapshot threat_detection.enabled reads false, so GuardDuty, the layer that correlates those logs into an account-compromise signal, was disabled.

Compiled by The EngineerSomething wrong?How this is made

Why it matters

  • constraint A scanner that evaluates settings on resources you already have cannot express "should exist", so detection, logging and backup gaps each need a hand-written presence rule to be visible at all.
  • cost Leaving the detector off costs whoever has to reconstruct the incident months later from a trail that was recording while nothing was correlating.
  • exposure Until a detector exists, the account's behavioural coverage is limited to whatever a filter author anticipated, so an unfamiliar call sequence is written down and never alerted on.
  • decision Teams running CSPM now choose between accumulating per-service presence exceptions and modelling each account as an asset with its own presence checks.

CloudTrail records every API call across every service, which the post describes as storage and retention with no signal [7]. The metric filters are pattern matches: they catch the case whoever wrote the filter had in mind, and a technique that fires a different API call goes through [6]. GuardDuty is the behavioural layer, correlating VPC Flow Logs, CloudTrail and DNS query logs against known-bad indicators and statistical baselines, and detecting the patterns the filter author did not think to write [5].

A checklist scanner iterates resources: S3 buckets, IAM roles, security groups, trails [10]. A disabled GuardDuty is a property of the account itself. Nothing was created, so there is no `aws_guardduty_detector` to iterate over, the scan completes successfully, and the dashboard turns green [10]. "The wrong thing is the resource you don't have," the post says [11]. Three of the four items in the published snapshot pass, and the failing one is the only one with no resource behind it [21].

The control published with the write-up is CTL.GUARDDUTY.ENABLED.001, severity high [15]. Its unsafe predicate is a single comparison: `properties.threat_detection.enabled` equals `false` [17]. Four framework citations hang off that one field read, SOC 2 CC7.1, PCI DSS v4.0 5.2, NIST 800-53 r5 SI-3 and ISO 27001:2022 A.8.16 [16][20]. The params block sets `attack_stage` to `detection_evasion`, which the post calls the "blinding the defender" lane, shared with the CloudTrail and unauthorised-API-call controls [18].

An `eq false` test only matches the value `false` [22]. If the projection cannot reach the account, or the `threat_detection` block is absent from the snapshot, there is nothing for that predicate to compare against, so the account-level projection has to be right before the rule can do anything. Stave's approach is to project the account asset with three sub-blocks, `audit_trail`, `monitoring` and `threat_detection`, and run three independent presence checks against them [14].

Enabling the detector is one CLI call, and the post puts enforcement at one boolean check per account per snapshot [8][9]. For that second number to transfer to your setup, your inventory has to already hold an account-level record with a `threat_detection` field. An inventory assembled by listing resources stops at resources. The post says most CSPM tools eventually added detector-presence rules as special-case logic [13]. The whole control, in its own words, is that an AWS account must have GuardDuty enabled with at least one detector [19].

What to watch

  • Whether HackerOne #3022516 gets a public resolution saying what the account owner enabled and when.
  • Whether CSPM vendors promote presence checks from per-service special-case rules to a default scanner pass.
  • Whether the predicate, which today fires on eq false, is revised to fire on a missing or unknown threat_detection field.
Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories