Security Deep Dive (GuardDuty, WAF, Security Hub)¶
Level 1's security group and IAM basics stop intrusions at the network and permission edge. This module covers three services that detect and respond to threats that get past those edges: GuardDuty (threat detection), WAF (application-layer filtering), and Security Hub (centralized findings).
GuardDuty: continuous threat detection¶
GuardDuty analyzes VPC Flow Logs, DNS logs, and CloudTrail events against threat intelligence feeds and anomaly models — no agents to install, no logs to configure yourself.
aws guardduty create-detector --enable
aws guardduty list-findings \
--detector-id 8ab1c2d3e4f5678901234567890abcdef \
--finding-criteria '{"Criterion":{"severity":{"Gte":7}}}'
aws guardduty get-findings \
--detector-id 8ab1c2d3e4f5678901234567890abcdef \
--finding-ids 8cb1c2d3e4f5678901234567890abcdef
# {
# "Findings": [{
# "Type": "UnauthorizedAccess:EC2/SSHBruteForce",
# "Severity": 5.0,
# "Title": "203.0.113.5 is performing SSH brute force attacks against i-0abc123."
# }]
# }
Findings are scored 1-10 (severity); route high-severity findings to EventBridge for automated response:
aws events put-rule \
--name guardduty-high-severity \
--event-pattern '{"source":["aws.guardduty"],"detail":{"severity":[{"numeric":[">=",7]}]}}'
WAF: filtering at the application layer¶
Security groups filter by IP/port; WAF inspects HTTP request content — SQL injection patterns, rate limits per IP, geographic blocks — and attaches to CloudFront, ALB, or API Gateway.
aws wafv2 create-web-acl \
--name training-app-waf \
--scope REGIONAL \
--default-action Allow={} \
--visibility-config SampledRequestsEnabled=true,CloudWatchMetricsEnabled=true,MetricName=training-app-waf \
--rules file://waf-rules.json
[
{
"Name": "RateLimitPerIP",
"Priority": 1,
"Action": { "Block": {} },
"Statement": { "RateBasedStatement": { "Limit": 2000, "AggregateKeyType": "IP" } },
"VisibilityConfig": { "SampledRequestsEnabled": true, "CloudWatchMetricsEnabled": true, "MetricName": "RateLimitPerIP" }
},
{
"Name": "AWSManagedCommonRuleSet",
"Priority": 2,
"OverrideAction": { "None": {} },
"Statement": { "ManagedRuleGroupStatement": { "VendorName": "AWS", "Name": "AWSManagedRulesCommonRuleSet" } },
"VisibilityConfig": { "SampledRequestsEnabled": true, "CloudWatchMetricsEnabled": true, "MetricName": "CommonRuleSet" }
}
]
aws wafv2 associate-web-acl \
--web-acl-arn arn:aws:wafv2:us-east-1:123456789012:regional/webacl/training-app-waf/abc123 \
--resource-arn arn:aws:elasticloadbalancing:us-east-1:123456789012:loadbalancer/app/training-alb/def456
AWS Managed Rule Groups (like AWSManagedRulesCommonRuleSet, covering
OWASP Top 10 patterns) save you from writing your own SQLi/XSS regex
rules — start with OverrideAction: None (enforce) only after testing
with Count to see what would have been blocked.
Security Hub: centralized findings¶
GuardDuty, Inspector, Macie, and WAF each produce their own findings. Security Hub aggregates them (plus your own custom findings) into one place, scored against standards like CIS AWS Foundations.
aws securityhub enable-security-hub \
--enabled-standards StandardsSubscriptionArns=arn:aws:securityhub:us-east-1::standards/aws-foundational-security-best-practices/v/1.0.0
aws securityhub get-findings \
--filters '{"SeverityLabel":[{"Value":"CRITICAL","Comparison":"EQUALS"}]}'
In a multi-account Organization, one account can be designated the
Security Hub administrator, aggregating findings from every member
account into a single dashboard — set up via
aws securityhub create-members plus an invitation/auto-enable flow.
Gotchas¶
- GuardDuty has no free tier beyond a 30-day trial and bills on
volume of logs analyzed — a very high-traffic VPC can make GuardDuty
itself a meaningful cost line; it's still almost always worth it, but
don't enable it silently across every account without checking the
estimate first (
get-usage-statistics). - WAF's default action matters more than the rules — a Web ACL with
DefaultAction: Allowand no matching rule lets everything through; double checkdefault-actionisn't accidentallyBlockin production either, which would 500 all legitimate traffic. - Rule priority order determines evaluation — WAF evaluates rules
in ascending
Priorityand stops at the first terminating action (Block/Allow), so a broad allow rule placed before a specific block rule silently defeats it. - Security Hub standards checks run periodically, not real-time — don't expect a finding to appear the instant a misconfiguration happens; checks run on an internal schedule (typically within hours).
- Enabling multiple standards multiplies findings volume — start with one (e.g., AWS Foundational Security Best Practices) and triage before turning on CIS and PCI DSS simultaneously.
Cheat sheet¶
| Command | Purpose |
|---|---|
aws guardduty create-detector --enable |
Turn on threat detection |
aws guardduty list-findings |
List current findings |
aws wafv2 create-web-acl |
Create a Web ACL |
aws wafv2 associate-web-acl |
Attach it to ALB/CloudFront/API Gateway |
aws securityhub enable-security-hub |
Turn on centralized findings |
aws securityhub get-findings |
Query aggregated findings |
How It Actually Works¶
GuardDuty doesn't scan your resources directly — it's a passive
consumer of existing data streams AWS already generates for other purposes:
VPC Flow Logs, DNS query logs, and CloudTrail management/data events are
continuously fed into GuardDuty's own threat-intelligence and
machine-learning pipeline, which correlates them against known malicious IP
lists, DNS patterns associated with C2 infrastructure, and behavioral
baselines built per-account (e.g., "this IAM user has never called
GetSecretValue before, and just did, from an unusual geography"). Because
it's built on log analysis rather than live interception, GuardDuty findings
are inherently detective, not preventive — there's an unavoidable
analysis lag between the underlying activity and a finding appearing, on
the order of minutes.
AWS Config works by subscribing to CloudTrail's change-relevant API calls and, on detecting one, invoking the affected resource type's describe API to capture a full configuration snapshot, which it stores as an immutable history item — this is what lets Config answer "what did this security group look like at 3pm last Tuesday" months later: it's not inferring history, it's replaying a literal recorded snapshot from that timestamp. Config Rules are Lambda functions (AWS-managed or custom) that Config invokes against each new snapshot to evaluate compliance, which is why a rule's evaluation timestamp can lag noticeably behind the actual resource change it's evaluating.
KMS enforces a hard boundary: your key's cryptographic material never leaves the KMS HSM boundary in plaintext form, ever — this is why every KMS "decrypt" or "encrypt" operation is a network call rather than something an SDK can do locally with a cached key, and why CloudTrail can log a complete, non-repudiable audit trail of every single use of a key (unlike a client-managed key you could copy and use anywhere undetected).
Exercise¶
Enable GuardDuty in a test account, create a WAF Web ACL with the AWS
Managed Common Rule Set in Count mode (not enforcing) attached to an
ALB, and enable Security Hub with the AWS Foundational Security Best
Practices standard. After an hour, compare what each of the three
surfaces reports for the same account.