AWS GuardDuty Complete Guide 2024: Threat Detection, Multi-Account Setup, Malware Protection & Automated Response
Master AWS GuardDuty with this comprehensive 3000+ word guide covering threat intelligence, multi-account deployment with Organizations, finding types and severity levels, suppression rules, S3/EKS/RDS/Lambda protection, malware scanning, EventBridge automation, Security Hub integration, and CloudWatch Events with 6+ production-ready code examples.
Amazon GuardDuty is AWS's intelligent threat detection service that uses machine learning, anomaly detection, and integrated threat intelligence to identify malicious activity and unauthorized behavior across your AWS environment. In an era where cloud security threats evolve daily—from cryptocurrency mining attacks to sophisticated data exfiltration attempts and ransomware campaigns—GuardDuty serves as your first line of defense, continuously monitoring billions of events without requiring any security infrastructure to deploy or manage.
This comprehensive guide covers everything you need to implement production-grade threat detection: from understanding GuardDuty's architecture and threat intelligence sources to deploying multi-account configurations with AWS Organizations, configuring suppression rules, enabling comprehensive protection for S3, EKS, RDS, and Lambda workloads, implementing malware protection, and building automated remediation pipelines with EventBridge, Lambda, and CloudWatch Events.
Understanding GuardDuty Fundamentals and Threat Intelligence
GuardDuty's power comes from its ability to analyze multiple data sources simultaneously using machine learning models trained on AWS's vast threat intelligence network. Unlike traditional security tools that rely solely on signature-based detection, GuardDuty employs behavioral analysis and continuously updated threat feeds to identify both known and unknown threats. Understanding these fundamentals helps you maximize detection coverage and troubleshoot any gaps in your security monitoring.
How GuardDuty Threat Intelligence Works
GuardDuty leverages several threat intelligence sources to identify malicious activity:
AWS Internal Threat Intelligence: AWS continuously monitors its global infrastructure, identifying malicious IP addresses, domains, and behavioral patterns across millions of customer accounts. This intelligence is automatically incorporated into GuardDuty's detection algorithms.
Third-Party Threat Feeds: GuardDuty integrates with commercial threat intelligence providers, including CrowdStrike and Proofpoint, to enhance detection capabilities with external threat data including command-and-control server lists, malware distribution networks, and cryptocurrency mining pools.
Machine Learning Models: GuardDuty establishes baseline behavior patterns for your AWS accounts and uses anomaly detection to identify deviations that may indicate compromise. These models analyze API call patterns, network traffic flows, and DNS query behaviors unique to your environment.
Custom Threat Lists: Organizations can supplement GuardDuty's built-in intelligence with their own threat indicators, including IP addresses from internal security research, industry-specific threat sharing communities (ISACs), or custom honeypot networks.
Core Data Sources Analyzed
AWS CloudTrail Management Events: GuardDuty analyzes all management API calls across your AWS account, detecting reconnaissance activities like DescribeInstances calls from unusual locations, privilege escalation attempts through IAM modifications, defense evasion through security group changes, and persistence mechanisms like unauthorized key creation. This includes analysis of both successful and failed API calls to detect brute force attempts.
AWS CloudTrail S3 Data Events: When S3 protection is enabled, GuardDuty monitors object-level API operations including GetObject, PutObject, DeleteObject, and ListObjects calls, detecting data exfiltration patterns, unusual access from new principals, ransomware-like bulk deletion or encryption activity, and public exposure of sensitive data.
VPC Flow Logs: Network traffic metadata (not packet contents) reveals port scanning activities, cryptocurrency mining communication to known mining pools, command and control (C2) server connections, data exfiltration through unusual protocols or destinations, and lateral movement within your VPC. GuardDuty processes these logs without requiring you to enable VPC Flow Logs separately—it accesses this data directly from the VPC infrastructure.
DNS Logs: GuardDuty analyzes DNS queries to detect communication with known malicious domains, DNS tunneling for data exfiltration (unusually long DNS queries), algorithmically generated domain (DGA) communications associated with malware, and cryptocurrency mining pool DNS lookups. Like VPC Flow Logs, GuardDuty accesses DNS data directly without requiring additional configuration.
Extended Protection Features: S3, EKS, RDS, Lambda, and Malware
GuardDuty has evolved beyond its original scope to provide comprehensive protection across multiple AWS service categories. Each protection feature addresses specific threat vectors relevant to modern cloud architectures.
S3 Protection Features
S3 Protection analyzes CloudTrail S3 data events to detect threats targeting your object storage. This is critical because S3 buckets often contain the most sensitive organizational data and are frequent targets for data exfiltration and ransomware attacks.
Key S3 Threat Detection Capabilities:
- Detection of anonymous access being granted to previously private buckets
- Identification of data access from known malicious IP addresses
- Anomalous data download patterns indicating potential exfiltration
- Policy changes that weaken bucket security posture
- Access from Tor exit nodes or anonymizing proxies
EKS Protection Features
EKS protection provides visibility into Kubernetes environments through two complementary mechanisms:
EKS Audit Logs: Monitors Kubernetes API server audit logs to detect suspicious container activities, privilege escalation within clusters through role binding manipulation, unauthorized access to Kubernetes secrets, suspicious pod deployments, and attempts to disable security controls.
EKS Runtime Monitoring: Provides real-time visibility into container and host-level activities within EKS clusters. This deploys a GuardDuty security agent (managed through an EKS add-on) that detects:
- Cryptocurrency mining processes within containers
- Reverse shell establishment and interactive shell spawning
- File integrity violations and suspicious binary execution
- Container escape attempts
- Privilege escalation through kernel exploits
RDS Protection Features
RDS Login Activity monitoring tracks authentication attempts to your RDS databases, providing crucial visibility into database security:
Brute Force Detection: Identifies patterns of failed login attempts that indicate password guessing attacks against RDS instances.
Anomalous Login Detection: Flags successful logins from unusual locations, at unusual times, or using unusual patterns that may indicate credential compromise.
Suspicious Database Activity: Detects unusual query patterns or access from unexpected principals that could indicate data theft or reconnaissance.
Lambda Network Activity Monitoring
Lambda protection analyzes VPC network activity from your Lambda functions to detect compromised functions:
- Communication with known malicious IP addresses or domains
- DNS queries to command-and-control infrastructure
- Unusual network patterns indicating function exploitation
- Data exfiltration attempts through network connections
- Cryptocurrency mining network activity from Lambda execution
Malware Protection for EC2 (EBS Volumes)
GuardDuty's malware protection provides agentless scanning of EBS volumes when suspicious activity is detected:
How It Works: When GuardDuty detects an EC2-related finding that suggests possible malware (such as communication with known C2 servers or cryptocurrency mining), it automatically initiates a scan of the EBS volumes attached to that instance. The scan creates a temporary snapshot, analyzes it for malware signatures and indicators of compromise, and reports findings without impacting the running instance.
Detection Capabilities:
- Known malware families and variants
- Cryptocurrency miners
- Rootkits and kernel-level threats
- Webshells and backdoors
- Potentially unwanted programs (PUPs)
Multi-Account GuardDuty Deployment with AWS Organizations
For enterprise environments, deploying GuardDuty across all accounts in your AWS Organization is essential. This centralized approach ensures consistent threat detection coverage and simplifies security operations through delegated administration.
Step 1: Designate a Delegated Administrator
First, designate your security account as the GuardDuty delegated administrator from your organization's management account. This follows AWS security best practices of separating security tooling from the management account:
# Run from the AWS Organizations management account
# Replace SECURITY_ACCOUNT_ID with your security tooling account ID
aws guardduty enable-organization-admin-account \
--admin-account-id 123456789012 \
--region us-east-1
# Verify the delegated administrator
aws guardduty list-organization-admin-accounts --region us-east-1
# List organization admin accounts across all regions
for region in $(aws ec2 describe-regions --query 'Regions[].RegionName' --output text); do
echo "Region: $region"
aws guardduty list-organization-admin-accounts --region $region
done
Step 2: Enable GuardDuty with All Protection Features Using Terraform
This comprehensive Terraform configuration creates a GuardDuty detector with all protection features enabled and configures automatic enrollment for new organization accounts:
# Terraform configuration for GuardDuty multi-account deployment
# Run this in your delegated administrator account
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
variable "environment" {
description = "Environment name for tagging"
default = "production"
}
# Create the GuardDuty detector with all features enabled
resource "aws_guardduty_detector" "main" {
enable = true
finding_publishing_frequency = "FIFTEEN_MINUTES"
datasources {
s3_logs {
enable = true
}
kubernetes {
audit_logs {
enable = true
}
}
malware_protection {
scan_ec2_instance_with_findings {
ebs_volumes {
enable = true
}
}
}
}
tags = {
Environment = var.environment
ManagedBy = "terraform"
Purpose = "security-monitoring"
Service = "guardduty"
}
}
# Enable EKS Runtime Monitoring with automatic agent management
resource "aws_guardduty_detector_feature" "eks_runtime" {
detector_id = aws_guardduty_detector.main.id
name = "EKS_RUNTIME_MONITORING"
status = "ENABLED"
additional_configuration {
name = "EKS_ADDON_MANAGEMENT"
status = "ENABLED"
}
}
# Enable Lambda Network Activity Monitoring
resource "aws_guardduty_detector_feature" "lambda_network" {
detector_id = aws_guardduty_detector.main.id
name = "LAMBDA_NETWORK_LOGS"
status = "ENABLED"
}
# Enable RDS Login Activity Monitoring
resource "aws_guardduty_detector_feature" "rds_login" {
detector_id = aws_guardduty_detector.main.id
name = "RDS_LOGIN_EVENTS"
status = "ENABLED"
}
# Configure organization-wide auto-enrollment
resource "aws_guardduty_organization_configuration" "main" {
detector_id = aws_guardduty_detector.main.id
auto_enable_organization_members = "ALL"
datasources {
s3_logs {
auto_enable = true
}
kubernetes {
audit_logs {
enable = true
}
}
malware_protection {
scan_ec2_instance_with_findings {
ebs_volumes {
auto_enable = true
}
}
}
}
}
# Configure organization feature settings for new members
resource "aws_guardduty_organization_configuration_feature" "eks_runtime_org" {
detector_id = aws_guardduty_detector.main.id
name = "EKS_RUNTIME_MONITORING"
auto_enable = "ALL"
additional_configuration {
name = "EKS_ADDON_MANAGEMENT"
auto_enable = "ALL"
}
}
resource "aws_guardduty_organization_configuration_feature" "lambda_org" {
detector_id = aws_guardduty_detector.main.id
name = "LAMBDA_NETWORK_LOGS"
auto_enable = "ALL"
}
resource "aws_guardduty_organization_configuration_feature" "rds_org" {
detector_id = aws_guardduty_detector.main.id
name = "RDS_LOGIN_EVENTS"
auto_enable = "ALL"
}
# Output the detector ID for reference
output "guardduty_detector_id" {
description = "The ID of the GuardDuty detector"
value = aws_guardduty_detector.main.id
}
output "guardduty_detector_arn" {
description = "The ARN of the GuardDuty detector"
value = aws_guardduty_detector.main.arn
}
Step 3: Enroll Existing Member Accounts with Python boto3
Use this Python script to programmatically enroll all existing organization accounts as GuardDuty members:
#!/usr/bin/env python3
"""
GuardDuty Multi-Account Enrollment Script
Enrolls all AWS Organization accounts as GuardDuty members.
Run this from the delegated administrator account.
"""
import boto3
from botocore.exceptions import ClientError
import time
import logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
def get_detector_id(guardduty_client):
"""Get the GuardDuty detector ID or create one if it doesn't exist."""
try:
detectors = guardduty_client.list_detectors()
if detectors['DetectorIds']:
return detectors['DetectorIds'][0]
# Create detector if none exists
response = guardduty_client.create_detector(
Enable=True,
FindingPublishingFrequency='FIFTEEN_MINUTES',
Features=[
{'Name': 'S3_DATA_EVENTS', 'Status': 'ENABLED'},
{'Name': 'EKS_AUDIT_LOGS', 'Status': 'ENABLED'},
{'Name': 'EBS_MALWARE_PROTECTION', 'Status': 'ENABLED'},
{'Name': 'RDS_LOGIN_EVENTS', 'Status': 'ENABLED'},
{'Name': 'LAMBDA_NETWORK_LOGS', 'Status': 'ENABLED'},
{'Name': 'EKS_RUNTIME_MONITORING', 'Status': 'ENABLED'}
]
)
return response['DetectorId']
except ClientError as e:
logger.error(f"Error getting/creating detector: {e}")
raise
def get_organization_accounts(organizations_client):
"""Retrieve all active accounts in the organization."""
accounts = []
paginator = organizations_client.get_paginator('list_accounts')
for page in paginator.paginate():
for account in page['Accounts']:
if account['Status'] == 'ACTIVE':
accounts.append({
'AccountId': account['Id'],
'Email': account['Email']
})
return accounts
def get_existing_members(guardduty_client, detector_id):
"""Get list of existing GuardDuty member account IDs."""
existing_members = set()
paginator = guardduty_client.get_paginator('list_members')
for page in paginator.paginate(DetectorId=detector_id):
for member in page.get('Members', []):
existing_members.add(member['AccountId'])
return existing_members
def enroll_member_accounts(guardduty_client, detector_id, accounts, current_account_id):
"""Enroll accounts as GuardDuty members."""
# Filter out the current (administrator) account
member_accounts = [acc for acc in accounts if acc['AccountId'] != current_account_id]
if not member_accounts:
logger.info("No member accounts to enroll.")
return
# Get existing members to avoid duplicates
existing_members = get_existing_members(guardduty_client, detector_id)
new_members = [acc for acc in member_accounts if acc['AccountId'] not in existing_members]
if not new_members:
logger.info("All accounts are already enrolled as members.")
return
logger.info(f"Enrolling {len(new_members)} new member accounts...")
# Process in batches of 50 (API limit)
batch_size = 50
for i in range(0, len(new_members), batch_size):
batch = new_members[i:i + batch_size]
try:
# Create members
response = guardduty_client.create_members(
DetectorId=detector_id,
AccountDetails=batch
)
# Check for unprocessed accounts
if response.get('UnprocessedAccounts'):
for unprocessed in response['UnprocessedAccounts']:
logger.warning(f"Failed to create member {unprocessed['AccountId']}: {unprocessed['Result']}")
else:
logger.info(f"Successfully created {len(batch)} members")
# Small delay to avoid throttling
time.sleep(0.5)
except ClientError as e:
logger.error(f"Error creating members: {e}")
def main():
# Initialize clients
session = boto3.Session()
guardduty = session.client('guardduty')
organizations = session.client('organizations')
sts = session.client('sts')
# Get current account ID
current_account = sts.get_caller_identity()['Account']
logger.info(f"Running from account: {current_account}")
# Get detector ID
detector_id = get_detector_id(guardduty)
logger.info(f"Using GuardDuty detector: {detector_id}")
# Get all organization accounts
accounts = get_organization_accounts(organizations)
logger.info(f"Found {len(accounts)} accounts in organization")
# Enroll member accounts
enroll_member_accounts(guardduty, detector_id, accounts, current_account)
# Verify enrollment
members = guardduty.list_members(DetectorId=detector_id)
logger.info(f"Total enrolled members: {len(members.get('Members', []))}")
for member in members.get('Members', []):
status = member.get('RelationshipStatus', 'Unknown')
logger.info(f" Account {member['AccountId']}: {status}")
if __name__ == "__main__":
main()
GuardDuty Finding Types and Severity Levels
GuardDuty categorizes findings into several types, each indicating different threat patterns. Understanding these categories and severity levels helps security teams prioritize response efforts effectively.
Severity Level Classification
GuardDuty assigns severity scores from 0.1 to 8.9, categorized into three levels:
High Severity (7.0-8.9): Indicates resources are likely compromised and require immediate investigation. Examples include active cryptocurrency mining, confirmed malware, or successful credential exfiltration.
Medium Severity (4.0-6.9): Suggests suspicious activity that warrants investigation. Examples include reconnaissance activities, policy violations, or unusual access patterns.
Low Severity (0.1-3.9): Indicates potentially unwanted or suspicious activity that may not indicate active compromise. Examples include port probes from non-malicious sources or minor policy violations.
Reconnaissance Findings
Reconnaissance findings indicate that an attacker is gathering information about your environment:
- Recon:EC2/PortProbeUnprotectedPort: An EC2 instance has an unprotected port being probed by a known malicious IP
- Recon:EC2/Portscan: An EC2 instance is performing outbound port scans, indicating potential compromise
- Recon:IAMUser/MaliciousIPCaller: API calls from a known malicious IP address
- Recon:IAMUser/TorIPCaller: API calls originating from a Tor exit node
- Discovery:S3/MaliciousIPCaller: S3 bucket enumeration from malicious sources
Trojan and Malware Findings
Trojan findings suggest that an EC2 instance may be infected with malware:
- Trojan:EC2/BlackholeTraffic: Communication with an IP that silently discards traffic
- Trojan:EC2/DropPoint: Communication with a known credential drop point
- Trojan:EC2/DGADomainRequest.B: DNS queries for algorithmically generated domains
- Execution:EC2/MaliciousFile: Malware detected on EBS volume scan
- Execution:ECS/MaliciousFile: Container with malware detected
UnauthorizedAccess Findings
These findings indicate potential unauthorized access to your AWS resources:
- UnauthorizedAccess:EC2/SSHBruteForce: SSH brute force attack detected
- UnauthorizedAccess:EC2/RDPBruteForce: RDP brute force attack detected
- UnauthorizedAccess:IAMUser/ConsoleLoginSuccess.B: Console login from unusual location
- UnauthorizedAccess:IAMUser/InstanceCredentialExfiltration.OutsideAWS: EC2 credentials used externally
- UnauthorizedAccess:S3/MaliciousIPCaller.Custom: S3 access from your custom threat list
CryptoCurrency Findings
Cryptocurrency mining is a common attack goal, often detectable through network patterns:
- CryptoCurrency:EC2/BitcoinTool.B: EC2 communicating with Bitcoin-related hosts
- CryptoCurrency:Runtime/BitcoinTool.B: Container querying mining pool IPs
- CryptoCurrency:Lambda/BitcoinTool.B: Lambda function mining communications
Configuring Suppression Rules
Suppression rules allow you to filter out findings that you've determined to be benign in your environment, reducing alert fatigue and helping security teams focus on genuine threats. Proper suppression rule configuration is essential for operational efficiency.
When to Use Suppression Rules
Legitimate Business Activities: Suppress findings for security scanning tools, penetration testing activities, or other authorized security assessments.
Known Infrastructure Patterns: Suppress findings for expected behaviors like regular vulnerability scans, automated backup systems, or monitoring tools that trigger false positives.
Accepted Risks: Suppress findings for calculated risks that have been reviewed and accepted through your risk management process.
Creating Suppression Rules with AWS CLI
# Get your detector ID
DETECTOR_ID=$(aws guardduty list-detectors --query 'DetectorIds[0]' --output text)
# Create a suppression rule for authorized penetration testing IPs
aws guardduty create-filter \
--detector-id $DETECTOR_ID \
--name "SuppressPenTestFindings" \
--description "Suppress findings from authorized penetration testing activities" \
--action ARCHIVE \
--finding-criteria '{
"Criterion": {
"service.action.networkConnectionAction.remoteIpDetails.ipAddressV4": {
"Equals": ["203.0.113.50", "203.0.113.51"]
},
"type": {
"Equals": [
"Recon:EC2/PortProbeUnprotectedPort",
"Recon:EC2/Portscan"
]
}
}
}'
# Create a suppression rule for security scanner tools
aws guardduty create-filter \
--detector-id $DETECTOR_ID \
--name "SuppressSecurityScannerFindings" \
--description "Suppress findings from authorized security scanning tools" \
--action ARCHIVE \
--finding-criteria '{
"Criterion": {
"resource.instanceDetails.tags.key": {
"Equals": ["SecurityScanner"]
},
"resource.instanceDetails.tags.value": {
"Equals": ["Authorized"]
},
"severity": {
"LessThanOrEquals": 4
}
}
}'
# List all suppression rules
aws guardduty list-filters --detector-id $DETECTOR_ID
# View suppression rule details
aws guardduty get-filter \
--detector-id $DETECTOR_ID \
--filter-name "SuppressPenTestFindings"
Suppression Rules Best Practices
- Document All Rules: Maintain documentation explaining why each suppression rule exists and when it should be reviewed
- Use Specific Criteria: Make suppression rules as specific as possible to avoid accidentally suppressing genuine threats
- Regular Review: Review suppression rules quarterly to ensure they remain appropriate
- Expiration Dates: Consider using automation to remove temporary suppression rules after pen tests complete
- Severity Limits: Generally avoid suppressing high-severity findings—investigate these even if they appear benign
Configuring Trusted IP and Threat Lists
Trusted IP lists help reduce false positives from known good sources, while threat lists allow you to add custom intelligence feeds from your security research or industry sharing communities.
Creating a Trusted IP List
# Create the trusted IP list file with CIDR notation
cat > trusted-ips.txt << 'EOF'
203.0.113.0/24
198.51.100.10/32
192.0.2.0/24
EOF
# Upload to S3 (bucket must be accessible by GuardDuty)
aws s3 cp trusted-ips.txt s3://my-security-bucket/guardduty/trusted-ips.txt
# Get your detector ID
DETECTOR_ID=$(aws guardduty list-detectors --query 'DetectorIds[0]' --output text)
# Create the trusted IP set
aws guardduty create-ip-set \
--detector-id $DETECTOR_ID \
--name "Corporate-Trusted-IPs" \
--format TXT \
--location "s3://my-security-bucket/guardduty/trusted-ips.txt" \
--activate
# Verify creation
aws guardduty list-ip-sets --detector-id $DETECTOR_ID
Creating a Custom Threat Intelligence List
# Create threat list file with known malicious IPs
cat > threat-intel.txt << 'EOF'
45.155.205.0/24
185.220.101.0/24
91.219.29.0/24
EOF
# Upload to S3
aws s3 cp threat-intel.txt s3://my-security-bucket/guardduty/threat-intel.txt
# Create the threat intel set
aws guardduty create-threat-intel-set \
--detector-id $DETECTOR_ID \
--name "Custom-Threat-Intel" \
--format TXT \
--location "s3://my-security-bucket/guardduty/threat-intel.txt" \
--activate
# Verify the threat intel set
aws guardduty list-threat-intel-sets --detector-id $DETECTOR_ID
CloudWatch Events and EventBridge Integration
GuardDuty publishes all findings to Amazon EventBridge (formerly CloudWatch Events), enabling powerful automated response workflows. This integration is the foundation for security automation and is essential for reducing mean time to remediation.
EventBridge Rule Patterns for GuardDuty
{
"source": ["aws.guardduty"],
"detail-type": ["GuardDuty Finding"],
"detail": {
"severity": [{"numeric": [">=", 7]}]
}
}
Complete CloudFormation Template for Automated Response
AWSTemplateFormatVersion: '2010-09-09'
Description: GuardDuty automated response with EventBridge and Lambda
Parameters:
SlackWebhookUrl:
Type: String
Description: Slack webhook URL for notifications
NoEcho: true
SeverityThreshold:
Type: Number
Default: 7
Description: Minimum severity to trigger automated response
Resources:
HighSeverityFindingsRule:
Type: AWS::Events::Rule
Properties:
Name: guardduty-high-severity-findings
Description: Capture high severity GuardDuty findings
EventPattern:
source:
- aws.guardduty
detail-type:
- GuardDuty Finding
detail:
severity:
- numeric:
- ">="
- !Ref SeverityThreshold
State: ENABLED
Targets:
- Id: ResponseLambda
Arn: !GetAtt ResponseFunction.Arn
- Id: NotificationSNS
Arn: !Ref NotificationTopic
AllFindingsRule:
Type: AWS::Events::Rule
Properties:
Name: guardduty-all-findings
Description: Capture all GuardDuty findings for logging
EventPattern:
source:
- aws.guardduty
detail-type:
- GuardDuty Finding
State: ENABLED
Targets:
- Id: CloudWatchLogs
Arn: !Sub 'arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:${FindingsLogGroup}'
FindingsLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: /aws/guardduty/findings
RetentionInDays: 365
NotificationTopic:
Type: AWS::SNS::Topic
Properties:
TopicName: guardduty-findings-notifications
KmsMasterKeyId: alias/aws/sns
NotificationTopicPolicy:
Type: AWS::SNS::TopicPolicy
Properties:
Topics:
- !Ref NotificationTopic
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: events.amazonaws.com
Action: sns:Publish
Resource: !Ref NotificationTopic
ResponseFunction:
Type: AWS::Lambda::Function
Properties:
FunctionName: guardduty-automated-response
Runtime: python3.11
Handler: index.handler
Timeout: 300
MemorySize: 256
Role: !GetAtt ResponseFunctionRole.Arn
Environment:
Variables:
SLACK_WEBHOOK_URL: !Ref SlackWebhookUrl
Code:
ZipFile: |
import json
import boto3
import urllib.request
import os
from datetime import datetime
ec2 = boto3.client('ec2')
iam = boto3.client('iam')
def handler(event, context):
print(f"Received event: {json.dumps(event)}")
finding = event['detail']
finding_type = finding['type']
severity = finding['severity']
account_id = finding['accountId']
region = finding['region']
response_actions = []
if 'EC2' in finding_type:
response_actions.extend(handle_ec2_finding(finding))
elif 'IAMUser' in finding_type:
response_actions.extend(handle_iam_finding(finding))
elif 'S3' in finding_type:
response_actions.extend(handle_s3_finding(finding))
send_slack_notification(finding, response_actions)
return {
'statusCode': 200,
'body': json.dumps({
'finding_type': finding_type,
'actions_taken': response_actions
})
}
def handle_ec2_finding(finding):
actions = []
resource = finding.get('resource', {})
instance_details = resource.get('instanceDetails', {})
instance_id = instance_details.get('instanceId')
if not instance_id:
return actions
finding_type = finding['type']
if 'CryptoCurrency' in finding_type:
try:
vpc_id = instance_details.get('networkInterfaces', [{}])[0].get('vpcId')
if vpc_id:
sg_response = ec2.create_security_group(
GroupName=f'guardduty-isolation-{instance_id}',
Description='Isolation SG created by GuardDuty response',
VpcId=vpc_id
)
isolation_sg = sg_response['GroupId']
ec2.modify_instance_attribute(
InstanceId=instance_id,
Groups=[isolation_sg]
)
actions.append(f'Isolated instance {instance_id} with SG {isolation_sg}')
except Exception as e:
actions.append(f'Failed to isolate {instance_id}: {str(e)}')
if 'BruteForce' in finding_type:
actions.append(f'Flagged instance {instance_id} for brute force attack review')
return actions
def handle_iam_finding(finding):
actions = []
resource = finding.get('resource', {})
access_key_details = resource.get('accessKeyDetails', {})
user_name = access_key_details.get('userName')
access_key_id = access_key_details.get('accessKeyId')
if 'CredentialExfiltration' in finding['type'] and access_key_id:
try:
iam.update_access_key(
UserName=user_name,
AccessKeyId=access_key_id,
Status='Inactive'
)
actions.append(f'Disabled access key {access_key_id} for user {user_name}')
except Exception as e:
actions.append(f'Failed to disable key: {str(e)}')
return actions
def handle_s3_finding(finding):
actions = []
bucket_name = finding.get('resource', {}).get('s3BucketDetails', [{}])[0].get('name')
if bucket_name:
actions.append(f'Flagged S3 bucket {bucket_name} for security review')
return actions
def send_slack_notification(finding, actions):
webhook_url = os.environ.get('SLACK_WEBHOOK_URL')
if not webhook_url:
return
severity_emoji = '🔴' if finding['severity'] >= 7 else '🟡' if finding['severity'] >= 4 else '🟢'
message = {
'blocks': [
{
'type': 'header',
'text': {'type': 'plain_text', 'text': f"{severity_emoji} GuardDuty Finding Detected"}
},
{
'type': 'section',
'fields': [
{'type': 'mrkdwn', 'text': f"*Type:*\n{finding['type']}"},
{'type': 'mrkdwn', 'text': f"*Severity:*\n{finding['severity']}"},
{'type': 'mrkdwn', 'text': f"*Account:*\n{finding['accountId']}"},
{'type': 'mrkdwn', 'text': f"*Region:*\n{finding['region']}"}
]
},
{
'type': 'section',
'text': {'type': 'mrkdwn', 'text': f"*Description:*\n{finding.get('description', 'No description')}"}
}
]
}
if actions:
message['blocks'].append({
'type': 'section',
'text': {'type': 'mrkdwn', 'text': f"*Automated Actions:*\n- " + "\n- ".join(actions)}
})
try:
req = urllib.request.Request(
webhook_url,
data=json.dumps(message).encode('utf-8'),
headers={'Content-Type': 'application/json'}
)
urllib.request.urlopen(req)
except Exception as e:
print(f"Failed to send Slack notification: {e}")
ResponseFunctionRole:
Type: AWS::IAM::Role
Properties:
RoleName: guardduty-response-function-role
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
Policies:
- PolicyName: GuardDutyResponsePolicy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- ec2:CreateSecurityGroup
- ec2:ModifyInstanceAttribute
- ec2:DescribeSecurityGroups
- ec2:DescribeInstances
Resource: '*'
- Effect: Allow
Action:
- iam:UpdateAccessKey
- iam:ListAccessKeys
Resource: '*'
LambdaPermission:
Type: AWS::Lambda::Permission
Properties:
FunctionName: !Ref ResponseFunction
Action: lambda:InvokeFunction
Principal: events.amazonaws.com
SourceArn: !GetAtt HighSeverityFindingsRule.Arn
Outputs:
ResponseFunctionArn:
Value: !GetAtt ResponseFunction.Arn
NotificationTopicArn:
Value: !Ref NotificationTopic
FindingsLogGroupName:
Value: !Ref FindingsLogGroup
Security Hub Integration
AWS Security Hub aggregates findings from GuardDuty, Amazon Inspector, Amazon Macie, and third-party tools into a unified security dashboard. This integration is essential for comprehensive security visibility and compliance monitoring.
Enabling Security Hub Integration
# Enable Security Hub with all standards
aws securityhub enable-security-hub \
--enable-default-standards \
--region us-east-1
# Verify GuardDuty integration is active
aws securityhub list-enabled-products-for-import \
--region us-east-1 \
--query "ProductSubscriptions[?contains(ProductArn, 'guardduty')]"
# Enable GuardDuty product subscription if not active
aws securityhub enable-import-findings-for-product \
--product-arn "arn:aws:securityhub:us-east-1::product/aws/guardduty" \
--region us-east-1
# Create a custom insight for GuardDuty findings
aws securityhub create-insight \
--name "High Severity GuardDuty Findings" \
--filters '{
"ProductName": [{"Value": "GuardDuty", "Comparison": "EQUALS"}],
"SeverityLabel": [{"Value": "CRITICAL", "Comparison": "EQUALS"}, {"Value": "HIGH", "Comparison": "EQUALS"}],
"RecordState": [{"Value": "ACTIVE", "Comparison": "EQUALS"}]
}' \
--group-by-attribute "ResourceType" \
--region us-east-1
Cost Optimization for GuardDuty
While GuardDuty provides essential security capabilities, costs can grow significantly with data volume in large environments. Understanding the pricing model and implementing optimization strategies is important for cost-effective security.
Understanding GuardDuty Pricing
GuardDuty charges are based on data volume analyzed:
- CloudTrail Events: Per million management events analyzed
- VPC Flow Logs: Per GB of logs analyzed
- DNS Logs: Per million DNS queries analyzed
- S3 Data Events: Per million S3 data events analyzed
- EKS Audit Logs: Per million events analyzed
- Runtime Monitoring: Per vCPU-hour monitored for EKS/ECS/EC2
- Malware Scans: Per GB of EBS volume scanned
Monitoring Usage and Costs
# View GuardDuty usage statistics
DETECTOR_ID=$(aws guardduty list-detectors --query 'DetectorIds[0]' --output text)
aws guardduty get-usage-statistics \
--detector-id $DETECTOR_ID \
--usage-statistic-type SUM_BY_DATA_SOURCE \
--usage-criteria '{"DataSources": ["CLOUD_TRAIL", "DNS_LOGS", "FLOW_LOGS", "S3_LOGS", "KUBERNETES_AUDIT_LOGS"]}'
# Get cost by feature
aws guardduty get-usage-statistics \
--detector-id $DETECTOR_ID \
--usage-statistic-type SUM_BY_FEATURE
Working with Warqline
We are a cloud engineering consultancy and an official AWS and Google Cloud partner. If you are running this in production and want a second pair of eyes, we scope work in a free 45-minute technical call: you describe what you are running and what worries you, and we tell you what we would look at first.
Conclusion: Building a Comprehensive Threat Detection Strategy
AWS GuardDuty is an essential component of any cloud security strategy, providing intelligent, managed threat detection that scales automatically with your AWS environment. By implementing the configurations and best practices outlined in this comprehensive guide, you can:
- Deploy organization-wide coverage using delegated administrator and auto-enrollment for consistent protection
- Enable comprehensive protection across EC2, S3, EKS, Lambda, RDS, and EBS workloads with malware scanning
- Reduce alert fatigue with properly configured suppression rules and trusted IP lists
- Leverage custom threat intelligence by integrating your organization's threat feeds
- Automate incident response using EventBridge, CloudWatch Events, and Lambda for faster remediation
- Centralize security visibility through Security Hub integration for unified compliance monitoring
- Optimize costs while maintaining effective threat detection coverage through usage monitoring
Remember that GuardDuty is most effective as part of a defense-in-depth strategy that includes preventive controls (IAM, VPC security groups, encryption), detective controls (CloudTrail, Config, GuardDuty), and responsive controls (automated remediation, incident response runbooks). The combination of intelligent threat detection with automated response capabilities dramatically reduces your mean time to detection and remediation.
For enterprise-grade security assessments that incorporate GuardDuty findings with comprehensive AWS Well-Architected reviews, talk to our engineers and start your security optimization journey today.