Introduction
In today’s fast-paced cloud environment, security incidents can occur at any time. Responding quickly and effectively is crucial to minimizing their impact. AWS Security Hub provides a centralized view of your security posture across your AWS accounts and services. However, manually responding to findings can be time-consuming and error-prone. This article demonstrates how to automate incident response using AWS Security Hub, Lambda, and EventBridge, enabling you to streamline your security workflows and significantly reduce response times.
Understanding the Components
Before diving into the implementation, let’s understand the key components involved:
AWS Security Hub: A security service that aggregates, organizes, and prioritizes security alerts, or findings, from multiple AWS services, such as AWS Config, GuardDuty, Inspector, and IAM Access Analyzer. It also integrates with third-party security products.
AWS Lambda: A serverless compute service that lets you run code without provisioning or managing servers. We’ll use Lambda to execute automated response actions based on Security Hub findings.
Amazon EventBridge: A serverless event bus service that allows you to route events between AWS services, SaaS applications, and custom applications. We’ll use EventBridge to trigger our Lambda function when a new Security Hub finding matches specific criteria.
Use Case: Automatically Isolating Compromised EC2 Instances
Let’s consider a common use case: automatically isolating a compromised EC2 instance detected by GuardDuty. When GuardDuty detects suspicious activity on an EC2 instance, it generates a finding in Security Hub. Our automation will then:
- Receive the Security Hub finding via EventBridge.
- Trigger a Lambda function.
- The Lambda function will:
- Identify the compromised EC2 instance.
- Update the EC2 instance’s security group to restrict all inbound and outbound traffic, effectively isolating it.
- Optionally, send a notification to a security team via SNS or Slack.
Implementation Steps
1. Configure AWS Security Hub
Ensure that AWS Security Hub is enabled in your AWS account and region. Enable integration with GuardDuty (or other security services you want to monitor). This will ensure that findings from these services are automatically ingested into Security Hub.
2. Create an IAM Role for the Lambda Function
The Lambda function needs permissions to access Security Hub, EC2, and potentially SNS (for notifications). Create an IAM role with the following policies:
AWSLambdaBasicExecutionRole: Provides basic permissions for Lambda execution.AmazonEC2ReadOnlyAccess: Allows the Lambda function to read EC2 instance information.AmazonEC2FullAccess: Allows the Lambda function to modify EC2 instance security groups. Use with caution and consider least privilege.SecurityHubReadOnlyAccess: Allows the Lambda function to read Security Hub findings.SNS:Publish: (Optional) Allows the Lambda function to publish notifications to an SNS topic.
Here’s an example policy you can attach to the role. Remember to adjust permissions based on your specific requirements:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:*:*:*"
},
{
"Effect": "Allow",
"Action": [
"ec2:DescribeInstances",
"ec2:DescribeSecurityGroups"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"ec2:ModifySecurityGroupRules",
"ec2:RevokeSecurityGroupIngress",
"ec2:RevokeSecurityGroupEgress",
"ec2:AuthorizeSecurityGroupIngress",
"ec2:AuthorizeSecurityGroupEgress"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"securityhub:GetFindings",
"securityhub:BatchUpdateFindings"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"sns:Publish"
],
"Resource": "arn:aws:sns:YOUR_REGION:YOUR_ACCOUNT_ID:YOUR_SNS_TOPIC"
}
]
}
Replace YOUR_REGION, YOUR_ACCOUNT_ID, and YOUR_SNS_TOPIC with your actual values.
3. Create the Lambda Function
Create a new Lambda function in the AWS Management Console. Choose Python 3.x as the runtime and select the IAM role you created in the previous step.
Here’s a Python code example for the Lambda function:
import boto3
import json
ec2 = boto3.client('ec2')
securityhub = boto3.client('securityhub')
sns = boto3.client('sns')
def lambda_handler(event, context):
"""
This function is triggered by EventBridge when a Security Hub finding is generated.
It isolates the compromised EC2 instance by updating its security group.
"""
try:
finding = event['detail']
finding_arn = finding['Id']
instance_id = None
# Extract instance ID from the finding
for resource in finding['Resources']:
if resource['Type'] == 'AwsEc2Instance':
instance_id = resource['Id']
break
if not instance_id:
print("No EC2 instance ID found in the finding.")
return {
'statusCode': 200,
'body': json.dumps('No EC2 instance ID found.')
}
print(f"Compromised EC2 Instance ID: {instance_id}")
# Get the current security groups associated with the instance
response = ec2.describe_instances(InstanceIds=[instance_id])
security_group_ids = [sg['GroupId'] for sg in response['Reservations'][0]['Instances'][0]['SecurityGroups']]
print(f"Security Groups associated with instance: {security_group_ids}")
# Create a new security group for isolation
isolation_group_name = f'isolation-group-{instance_id}'
isolation_group_description = f'Isolation group for compromised instance {instance_id}'
try:
new_security_group = ec2.create_security_group(
GroupName=isolation_group_name,
Description=isolation_group_description,
VpcId=response['Reservations'][0]['Instances'][0]['VpcId']
)
isolation_group_id = new_security_group['GroupId']
print(f"Created new isolation security group: {isolation_group_id}")
except Exception as e:
print(f"Error creating security group: {e}")
isolation_group_id = None # Handle the case where group creation fails
if isolation_group_id:
# Revoke all ingress and egress rules from existing security groups
for sg_id in security_group_ids:
try:
ec2.revoke_security_group_ingress(GroupId=sg_id, IpPermissions=[{'IpProtocol': '-1', 'IpRanges': [{'CidrIp': '0.0.0.0/0'}] }])
ec2.revoke_security_group_egress(GroupId=sg_id, IpPermissions=[{'IpProtocol': '-1', 'IpRanges': [{'CidrIp': '0.0.0.0/0'}] }])
print(f"Revoked ingress and egress rules from security group: {sg_id}")
except Exception as e:
print(f"Error revoking rules from security group {sg_id}: {e}")
# Associate the new isolation security group with the instance
try:
ec2.modify_instance_attribute(InstanceId=instance_id, Groups=[isolation_group_id])
print(f"Associated isolation security group {isolation_group_id} with instance {instance_id}")
except Exception as e:
print(f"Error associating isolation security group: {e}")
# Optionally, send a notification to a security team via SNS
# Replace with your SNS topic ARN
sns_topic_arn = 'arn:aws:sns:YOUR_REGION:YOUR_ACCOUNT_ID:YOUR_SNS_TOPIC'
message = f"Security Hub finding detected a compromised EC2 instance ({instance_id}). Instance has been isolated using security group {isolation_
