Cloud accounts are the unit of blast radius. Organizations use separate accounts/subscriptions/projects for different environments (prod, staging, dev) or different teams. But workloads often need to cross accounts β a production app reading from a shared data lake, a logging pipeline collecting from many accounts. These cross-account integrations create attack paths.
Why this happens
The alternative to cross-account access is either (a) one giant account (terrible security boundary) or (b) duplicating everything per account (operationally miserable). So cross-account access is the practical middle ground. It works via trust relationships β account A’s IAM trusts account B’s principals to assume specific roles.
Mistakes:
- Trust policy uses
"Principal": {"AWS": "*"} β ANY AWS account can assume
- Trust policy uses broad account (e.g., the partner’s entire account) instead of specific role
- Trust without External ID condition (enables confused-deputy attacks)
- Role grant broader than needed (Owner when ReadOnly suffices)
- Cross-account CloudTrail not unified; attacker crosses but detection doesn’t follow
AWS cross-account attack
# Account A is your account. Account B has a role with broad trust
# Pacu can enumerate assumable roles
pacu > run iam__enum_assume_role --role-names partner-integration
# Or use aws CLI
aws sts assume-role \
--role-arn arn:aws:iam::B_ACCOUNT:role/shared-role \
--role-session-name test
# If trust is "Principal: AWS:*" β works from any account
# If trust is "AWS: A_ACCOUNT" β works from A to B
# If trust requires External ID β need to know the ID (often a secret)
# Upon assuming, check permissions in B
aws sts get-caller-identity # verify assumption worked
aws s3 ls # what's visible?
aws iam list-users # privilege escalation path?
Confused deputy + External ID
AWS’s specific guidance: when giving cross-account access to a third-party, use External ID. Third-party signs each AssumeRole with the External ID; other customers of that third-party can’t impersonate you. Without External ID, if third-party’s account is compromised or misconfigured, all their customers are exposed.
# Correct trust policy with External ID
{
"Effect": "Allow",
"Principal": {"AWS": "THIRDPARTY_ACCOUNT_ID"},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {"sts:ExternalId": "UNIQUE_TO_YOU_VALUE"}
}
}
Azure cross-tenant / cross-subscription
Azure has guest user invitations + B2B. External user invited to your tenant β access resources. If permissions over-granted, external user has broad access.
Azure Lighthouse lets MSPs manage customer tenants. Compromise of MSP = compromise of all customer tenants they manage. 2020 Kaseya MSP compromise spread ransomware to downstream customers via this pattern.
π Intermediate Module Β· Basic Tier
Continue reading with Basic tier (βΉ499/month)
You've read 33% of this module. Unlock the remaining deep-dive, quiz, and every other Intermediate module.
99+ modulesAll levels up to this tier
20-question quizzesUnlimited retries with explanations
Completion certificatesShareable on LinkedIn
3 more sections locked below