What Makes a Good Foothold in AWS?
The single most consequential decision in an AWS security assessment is the one most teams make in 30 seconds: which identity do we start from? Pick the management-account admin and the agent dutifully reports that admin can do anything. Pick a sandboxed dev role with no outbound trust and the agent reports a small, neat graph that bears no resemblance to how a real breach would unfold. Pick the foothold an actual attacker would land on (the EC2 role on the public web service, the CI deploy role, the developer SSO permission set, the long-lived AKIA key in CircleCI) and the agent reports the breach you actually have.
Foothold quality is not a binary. It's a set of properties an attacker would grade your starting identity on, and an assessment that starts from a high-quality foothold tells you what an attacker would learn if they got there. This post is a guide for picking that identity.
What a foothold actually is
In hackaws.cloud the foothold is defined as "the starting principal (IAM role, IAM user, or SSO user) used to begin the assessment." That's the input shape the platform accepts, because IAM is where blast radius analysis works. But the concept of a foothold is broader, and a security program that thinks only in IAM principals leaves entire categories of risk untested.
There are three classes:
1. An IAM principal you can act as. A role you can assume, a user you can sign requests as, an SSO session you can replay. Permissions, trust relationships, and resource-based policies define everything reachable. Most of what follows in this post is about this class.
2. Compute running under a principal. A shell on an EC2 instance, code-exec inside a Lambda function, a session in a SageMaker notebook, RCE in a container. The IAM credential is implicit (recoverable from IMDS, the env, or the runtime SDK chain), but the foothold also includes everything else inside that process: environment variables, mounted secrets, files on disk, shell history, network position inside a VPC, and the ability to make outbound calls that legitimate workload makes.
3. A non-IAM credential that grants AWS-resource access. RDS Postgres or MySQL credentials. Redshift logins. DocumentDB and ElastiCache passwords. MSK SASL/SCRAM credentials. A presigned S3 URL. An object in a publicly readable bucket. IAM doesn't gate these, CloudTrail doesn't see the native-auth versions of most of them, and they have their own blast-radius rules. They're often the destination of a chain that starts with an IAM principal, but they can also be the start.
The platform takes class-1 footholds as direct input today, and uncovers class-2 and class-3 reach as part of the assessment. When you're picking what to test from, think across all three.
What makes a foothold valuable
Attackers don't pick footholds randomly. They optimise for outcomes (actions on objectives) and grade candidate footholds on a small number of properties that determine whether the foothold can convert into the outcome at acceptable cost and detection risk. The same properties define what makes a foothold worth assessing.
Reach worth measuring
The transitive graph of what the foothold unlocks: direct API permissions, plus everything reachable through sts:AssumeRole chains, iam:PassRole to compute, secretsmanager:GetSecretValue to a database password, s3:GetObject on a Terraform state file that contains every ARN in the environment, resource-based policies on cross-account buckets, and so on.
Reach is the ceiling on outcomes. A foothold with broad reach can complete more objectives. A foothold with narrow reach caps damage regardless of how clever the attacker is. The LexisNexis breach is the canonical worked example: the attacker landed on an ECS task role, and that role's transitive reach into Secrets Manager unlocked 536 Redshift tables and 3.9 million records. No privilege escalation was needed. The foothold's reach was the breach.
The grade isn't "how many actions does the policy allow." It's "how many high-value resources can I reach through every path the policy enables." A read-only role that can GetSecretValue on the prod RDS master password has more effective reach than a wildcard-looking role scoped to a single empty bucket.
Durable enough to model real dwell time
How long the access stays valid without re-acquisition. Long-lived IAM access keys (AKIA…) sit at one extreme: replayable for years, surviving the source application getting patched, surviving the original developer leaving the company. Short STS sessions and OIDC-federated credentials sit at the other: minutes to hours, expiring whether or not anyone notices.
Attackers strongly prefer durable footholds because their objectives often take longer than a single STS session. GitGuardian's 2025 State of Secrets Sprawl found that 70% of secrets leaked in 2022 were still valid in 2025, with three-year-old credentials still admitting attackers. Datadog's 2025 State of Cloud Security found that 59% of AWS IAM users with an access key have one older than a year. Durability isn't a quirk of a few sloppy environments. It's the median.
Foothold durability matters for assessment quality because it sets the realistic dwell time the test should model. A foothold that an attacker could keep for months reveals a different blast radius than one that expires in an hour: slow-burn data exfiltration, persistence creation, lateral movement that pauses for review windows. Pick a foothold whose durability profile matches what you're worried about.
Hard for existing detections to see
How much CloudTrail, GuardDuty, and your SIEM rules will notice when this foothold is exercised. Two factors decide it: the volume of "normal" activity the principal generates (more noise = better cover) and how closely the foothold's actions resemble that activity.
A CI deploy role calling cloudformation:UpdateStack, ecr:PutImage, iam:PassRole, and secretsmanager:GetSecretValue looks like Tuesday. The same calls from a long-dormant developer's user account would page someone within minutes. Service identities on tier-1 workloads are detection-blind by design. Their traffic is the baseline.
AWS-2025-021, the IMDS impersonation bulletin we analysed alongside other trust-boundary patterns, is a useful illustration: an attacker who can stand up a fake IMDS on 169.254.169.254 and inject credentials into a non-EC2 host produces zero CloudTrail signal until those credentials are used elsewhere (host-side IMDS traffic on non-EC2 nodes is the detection AWS recommends). The foothold itself is invisible. Its actions, when they happen, look like whatever the legitimate caller would have done.
The grade for an assessment foothold is the same: high-quality starting identities are ones where running the test produces traffic that wouldn't trip existing detections, because that's what an attacker's traffic from there would also look like. As a bonus, the assessment doubles as a detection test.
Information-dense host environment
When the foothold is compute (class 2), the value isn't only the IAM credential. It's everything else the process can read. The TeamPCP supply chain campaign is the worked example. The malicious LiteLLM payload didn't just grab ~/.aws/credentials. It harvested:
~/.aws/config(profile names reveal account topology)~/.bash_history(everyaws sts assume-role --role-arn arn:aws:iam::123456789012:role/deploycommand in history is free reconnaissance)~/.ssh/(cross-system pivots)~/.kube/configand service account tokens- Docker configs (ECR auth)
- Environment variables of every running process
- Shell-stored connection strings, IaC files in the working tree, git remote URLs
A foothold that teaches the attacker the next hop is qualitatively different from one that doesn't. The same is true for the assessment: starting on a developer laptop or CI runner, where the agent can see the trust topology rather than blind-discover it, surfaces paths that pure IAM-graph analysis would miss. If you're choosing between two compute footholds with similar reach, pick the one whose host environment leaks the most about your account graph.
Realistic to obtain externally
A foothold is only useful for an assessment if it represents a starting point a real attacker could plausibly land on. This is the criterion that disqualifies most "convenient" candidates: the unattached admin role, the role only assumable from inside the bastion VPC, the SSO permission set restricted to a specific corporate-network IP range.
Real attackers obtain footholds through a finite set of vectors:
- Internet-exposed compute (SSRF, RCE, deserialisation). Capital One and the 93 HackerOne reports we analysed both started here.
- Supply chain compromise of dependencies, base images, or CI tooling. The TeamPCP campaign trojanised LiteLLM (present in 36% of cloud environments) via a stolen PyPI publish token.
- PaaS / SaaS vendor compromise. The Vercel breach, CircleCI 2023, and Heroku 2022 all exfiltrated long-lived AWS keys customers had pasted into vendor env-var stores.
- Federated trust abuse. GitHub Actions OIDC roles, Vercel OIDC roles, third-party SaaS roles trusted via SAML or OIDC.
- Credential theft from leaked artefacts (
.envfiles, public S3 buckets, exposed.git/config) and infostealer logs (UAT-10608 collected 196 sets of AWS credentials this way).
Pick footholds that map cleanly to one of these vectors. An EC2 instance role on your public web service is realistic. A CI/CD deploy role is realistic. A developer SSO permission set is realistic. A break-glass role only assumable by the security team from a hardware-key-protected console session is not.
Cross-account or external trust outbound
The single property that most strongly increases reach without changing direct permissions: whether the foothold sits in an account that trusts other accounts, or whether the foothold itself is allowed to assume roles elsewhere. A foothold in a hub account with sts:AssumeRole into 12 spokes is qualitatively different from a foothold in an island account with no outbound trust.
The Harmonix bulletin (AWS-2025-031) shows the trust-policy version of this: roles that trust Principal: arn:aws:iam::ACCOUNT:root are effectively assumable by any identity in the account whose policies allow sts:AssumeRole on that role's ARN (or a wildcard covering it). We covered the broader pattern in AWS Keeps Breaking Its Own Trust Boundaries. For assessment-foothold selection: prefer footholds that sit at trust junctions. They surface the cross-account paths static IAM analysis tends to miss.
Additional things a security tester needs on top
Everything above is what makes a foothold valuable, full stop. The same criteria apply to attackers and assessments alike. An authorised assessment adds three operational constraints that an attacker doesn't share.
Production-safe to act from. The foothold has to be one the test can exercise without risking workload damage. A role that can rds-data:ExecuteStatement on the production cluster is technically an excellent foothold. Acting from it during an assessment is not. Pick footholds whose realistic action set is read-heavy or scoped to non-customer paths, or scope the assessment's technique categories to avoid destructive actions when the foothold is high-blast-radius.
Defensible to justify. The choice of foothold has to survive a conversation with engagement owners and auditors. "We started from the EC2 instance role on our public marketing site because that's our most-exposed compute" is defensible. "We started from the CFO's SSO session because we had her credentials" is not. Tie every foothold to a documentable threat scenario before you point an agent at it.
Reproducible and cleanly reversible. Assessments get re-run when scope changes, when remediation lands, when leadership wants comparative numbers. The foothold class needs to be re-establishable on demand, even if the specific credential expires. That means the role still exists, the trust policy still admits the test caller, and the test runner can mint fresh credentials without re-running upstream setup. Anything the assessment creates during execution (temporary IAM users, session tokens, modified trust policies) needs a documented cleanup path. The platform records every change with a cleanup command attached for exactly this reason.
Where candidate footholds live in your environment
Stop thinking in terms of "an IAM principal we have an access key for" and start enumerating the places real attackers land:
Internet-facing compute identities. EC2 instance profiles attached to instances with public ENIs. ECS task roles for tasks fronted by public ALBs or CloudFront. Lambda execution roles for functions exposed via API Gateway, Function URLs, or CloudFront. App Runner service roles. Anything reachable from 0.0.0.0/0 whose compromise yields the attached principal.
CI/CD identities. GitHub Actions OIDC roles. CodeBuild service roles. Deploy roles assumed cross-account from a CI runner. Long-lived IAM users still configured in a CI vendor's secret store.
Federated and SSO identities. SSO permission sets, especially developer roles with prod read access or staging admin. SAML-federated roles trusting your IdP. OIDC roles trusting GitHub, Vercel, or other vendors.
Vendor / PaaS-trusted roles. IAM roles trusted by Datadog, Snowflake, MongoDB Atlas, Vercel, or any third party that needs cross-account access. Each one is a foothold the moment that vendor has a bad day.
Tier-1 service identities. ECS task roles, Lambda execution roles, and EC2 instance profiles attached to your customer-data workloads, even when they're not internet-exposed. Lateral movement from a less-protected service can reach them.
Legacy long-lived IAM users. The 59% with access keys older than a year. The bot accounts created in 2019 and never reviewed. The shared user with three sets of AKIA keys whose owner left the company.
Non-IAM credentials. RDS user/password pairs hardcoded in app config. Redshift logins. MSK SASL credentials. Public S3 buckets. These don't go directly into the platform, but enumerating them is part of understanding your real attack surface, and they often define the destination of an IAM-class foothold's blast radius.
How to choose between candidates
A short decision sequence:
- Realistic to obtain externally? If a real attacker couldn't plausibly land here, deprioritise. Test results from unobtainable footholds are academic.
- Reach worth measuring? Especially: is the reach uncertain? An admin role's reach is "everything." Uninteresting. A scoped-looking task role whose transitive reach you don't yet know is the high-information bet.
- Production-safe to act from? If not, either pick a different foothold or scope the technique categories to avoid destructive actions.
- Detection-blind? If yes, the assessment also tests your detections by being invisible. If no, you'll get noise but still useful results.
- Maps to a documentable real-world breach scenario? If you can name the attack pattern this foothold simulates ("CI runner compromise like LiteLLM," "internet-facing service like Capital One," "PaaS vendor breach like Vercel"), the engagement narrative is built.
When two candidates tie, pick the one with more cross-account or external trust outbound. That's where unmeasured reach hides.
Common mistakes
The management-account admin. It's the easiest credential to grab and the worst foothold to test from. The output is "admin can do everything," which you already knew. You learn nothing about real attack paths.
The break-glass role. Bypasses normal controls by design. Its reach isn't representative of any real attack. Use the engagement budget on a foothold an attacker would actually obtain.
The isolated single-account dev role. No outbound trust, no cross-account assumption, no production secrets reachable. Yields a clean, small graph that misrepresents the environment. Useful only as a sanity check.
The "convenient" foothold. The role you happen to have an access key for in 1Password because the previous engineer set it up. Convenience is anti-correlated with realism. If you can only assume this role from your laptop on the corporate VPN, an attacker can't either.
Testing only one foothold. Different starting points reveal different paths. The blast radius from a CI deploy role is structurally different from the blast radius from an internet-facing service role. Run both. Compare them. The interesting findings are usually the paths that show up in one and not the other.
Recommended starting points for a hackaws.cloud assessment
Run an assessment from each of these in sequence, then compare the resulting attack graphs:
Your most-exposed internet-facing service's compute role. The EC2 instance profile, ECS task role, or Lambda execution role on whatever workload is most reachable from the public internet. Models the Capital One / SSRF-to-IMDS class of breach.
Your CI/CD deploy role. The role your build pipeline assumes to deploy infrastructure. Often the highest-reach principal in the entire environment because it has CloudFormation, IAM, and Secrets Manager access. Models the TeamPCP class of supply chain breach.
A typical developer SSO permission set. Whatever permission set most engineers assume day-to-day. Models the laptop-infostealer / OAuth-supply-chain class of breach (Vercel, Heroku, CircleCI).
A vendor-trusted role you'd find painful to lose. Whichever third party has the broadest cross-account access. Models the PaaS vendor breach class.
The four together cover the majority of real-world AWS breach origins. The platform's blast-radius output for each is the answer to "what would the next breach in our environment actually look like?"
Key takeaways
Foothold quality determines assessment quality. The same agent run from a different starting identity produces different findings, sometimes structurally different. The choice of foothold is the assessment.
Footholds come in three classes: an IAM principal you can act as, compute running under a principal, or a non-IAM credential. The platform takes class-1 footholds today, but a complete security view considers all three.
A good foothold is high-reach, durable, detection-blind, information-dense, realistically obtainable, and connected to outbound trust. These are the properties an attacker grades by, and they're the properties that make a test informative.
Assessment-specific constraints are operational, not analytical. Production safety, defensibility, and reproducibility don't change what you'd want to test from. They change how you act once the foothold is selected.
Avoid the convenient foothold. Admin roles, break-glass roles, isolated dev roles, and "the credential we have lying around" all produce results that don't map to real risk. Pick footholds an external attacker could actually obtain.
Run several, compare the graphs. A single assessment from a single foothold under-models the environment. Internet-facing compute, CI deploy, developer SSO, and vendor-trusted roles together cover most real breach origins.
Ready to find out what an attacker would unlock from your real footholds? Sign up for hackaws.cloud and start with the identity an attacker would actually land on.