AWS GuardDuty

GuardDuty is an intelligent threat detection service that continuously analyzes AWS logs (CloudTrail, DNS, VPC Flow Logs, S3, EKS) using machine learning to identify suspicious activity.

Data Sources

GuardDuty analyzes:
  │
  ├── CloudTrail Management Events — API calls (who did what)
  ├── CloudTrail S3 Data Events — S3 object operations
  ├── VPC Flow Logs — network traffic (who talked to whom)
  ├── DNS Logs — DNS queries from within VPC
  ├── EKS Audit Logs — Kubernetes API activity
  └── RDS Login Activity — database login attempts (Aurora, RDS)

Findings

Severity Levels

SeverityScoreExample
HIGH7.0-8.9Cryptocurrency mining, data exfiltration
MEDIUM4.0-6.9Compromised IAM user, unusual API call
LOW1.0-3.9Policy change, root login

Finding Types

Discovery:
  - ReconnaissanceDiscovery — unusual enumeration activity

Compromise:
  - IAMUser/CompromisedCredentials — leaked access keys
  - EC2/ compromisedInstance — EC2 instance compromised
  - Container/compromisedWorkload — Kubernetes compromise

Exfiltration:
  - Data exfiltration via S3 or DNS
  - Large S3 data transfer

Cryptocurrency:
  - EC2/CryptocurrencyExecution — crypto mining
  - Container/CryptocurrencyExecution — crypto in containers

Finding Example

{
  "AccountId": "123456789012",
  "Partition": "aws",
  "Region": "us-east-1",
  "Type": "UnauthorizedAccess:IAMUser/ConsoleLogin",
  "Severity": {
    "Score": 7.5,
    "Label": "HIGH"
  },
  "Title": "Root user sign-in from a new IP address.",
  "Description": "A root user console login from a new IP address was detected.",
  "Resources": [{
    "AccountId": "123456789012",
    "Type": "AwsIamUser",
    "IamUserArn": "arn:aws:iam::123456789012:root"
  }],
  "Service": {
    "Action": {
      "ConsoleLoginAction": {
        "ActionType": "REMOTE_LOGIN"
      }
    },
    "Actor": {
      "RemoteIpDetails": {
        "IpAddressV4": "203.0.113.10",
        "Country": {"Name": "Russia"},
        "City": {"Name": "Moscow"}
      }
    },
    "LastSeen": "2024-01-15T10:30:00Z"
  }
}

Enabling GuardDuty

# Enable GuardDuty
aws guardduty enable-detector \
  --region us-east-1 \
  --finding-publishing-frequency ONE_HOUR  # or FIFTEEN_MINUTES, ONE_HOUR, SIX_HOURS
 
# Enable S3 protection (logs S3 data events)
aws guardduty update-detector \
  --detector-id xxxxx \
  --enable \
  --finding-publishing-frequency ONE_HOUR \
  --data-sources '{
    "S3Logs": {"Enable": true}
  }'
 
# Enable EKS protection
aws guardduty update-detector \
  --detector-id xxxxx \
  --data-sources '{
    "EKSAuditLogs": {"Enable": true}
  }'

Managing Findings

# List findings
aws guardduty list-findings \
  --detector-id xxxxx \
  --finding-criteria '{
    "Criterion": {
      "severity": {"Eq": ["HIGH"]},
      "service.archived": {"Eq": ["false"]}
    }
  }'
 
# Get finding details
aws guardduty get-findings \
  --detector-id xxxxx \
  --finding-ids xxxxx-xxxxx-xxxxx
 
# Archive finding (when false positive)
aws guardduty archive-findings \
  --detector-id xxxxx \
  --finding-ids xxxxx-xxxxx-xxxxx

Automated Response with EventBridge

# Create EventBridge rule
aws events put-rule \
  --name guardduty-high-severity \
  --event-pattern '{
    "source": ["aws.guardduty"],
    "detail": {
      "severity": [{"numeric": [">=", 7]}]
    }
  }'
 
# Add Lambda target
aws events put-targets \
  --rule guardduty-high-severity \
  --targets '[{
    "Id": "my-lambda",
    "Arn": "arn:aws:lambda:us-east-1:123456789012:function:guardduty-response"
  }]'

Example Response Lambda

import boto3
 
def lambda_handler(event, context):
    finding = event['detail']
    finding_type = finding['type']
    actor_ip = finding['service']['actor']['remoteIpDetails']['ipAddressV4']
    
    # Block IP in security group
    ec2 = boto3.client('ec2')
    
    # Create SG rule to block
    ec2.authorize_security_group_ingress(
        GroupId='sg-xxxxx',
        IpProtocol='tcp',
        FromPort=443,
        ToPort=443,
        CidrIp=f"{actor_ip}/32"
    )
    
    # Notify security team
    sns = boto3.client('sns')
    sns.publish(
        TopicArn='arn:aws:sns:us-east-1:123456789012:security-alerts',
        Message=f"GuardDuty HIGH: {finding_type} from {actor_ip}"
    )

GuardDuty Enterprise

Add centralized threat detection across all accounts:

# Enable GuardDuty in master account
aws guardduty enable-organization-configuration \
  --detector-id xxxxx \
  --autoEnable
 
# Member accounts automatically enrolled

Malware Protection

# Enable malware protection
aws guardduty update-detector \
  --detector-id xxxxx \
  --data-sources '{
    "MalwareProtection": {
      "ScanEc2InstanceWithFindings": {"Ec2InstanceYam": {"Enable": true}},
      "ServiceRoleArn": "arn:aws:iam::123456789012:role/GuardDuty MalwareProtection"
    }
  }'

When GuardDuty detects a compromised EC2 instance, it can initiate a malware scan.

Monitoring

# CloudWatch metrics
aws cloudwatch get-metric-statistics \
  --namespace AWS/GuardDuty \
  --metric-name FindingCount \
  --dimensions Name=ThreatPurpose,Value=UnauthorizedAccess

Pricing

ComponentCost
CloudTrail events analyzedFree (10M events/month free tier)
DNS Logs$0.60/million DNS queries
VPC Flow Logs$0.75/million flow log entries
S3 Data Events$1.00/million S3 events
EKS Audit Logs$1.00/million EKS audit events
Malware Protection (EC2)$1.00/GB scanned

Limits

ResourceLimit
Detectors1 per region
Findings1000 per page (list), 50 per batch (get)
IP sets100 per detector
Threat lists30 (for threat purposes)

References

Pricing Examples

Scenario 1: A small account (50 users, moderate activity). CloudTrail events: 5M/month. DNS queries: 10M/month × 6/month. VPC Flow: 100GB/month × 0.075/month. S3 events: disabled. Total: ~$6/month.

Scenario 2: A large enterprise (500 users, heavy activity). CloudTrail events: 100M/month (free). DNS queries: 1B/month × 600/month. VPC Flow: 10TB/month × 7.50/month. S3 events: 1B × 1,000/month. That’s $1,607/month — S3 data events are expensive at scale. Disable for non-critical buckets.

Nuggets & Gotchas

  • GuardDuty is a detection service, not prevention — it doesn’t block anything: GuardDuty identifies threats and generates findings. You must build automated responses (EventBridge + Lambda) or manually respond. Enable GuardDuty + response automation together.
  • **S3 data events in GuardDuty (1/M = $60/month. Start with just management events + DNS + VPC Flow.
  • GuardDuty findings auto-expire after 90 days — export important findings to S3 or Security Hub: If you need long-term retention, create an EventBridge rule to capture HIGH severity findings to S3 or SIEM.
  • GuardDuty RDS protection only covers Aurora and RDS (not DocumentDB, Neptune, etc.): If you use DocumentDB or Neptune, GuardDuty won’t log database login attempts for those engines. Use database-native audit logging for those.
  • GuardDuty malware protection requires GuardDuty to have an IAM role that can access EC2 instances — enable via ServiceRoleArn: Without this role, the malware scan won’t run even if enabled.