
The AWS Puzzle: From IMDSv2 to the CloudTrail trap for $0 USD (Part 2: The Defense)
When an oversight opens a breach in the cloud, the answer is not spending more—it is understanding the architecture. In this second post, we remediate Part 1's attack by enforcing IMDSv2, replace SSH keys with Session Manager, and explore the lesson I shared live at AWS Community Day Peru 2026: why confidential S3 downloads are not logged in CloudTrail by default, and how to audit your infrastructure for $0 USD.
Series: The AWS Oversights Puzzle (Level 100: Fundamentals) (2 articles)
- 2The AWS Puzzle: From IMDSv2 to the CloudTrail trap for $0 USD (Part 2: The Defense) This article
This article is an English edition of my original post published on AWS Builder Center (read in Spanish ). While the live demonstration video and conference slides were presented in Spanish at AWS Community Day Peru 2026, all step-by-step commands, CDK templates, and repository instructions are universal so you can deploy, remediate, and audit every defensive layer in your own AWS account.
Prefer watching the live conference session and demo?
You can check out the recording of my talk at AWS Community Day Peru 2026 (at timestamp 02:51:22) , where I demonstrate the live attack, the defense, and the modular AWS CDK architecture
From alert to remediation: hardening without breaking production
In the first part of this series, we explored the attack vector I presented at AWS User Group Minatitlán: how a single targeted
curl command could compromise an EC2 instance by exploiting a flaw in a web application, query internal instance metadata to steal temporary credentials, and escalate privileges through an IAM role—opening the door to everything that role allowed, from accessing internal services to downloading a confidential tax invoice stored in Amazon S3. In a controlled lab, it serves as an illustrative exercise, but in a real-world environment, it represents a severe security incident.To tackle the defensive side with a modern, modular architecture, I developed an implementation built with AWS CDK that I recently presented at AWS Community Day Peru 2026 (Lima / Virtual). During that session, I focused on how to neutralize these security blind spots directly from the cloud infrastructure itself and examined what audit records are genuinely preserved in an AWS account.
A note on this series:
This article is Part 2 of an ongoing series on practical security and auditing in AWS (in the first installment we covered the offensivecurlvector, and in the next post we will analyze web application security posture in AWS). However, this defensive guide is designed to be 100% self-contained, allowing you to read, understand, and apply it directly within your own AWS account.
Today, we step into the shoes of the defensive team (Blue Team). The challenge I set for myself when building this lab was straightforward: how do we remediate this breach directly at the AWS infrastructure layer, without disrupting existing workloads, and while staying strictly within the AWS Free Tier ($0 USD)?
Let's walk through the solution layer by layer, from compute hardening to forensic audit logs.
1. Hardening compute: patch the web application or harden the cloud?
When we saw the attacker abuse the web application to extract temporary instance credentials, the most immediate developer instinct was to patch the code: "let me open the Python script and add an input validation filter to reject the IP address
169.254.169.254".This does solve the immediate problem on that specific endpoint. But in production architectures, we must ask a much deeper question: what happens if another microservice is deployed on that same machine tomorrow and forgets that check? Or what happens if an open-source library or external dependency introduces an unpatched Server-Side Request Forgery (SSRF) flaw?
The fundamental architectural principle in cloud security is that infrastructure must defend itself, regardless of software flaws that might exist at the application layer. In AWS, the native mechanism to mitigate this vector is IMDSv2.

Infrastructure-level hardening: enforcing IMDSv2 on the EC2 instance to neutralize unauthorized SSRF requests.
How does IMDSv2 neutralize the attack?
Every EC2 instance includes access to the internal Instance Metadata Service (IMDS), allowing applications running on the host to query their own configuration and retrieve temporary security credentials tied to their IAM instance profile.
In the legacy version (IMDSv1), the service answered simple, unauthenticated
GET requests. If a vulnerable web application made an internal request toward 169.254.169.254, the metadata service handed over security tokens to whoever asked. That is why the SSRF attack succeeded in our first article.IMDSv2 fundamentally changes this behavior by enforcing a token-oriented session workflow:
- First, the client must initiate a session by sending an
HTTP PUTrequest containing a special header (X-aws-ec2-metadata-token-ttl-seconds) to request a short-lived session token. - Next, the client must include that token in the request header of every subsequent
GETrequest.
Why does this kill the attack at its root? Because standard SSRF web vulnerabilities can only force the target server to execute simple
GET requests. They lack the ability to inject custom HTTP headers or execute the preceding PUT handshake needed to retrieve the session token. As a result, the request is immediately rejected with an HTTP 401 Unauthorized status code.To enforce IMDSv2 on your instance directly from your terminal:
1
2
3
4
aws ec2 modify-instance-metadata-options \
--instance-id <YOUR-INSTANCE-ID> \
--http-tokens required \
--http-put-response-hop-limit 1The operational purpose of these two parameters:
--http-tokens required: Enforces mandatory session tokens. Any request attempting to use legacy IMDSv1 is rejected automatically.--http-put-response-hop-limit 1: Restricts the token response packet to a single network hop. If the application runs inside a Docker container on the host, the token packet cannot cross the virtual bridge into the container, preventing containerized workloads from requesting host credentials.
Validating live: the real test
In security and auditing, we never assume something is protected just because we checked a box or ran a terminal command. We must validate by re-testing the attack vector.
Using our interactive assistant
./redteam (Option 6 - Blue Team Mode), after enforcing IMDSv2 and enabling S3 Block Public Access, we rerun our validation suite:- Test against IMDSv2: We trigger the SSRF request searching for the IAM role at
169.254.169.254. The instance responds withHTTP 401 Unauthorized. While the application code remains vulnerable, credential extraction is completely blocked at the infrastructure layer. - Test against S3: We attempt to fetch the confidential file using
curl -I. Amazon S3 returnsHTTP 403 Forbidden. The global block prevents anonymous downloads even if the bucket policy permits public read access.
The production dilemma: why hasn't every company enabled IMDSv2 yet?
In security whitepapers, the advice sounds trivial: "enforce IMDSv2 everywhere". But in enterprise environments, this change requires evaluating software dependencies to avoid outages:
- Legacy systems: If an organization runs applications built with older AWS SDKs (Java SDK v1, Python boto2, or legacy PHP libraries), those versions do not support the two-step token flow. Enforcing IMDSv2 without testing will prevent applications from refreshing temporary credentials, causing sudden downtime.
- Safe migration strategy:
- Pre-migration CloudWatch monitoring: Track the metric
MetadataNoToken. If it stays consistently at zero, it is safe to enforce IMDSv2. If calls are recorded, identify and update the outdated SDKs first. - Host-level operating system controls: If you cannot enforce IMDSv2 immediately, configure local Linux firewall rules (
iptables) to block the web server user (www-data) from reaching169.254.169.254, restricting metadata access solely to root or approved system daemons. - Least privilege principle: The IAM role attached to the instance must never grant wildcard administrator permissions (
*). By strictly scoping permissions, the blast radius of any potential leak is minimized.
- Pre-migration CloudWatch monitoring: Track the metric
Auditing instance metadata in 5 seconds (for $0 USD)
Official AWS compliance guides state: "Detecting instances with IMDSv1 is accomplished by enabling AWS Config rule
ec2-imdsv2-check". On paper, this is ideal.But let's be honest: in a small business, a startup, or a personal learning project, do you actually keep AWS Config running across all regions 24/7, or did you turn it off after month one to prevent unexpected credit card charges?
AWS Config is a powerful governance tool, but it is not your only option. If you do not have the budget to keep it continuously enabled, you can audit which instances permit IMDSv1 in 5 seconds and at zero cost ($0 USD) with a single AWS CLI command:
1
2
3
4
aws ec2 describe-instances \
--filters Name=metadata-options.http-tokens,Values=optional \
--query 'Reservations[*].Instances[*].[InstanceId, State.Name, Tags[?Key==`Name`].Value|[0]]' \
--output tableIn cloud security, there is no single dogmatic path: some teams enforce blocking at the root using Service Control Policies (SCPs) in AWS Organizations, while others audit with open-source scanners like Prowler. What matters most is maintaining visibility without relying on tools you cannot afford.
2. Hardening access: migrating from Port 22 to AWS Systems Manager
Once the instance is shielded against metadata extraction, the next common misconfiguration lies in how administrators connect to it.
A frequent mistake when starting out in AWS is leaving port 22 (SSH) open to
0.0.0.0/0 in the Security Group to allow management from anywhere, while storing private .pem keys on personal laptops.This approach introduces severe operational risks: any server exposing port 22 to the public internet is subject to relentless automated scanning, and an accidental commit of a private key to a repository can immediately compromise the server.
The modern, free alternative is AWS Systems Manager (Session Manager). Instead of opening inbound ports or managing SSH key pairs, administrative connections are authenticated through the AWS console or the AWS CLI:
1
aws ssm start-session --target <YOUR-INSTANCE-ID>Operational advantages of Session Manager:
- Zero inbound ports open to the Internet: The Security Group requires zero inbound administrative rules.
- Elimination of
.pemkeys: No need to generate, distribute, or rotate private key files. - Centralized IAM control: Access is managed through AWS IAM policies with built-in multi-factor authentication (MFA) enforcement.
- Traceability and auditability: Every session initiation and command executed can be logged to CloudTrail or CloudWatch Logs.
3. Hardening data and logs: the great CloudTrail trap
With the compute instance hardened and port 22 closed, we turn our attention to Amazon S3 and a pervasive assumption: believing that CloudTrail was watching everything.
There is a widespread misconception that AWS CloudTrail automatically records every single operation occurring inside an AWS account simply because it is enabled.
I demonstrated this reality live during my session at AWS Community Day Peru 2026: after downloading a file from Amazon S3, we opened the CloudTrail console to inspect the
GetObject event... and the event history showed absolutely nothing.
The CloudTrail trap: default $0 USD event history only records Management Events; auditing S3 downloads requires enabling Data Events.
The technical reason behind this behavior lies in how CloudTrail categorizes events:
- Management Events: Infrastructure-level changes, such as launching EC2 instances, modifying Security Groups, or deleting IAM roles. These are enabled by default in the event history and are free for the last 90 days.
- Data Events: Object-level operations inside Amazon S3 (
GetObject,PutObject). These are not enabled by default due to high-volume scale and cost: imagine an e-commerce platform or media site serving millions of image downloads every hour; if CloudTrail logged every single download by default, customer bills and storage usage would skyrocket within hours.
If an attacker uses
curl to download a confidential document from S3, the default $0 USD event history will not record which files were accessed.In compliance auditing (such as ISO 27001 or SOC 2), documented evidence is the foundation of internal control. The recommended strategy is not to turn on Data Events blindly across an entire account, but to enable Data Events selectively on high-risk buckets:
- Buckets storing database or system backups.
- Buckets containing financial records, contracts, or confidential invoices.
- If real-time monitoring is required, configure event triggers (Amazon EventBridge rules or S3 Event Notifications) to raise alerts on suspicious access patterns.
Keep financial transparency in mind: CloudTrail Data Events are a paid feature (billed per 100,000 events recorded). In learning labs or test accounts, enable them strictly while executing your audit tests and remember to disable them afterward to keep your account balance at zero.
4. From patching to designing: the 4 blind spots with AWS CDK
Patching an instance on the fly and adjusting security rules by hand solves an emergency. But in professional environments, our goal as a Blue Team is to design architectures that are secure by default using Infrastructure as Code (IaC).
For the live demonstration in Peru, I built a modular architecture using AWS CDK (TypeScript) (official GitHub repository ) addressing the 4 most common cloud security blind spots:
- Least Privilege IAM: Instead of static credentials or overly broad roles with wildcard
*permissions, the application is strictly restricted tos3:PutObjectscoped to an upload prefix. (Today, open-source tools from AWS Labs like IAM Policy Autopilot enable teams to automatically generate scoped policies by analyzing application source code). - Multi-layer Network Perimeter: Pairing Security Groups (stateful firewalls at the network interface level) with Network ACLs (stateless filters at the subnet level) to immediately enforce IP-based blocks using explicit
DENYrules. - Private Amazon S3 + Pre-signed URLs (STS SigV4): To deliver confidential files (such as PDFs or certificates), the S3 bucket remains 100% private. The application requests a temporary access pass from AWS STS signed with SigV4, valid for only 15 minutes.
- CloudTrail Auditing: Leveraging the 90-day event history to audit which IAM identities or roles executed infrastructure changes.
Don't have an AWS account or prefer exploring the console before installing anything?
For learners who do not have an active AWS account, do not wish to input a credit card, or simply want to review console behavior before touching code, I recorded 8 short console screen captures in the repository's/videosdirectory . You can inspect exactly what happens at each stage (Security Group warnings, STS SigV4 pre-signed downloads, NACL IP blocking, and teardown) without installing any local tools.
5. How to replicate, observe, or tear down the lab ($0 USD)
To help you learn at your own pace and according to your available resources, I have provided three options:
Option A: Replicate the attack vector and hot-patch defense (CloudFormation)
If you want to recreate Part 1's attack and apply live defense through the interactive terminal assistant:
1
2
3
git clone https://github.com/Siegfried-FS/lab-red-team.git
cd lab-red-team
./redteam(Select Option 6: Blue Team Mode to enforce IMDSv2 and validate SSRF mitigation).
Option B: Deploy the secure architecture from the talk (AWS CDK)
If you prefer deploying the modular Infrastructure as Code application presented at AWS Community Day Peru 2026:
1
2
3
git clone https://github.com/Siegfried-FS/aws-cloud-security-lab.git
cd aws-cloud-security-lab
./cloudsec
Official presentation at AWS Community Day Peru 2026: secure architecture with AWS CDK, blind-spot mitigation, and live demo.
Download the official presentation slides:
You can view or download the presentation slides in PDF format used during the Lima/Virtual session directly from the repository: AWSCommunityDayPeru2026_RobertoFlores.pdf on GitHub .
Option C: Learn without installing tools or creating an AWS account
Sometimes we don't have a payment card ready to register an AWS account, we are working on a restricted machine where we cannot install tools, or we simply want to grasp the concepts visually before touching a CLI.
To ensure everyone has access to learn, I recorded 8 short screen videos directly in the AWS console (free, no sign-up, and zero installation required). You can open them in your browser to inspect what happens behind the scenes:
- How AWS raises warnings when opening a Security Group to
0.0.0.0/0. - How S3 pre-signed URLs with STS SigV4 work in real time.
- How to block a malicious IP address using Network ACLs.
- How to audit events in CloudTrail and confirm the account is left completely clean at $0 USD.
- Watch the 8 step-by-step console demonstration videos on GitHub
Real-world budget and cost validation
- Cost on AWS: $0.00 USD. Both labs run within the AWS Free Tier (1
t2.microinstance and a few kilobytes in S3). - Clean teardown: The
./scripts/destroy.shscript (inlab-red-team) or./cloudsecdestroy option (inaws-cloud-security-lab) cleans up provisioned resources automatically.
An essential lesson on cloud auditing and costs:
"A terminal script might print a clean green message claiming everything is finished and your account is clean. But never rely solely on a script output: always log into the AWS web console or query the AWS CLI to verify with your own eyes that instances are genuinely in the 'Terminated' state. If an orphaned EBS volume or Elastic IP is left running due to a silent failure, AWS will continue billing you at the end of the month."

Financial audit validation: automated teardown and AWS CLI verification confirming the Terminated state to guarantee zero cost ($0 USD).
Questions I had to ask myself...
To close this article, I don't want to leave you with an exam quiz. Instead, I want to share the honest questions I had to ask myself when I started auditing my own cloud environments and labs:
- What vulnerability in my application or flaw in network routing could expose my host and allow someone to reach the metadata IP
169.254.169.254? For years, IMDSv1 was enabled by default, and many legacy AMIs still treat it as optional. When an application-level SSRF bug occurs, enforcing IMDSv2 at the infrastructure layer is the only barrier stopping credential extraction. - In how many past projects did I assign wildcard
*permissions to an IAM role just to get the application working without errors? Today, we don't need to guess policies blindly: open-source tools like AWS Labs' IAM Policy Autopilot or IAM Access Analyzer allow us to generate least-privilege policies based on static code analysis or observed network calls. - Did I genuinely assume CloudTrail was logging everything in my account? Our lab demonstrated the reality: the default $0 USD event history only tracks management events. If someone downloads confidential documents from S3, without active Data Events, the exfiltration happens in complete silence.
- Why do we still keep
.pemkeys on our laptops when every meetup and security talk reminds us it is an unsafe practice? Opening port 22 to0.0.0.0/0and storing private keys on local computers is an unnecessary risk when AWS Systems Manager (Session Manager) provides secure, IAM-authenticated, and 100% auditable access without exposing inbound ports.
In security, as in community, nobody is born knowing everything. Recognizing these misconfigurations in our own architectures is the genuine first step toward building stronger, cleaner, and more transparent cloud systems.
Have you encountered any of these misconfigurations in your own deployments or in real-world scenarios you experienced? I would love to read your thoughts and reflections in the comments below.
The bridge to Part 3: What happens when you expose your web application?
We have explored how to harden cloud infrastructure across compute, storage, and identity layers (EC2, S3, and IAM). But cloud security does not end at server configuration or access policies.
What happens when you deploy web applications or community sites on managed hosting platforms like AWS Amplify?
In Part 3, we will analyze a common blind spot: why so many production websites fail web security assessments due to delivery-layer oversights, what real-world obstacles arise when trying to achieve a top security grade, and how to address web posture from an auditor's perspective.
- Remediation Repository (Part 1): Siegfried-FS/lab-red-team
- CDK Architecture Repository (Peru Talk): Siegfried-FS/aws-cloud-security-lab
- Full Conference Session Recording: AWS Community Day Peru 2026 on YouTube (Timestamp 02:51:22)
- Console Demonstration Clips: 8 Step-by-Step Demo Videos on GitHub (MP4)
#content-creators-latam #AWS #Security #Community #BlueTeam #Auditing
Series: The AWS Oversights Puzzle (Level 100: Fundamentals) (2 articles)
- 2The AWS Puzzle: From IMDSv2 to the CloudTrail trap for $0 USD (Part 2: The Defense) This article
Enjoyed reading this content? Let the author know!
Your likes, comments, shares, and saves help creators reach more builders.
Loading recommendations
Loading article