← Back to Tutorials
Tutorial 11 Beginner

How to Set Up AWS GuardDuty for AI-Powered Threat Detection

GuardDuty uses machine learning and threat intelligence to detect malicious activity in your AWS environment. Learn how to enable it with optimal settings and automated response.

20 min implementation
12 min read
Threat Detection

Why AWS GuardDuty is Essential for Security

AWS GuardDuty is a managed threat detection service that uses machine learning, anomaly detection, and integrated threat intelligence to identify malicious activity in your AWS environment. It continuously monitors your infrastructure without requiring additional software or complex configurations.

  • Detects compromised EC2 instances communicating with command & control servers
  • Identifies unauthorized cryptocurrency mining on your compute resources
  • Catches credential theft and unusual API call patterns
  • Monitors for data exfiltration attempts from S3 buckets
  • Analyzes VPC Flow Logs, DNS logs, and CloudTrail events automatically
  • Provides findings within minutes of detecting threats
⚠️
Critical: Without automated threat detection, compromised resources can go undetected for months. GuardDuty analyzes billions of events to identify threats that manual log analysis would miss, enabling rapid incident response before significant damage occurs.

The Four Critical Blind Spots GuardDuty Addresses

1

Cryptocurrency Mining

Unauthorized compute usage for mining operations. GuardDuty identifies suspicious DNS queries to mining pools and unusual CPU utilization patterns across EC2 instances.

2

Credential Compromise

Stolen AWS access keys being used from unusual locations. GuardDuty analyzes API call patterns, geolocation anomalies, and impossible travel scenarios.

3

Botnet Recruitment

Compromised instances communicating with known command & control servers. GuardDuty detects unusual network patterns and malicious IP communications that traditional firewalls miss.

4

Data Exfiltration

Large data transfers to suspicious external destinations. GuardDuty monitors S3 access patterns and network traffic for signs of data theft.

GuardDuty Pricing for SMBs

GuardDuty uses pay-as-you-go pricing based on the volume of data analyzed:

  • CloudTrail management events: $4.00 per million events
  • VPC Flow Logs & DNS logs: $1.00/GB (first 500GB), with volume discounts
  • S3 data events: $0.80 per million events (first 500M)
  • 30-day free trial available for new accounts
💡
Cost Example: A small business with 10 EC2 instances and moderate traffic typically pays $30-50/month for GuardDuty—a fraction of the cost of a single security incident.
1

Enable GuardDuty with Optimal Settings

~5 minutes

Prerequisites

  • AWS account with administrative privileges
  • CloudTrail enabled (GuardDuty will enable automatically if needed)
  • AWS CLI configured with appropriate permissions

Console Steps

1.1 Navigate to GuardDuty Service

  • Sign in to AWS Console
  • Search for "GuardDuty" in the services search bar
  • Click on "Amazon GuardDuty"

1.2 Enable GuardDuty

  • Click "Get started" on the GuardDuty welcome page
  • Review the service overview and pricing
  • Click "Enable GuardDuty"
AWS CLI - Enable GuardDuty
# Create GuardDuty detector with optimal settings
aws guardduty create-detector \
    --enable \
    --finding-publishing-frequency FIFTEEN_MINUTES

# Get the detector ID for future commands
DETECTOR_ID=$(aws guardduty list-detectors --query 'DetectorIds[0]' --output text)
echo "GuardDuty Detector ID: $DETECTOR_ID"

# Verify the detector is enabled
aws guardduty get-detector --detector-id $DETECTOR_ID

1.3 Configure Finding Publishing Frequency

  • In the GuardDuty console, click "Settings"
  • Set "Finding publishing frequency" to "15 minutes" for faster threat response
  • Click "Save"
GuardDuty Active: Your threat detection is now running. GuardDuty will begin analyzing your environment immediately and generate findings within 15 minutes of detecting threats.

1.4 Enable Multi-Region Coverage

  • GuardDuty operates per-region—enable it in all regions for complete protection
  • Use the script below to enable across all regions
Bash Script - Enable GuardDuty in All Regions
#!/bin/bash
# Enable GuardDuty in all AWS regions

REGIONS=$(aws ec2 describe-regions --query 'Regions[].RegionName' --output text)

for region in $REGIONS; do
    echo "Enabling GuardDuty in region: $region"
    aws guardduty create-detector \
        --enable \
        --region $region \
        --finding-publishing-frequency FIFTEEN_MINUTES \
        2>/dev/null || echo "Already enabled or error in $region"
done

echo "GuardDuty enabled in all regions"
⚠️
Multi-Region Important: GuardDuty operates per-region. For complete protection, enable it in all regions where you have AWS resources, especially if you have a global infrastructure footprint.
2

Configure Threat Intelligence Feeds

~5 minutes

Enhance GuardDuty's detection capabilities by adding custom threat intelligence feeds specific to your industry and threat landscape.

Console Steps

2.1 Create Threat Intel Lists

  • In GuardDuty console, click "Lists" in the left navigation
  • Click "Add a threat list"
  • Choose between IP list or domain list format
  • Upload your threat intelligence file from S3 (plain text format)
Example - Malicious IPs List Format
# malicious-ips.txt - One IP or CIDR per line
192.0.2.100
198.51.100.0/24
203.0.113.50

2.2 Upload and Activate Threat List

  • First, upload your threat list file to an S3 bucket
  • Then create the threat intel set in GuardDuty
AWS CLI - Create Threat Intelligence List
# Upload threat list to S3
aws s3 cp malicious-ips.txt s3://your-security-bucket/threat-intel/

# Create threat intel set in GuardDuty
aws guardduty create-threat-intel-set \
    --detector-id $DETECTOR_ID \
    --name "Custom-Malicious-IPs" \
    --format TXT \
    --location s3://your-security-bucket/threat-intel/malicious-ips.txt \
    --activate

# Verify the threat intel set was created
aws guardduty list-threat-intel-sets --detector-id $DETECTOR_ID

2.3 Create Trusted IP List (Optional)

  • Add trusted IPs to prevent false positives from known-good sources
  • Include your office IPs, VPN endpoints, and partner networks
AWS CLI - Create Trusted IP List
# Create trusted IP list file
cat > trusted-ips.txt << EOF
# Office IPs
203.0.113.10
# VPN endpoint
198.51.100.25
EOF

# Upload to S3
aws s3 cp trusted-ips.txt s3://your-security-bucket/threat-intel/

# Create trusted IP set
aws guardduty create-ip-set \
    --detector-id $DETECTOR_ID \
    --name "Trusted-Office-IPs" \
    --format TXT \
    --location s3://your-security-bucket/threat-intel/trusted-ips.txt \
    --activate
💡
Pro Tip: Subscribe to commercial threat intelligence feeds like AlienVault OTX, Emerging Threats, or Talos Intelligence for the most current threat indicators. Update your lists regularly for maximum effectiveness.
3

Set Up Automated Response Workflows

~7 minutes

Configure automated responses to GuardDuty findings using EventBridge and Lambda to contain threats immediately without manual intervention.

Console Steps

3.1 Create SNS Topic for Alerts

  • Navigate to Simple Notification Service (SNS)
  • Click "Create topic"
  • Name: guardduty-security-alerts
  • Type: Standard
  • Create topic and add email subscriptions
AWS CLI - Create SNS Topic and Subscription
# Create SNS topic for GuardDuty alerts
aws sns create-topic --name guardduty-security-alerts

# Get the topic ARN
TOPIC_ARN=$(aws sns list-topics --query "Topics[?contains(TopicArn, 'guardduty-security-alerts')].TopicArn" --output text)

# Subscribe email to alerts (replace with your email)
aws sns subscribe \
    --topic-arn $TOPIC_ARN \
    --protocol email \
    --notification-endpoint security@yourcompany.com

echo "Check your email to confirm the subscription"

3.2 Create EventBridge Rule for GuardDuty Findings

  • Navigate to Amazon EventBridge
  • Click "Create rule"
  • Name: guardduty-high-severity-findings
  • Configure event pattern for GuardDuty findings
  • Set SNS topic as target
AWS CLI - Create EventBridge Rule
# Create EventBridge rule for high/medium severity findings
aws events put-rule \
    --name guardduty-high-severity-findings \
    --event-pattern '{
        "source": ["aws.guardduty"],
        "detail-type": ["GuardDuty Finding"],
        "detail": {
            "severity": [
                {"numeric": [">=", 4.0]}
            ]
        }
    }' \
    --description "Route high and medium severity GuardDuty findings to SNS"

# Add SNS topic as target
aws events put-targets \
    --rule guardduty-high-severity-findings \
    --targets "Id"="1","Arn"="$TOPIC_ARN"

3.3 Create Automated Isolation Lambda (Optional)

  • For critical findings, automatically isolate compromised instances
  • Create a Lambda function that modifies security groups
  • Trigger via EventBridge for high-severity EC2 findings
Python - Automated Instance Isolation Lambda
import json
import boto3
import os

def lambda_handler(event, context):
    """
    Automatically isolate EC2 instances flagged by high-severity GuardDuty findings.
    """
    
    # Extract finding details
    finding = event['detail']
    finding_type = finding['type']
    severity = finding['severity']
    
    # Only process high severity EC2-related findings
    if severity < 7.0 or 'EC2' not in finding_type:
        print(f"Skipping finding: {finding_type} (severity: {severity})")
        return {'statusCode': 200, 'body': 'Finding below threshold'}
    
    # Get instance ID from finding
    try:
        instance_id = finding['resource']['instanceDetails']['instanceId']
    except KeyError:
        print("No instance ID found in finding")
        return {'statusCode': 200, 'body': 'No instance to isolate'}
    
    ec2 = boto3.client('ec2')
    sns = boto3.client('sns')
    
    # Get or create isolation security group
    isolation_sg = get_or_create_isolation_sg(ec2)
    
    # Isolate the instance
    try:
        ec2.modify_instance_attribute(
            InstanceId=instance_id,
            Groups=[isolation_sg]
        )
        
        # Send notification
        message = f"""
GuardDuty Auto-Response: Instance Isolated

Instance ID: {instance_id}
Finding Type: {finding_type}
Severity: {severity}

The instance has been automatically isolated by removing all security groups 
and applying a quarantine security group that blocks all traffic.

Please investigate immediately.
        """
        
        sns.publish(
            TopicArn=os.environ['SNS_TOPIC_ARN'],
            Subject=f"[CRITICAL] Instance {instance_id} Isolated - GuardDuty",
            Message=message
        )
        
        print(f"Successfully isolated instance {instance_id}")
        
    except Exception as e:
        print(f"Failed to isolate instance: {e}")
        raise
    
    return {'statusCode': 200, 'body': f'Instance {instance_id} isolated'}


def get_or_create_isolation_sg(ec2):
    """Get existing or create new isolation security group."""
    
    sg_name = 'guardduty-quarantine-sg'
    
    # Check if SG already exists
    try:
        response = ec2.describe_security_groups(
            Filters=[{'Name': 'group-name', 'Values': [sg_name]}]
        )
        if response['SecurityGroups']:
            return response['SecurityGroups'][0]['GroupId']
    except:
        pass
    
    # Create isolation security group (blocks all traffic)
    # Note: You'll need to specify your VPC ID
    vpc_id = os.environ.get('VPC_ID')
    
    response = ec2.create_security_group(
        GroupName=sg_name,
        Description='Quarantine SG for compromised instances - blocks all traffic',
        VpcId=vpc_id
    )
    
    sg_id = response['GroupId']
    
    # Remove default outbound rule
    ec2.revoke_security_group_egress(
        GroupId=sg_id,
        IpPermissions=[{
            'IpProtocol': '-1',
            'IpRanges': [{'CidrIp': '0.0.0.0/0'}]
        }]
    )
    
    return sg_id
Automation Active: Your environment now has automated threat response. High-severity threats will trigger immediate notifications and optional containment actions.
4

Configure Monitoring and Alerting

~3 minutes

Integrate GuardDuty with Security Hub and configure finding exports for comprehensive security visibility.

Console Steps

4.1 Enable Security Hub Integration

  • Navigate to AWS Security Hub
  • Enable Security Hub if not already enabled
  • GuardDuty findings are automatically sent to Security Hub
AWS CLI - Enable Security Hub Integration
# Enable Security Hub (GuardDuty integration is automatic)
aws securityhub enable-security-hub

# Verify GuardDuty integration
aws securityhub get-enabled-standards

# List product subscriptions (should include GuardDuty)
aws securityhub list-enabled-products-for-import

4.2 Configure Finding Export to S3

  • Export findings to S3 for long-term storage and SIEM integration
  • Requires S3 bucket with appropriate permissions and KMS encryption
AWS CLI - Configure Finding Export
# Create S3 bucket for findings archive
aws s3 mb s3://guardduty-findings-archive-ACCOUNT_ID

# Create publishing destination (requires KMS key)
aws guardduty create-publishing-destination \
    --detector-id $DETECTOR_ID \
    --destination-type S3 \
    --destination-properties \
        DestinationArn=arn:aws:s3:::guardduty-findings-archive-ACCOUNT_ID,\
KmsKeyArn=arn:aws:kms:REGION:ACCOUNT_ID:key/YOUR_KMS_KEY_ID

4.3 Enable Protection Plans

  • Enable additional protection for specific workloads
  • S3 Protection: Monitors CloudTrail S3 data events
  • EKS Protection: Analyzes Kubernetes audit logs
  • RDS Protection: Monitors Aurora database login activity
  • Lambda Protection: Monitors Lambda network activity
  • Runtime Monitoring: Deep visibility into EC2, EKS, and ECS workloads
AWS CLI - Enable Protection Plans
# Update detector to enable S3 Protection
aws guardduty update-detector \
    --detector-id $DETECTOR_ID \
    --features Name=S3_DATA_EVENTS,Status=ENABLED

# Enable EKS Protection (if using EKS)
aws guardduty update-detector \
    --detector-id $DETECTOR_ID \
    --features Name=EKS_AUDIT_LOGS,Status=ENABLED

# Enable RDS Protection (if using Aurora)
aws guardduty update-detector \
    --detector-id $DETECTOR_ID \
    --features Name=RDS_LOGIN_EVENTS,Status=ENABLED

# Enable Lambda Protection
aws guardduty update-detector \
    --detector-id $DETECTOR_ID \
    --features Name=LAMBDA_NETWORK_LOGS,Status=ENABLED

# Verify enabled features
aws guardduty get-detector --detector-id $DETECTOR_ID \
    --query 'Features[*].{Name:Name,Status:Status}'
Monitoring Complete: Your GuardDuty setup now includes Security Hub integration, finding exports, and protection plans for comprehensive threat visibility.

Validate Your Configuration

Complete these checks to ensure GuardDuty is properly configured:

Test GuardDuty Detection

Use these safe commands to generate test findings and verify your setup:

Bash Script - Test GuardDuty Detection
#!/bin/bash
# GuardDuty Detection Test Script
# Uses AWS-provided safe test domains

echo "Testing GuardDuty detection capabilities..."
echo "============================================"

# Test 1: DNS query to GuardDuty test domain (safe)
echo ""
echo "Test 1: Malicious DNS detection..."
nslookup guarddutyc2activityb.com

# Test 2: Generate sample findings via API
echo ""
echo "Test 2: Generating sample findings..."
DETECTOR_ID=$(aws guardduty list-detectors --query 'DetectorIds[0]' --output text)
aws guardduty create-sample-findings --detector-id $DETECTOR_ID

# Test 3: Check for new findings
echo ""
echo "Test 3: Checking for findings..."
sleep 30  # Wait for findings to be processed

aws guardduty list-findings \
    --detector-id $DETECTOR_ID \
    --max-results 5

echo ""
echo "============================================"
echo "Testing complete!"
echo "Check the GuardDuty console for sample findings."
echo "Verify you received SNS notifications."
⚠️
Testing Safety: These test commands use AWS-provided safe test domains and the sample findings API. Never test with actual malicious domains or IPs that could compromise your environment.

Security Validation Script

Bash Script - Validate GuardDuty Configuration
#!/bin/bash
# GuardDuty Configuration Validation Script

echo "Validating GuardDuty Configuration..."
echo "======================================"

DETECTOR_ID=$(aws guardduty list-detectors --query 'DetectorIds[0]' --output text)

if [ -z "$DETECTOR_ID" ] || [ "$DETECTOR_ID" == "None" ]; then
    echo "✗ GuardDuty is NOT enabled in this region!"
    exit 1
fi

echo "✓ GuardDuty Detector ID: $DETECTOR_ID"

# Check detector status
echo ""
echo "Checking detector status..."
STATUS=$(aws guardduty get-detector --detector-id $DETECTOR_ID --query 'Status' --output text)
if [ "$STATUS" == "ENABLED" ]; then
    echo "✓ Detector status: ENABLED"
else
    echo "✗ Detector status: $STATUS"
fi

# Check finding publishing frequency
echo ""
echo "Checking finding publishing frequency..."
FREQUENCY=$(aws guardduty get-detector --detector-id $DETECTOR_ID --query 'FindingPublishingFrequency' --output text)
echo "  Finding frequency: $FREQUENCY"
if [ "$FREQUENCY" == "FIFTEEN_MINUTES" ]; then
    echo "✓ Optimal frequency configured"
else
    echo "! Consider setting to FIFTEEN_MINUTES for faster response"
fi

# Check enabled features
echo ""
echo "Checking enabled features..."
aws guardduty get-detector --detector-id $DETECTOR_ID \
    --query 'Features[*].{Feature:Name,Status:Status}' \
    --output table

# Check threat intel sets
echo ""
echo "Checking threat intelligence lists..."
THREAT_SETS=$(aws guardduty list-threat-intel-sets --detector-id $DETECTOR_ID --query 'ThreatIntelSetIds' --output text)
if [ -n "$THREAT_SETS" ]; then
    echo "✓ Custom threat intel lists configured"
else
    echo "! No custom threat intel lists (optional)"
fi

# Check for recent findings
echo ""
echo "Checking for recent findings..."
FINDING_COUNT=$(aws guardduty list-findings --detector-id $DETECTOR_ID --query 'length(FindingIds)' --output text)
echo "  Total findings: $FINDING_COUNT"

echo ""
echo "======================================"
echo "GuardDuty validation complete!"

Common Mistakes to Avoid

Enabling GuardDuty in only one region. Enable in all active regions for complete coverage. Attackers often target regions with less monitoring.

Ignoring low-severity findings. Even minor findings can indicate reconnaissance activities that precede major attacks. Review all findings regularly.

Not testing automated responses. Regularly verify your response workflows work correctly during an actual incident, not just in theory.

Failing to update threat intelligence lists. Outdated threat feeds miss new attack vectors and command & control infrastructure. Update lists monthly.

Over-suppressing findings. Be conservative with suppression rules to avoid missing variant attacks. Only suppress after thorough investigation.

Not enabling protection plans for your workloads. If you use EKS, RDS, Lambda, or S3 extensively, enable the corresponding protection plans for targeted threat detection.

Want Comprehensive AWS Security Monitoring?

GuardDuty is one layer of protection. AWSight automatically monitors your AWS environment against 500+ security best practices daily—providing unified visibility across GuardDuty findings, configuration issues, and compliance gaps.

References