AWS Lambda Abuse: Function Hijacking, Layer Poisoning, IAM Pivot
Cloud Security
Offensive Lambda tradecraft covering function code hijack, layer poisoning, environment variable exfil, and the IAM pivot to broader cloud access.
By Arjun Raghavan, Security & Systems Lead, BIPI · December 9, 2024 · 11 min read
Lambda is convenient for developers and convenient for attackers. A serverless function carries an execution role, ships with environment variables, and runs in a runtime that almost nobody monitors. This post covers the Lambda-specific abuses we exercise on red team and BIPI cloud pentest engagements.
Initial access vectors
- lambda:UpdateFunctionCode on an existing function via a compromised CI role
- lambda:CreateFunction with iam:PassRole on a privileged service role
- Public function URLs left exposed by developers testing webhooks
- Misconfigured resource policies allowing cross-account invoke
Layer poisoning
Lambda layers are shared dependency bundles. If you can publish a new version of a layer that multiple functions reference, you have planted a supply chain backdoor inside the AWS account. The attack is quiet because layer updates do not change function code, and most CI pipelines do not pin layer versions.
- Identify layers shared by privileged functions via lambda:ListLayers and ListLayerVersions
- Publish a new version with a malicious shim in a commonly imported module
- Wait for the next function invocation; the new layer is pulled automatically
- Use the function execution role to enumerate IAM and pivot
Extracting credentials from the runtime
Inside the Lambda runtime, the execution role credentials are available via AWS_CONTAINER_CREDENTIALS_FULL_URI and the associated token. If your payload can read environment and make an outbound HTTPS call, you have the credentials. The exfil path of choice is a CloudFront-fronted attacker domain that blends with normal egress.
IAM pivot patterns
- Execution role with iam:PassRole and lambda:CreateFunction enables full self-replication
- Roles with secretsmanager:GetSecretValue * unlock production database credentials
- Roles with sts:AssumeRole on a cross-account role bridge into customer or partner accounts
- Roles with sns:Publish or eventbridge:PutEvents enable lateral movement via async triggers
A poisoned layer is a backdoor that survives function redeploys, because nobody pins layer versions and nobody scans layer contents.
Detection and CloudTrail blind spots
Lambda data events are off by default. Without them, you see the control plane changes but not the actual invocations. Even with them on, layer pulls happen behind the scenes and do not generate a CloudTrail entry the way a function code update does. This is why layer poisoning is attractive.
Remediation
- Pin layer versions in IaC and reject any drift in CI
- Move secrets out of env vars into Secrets Manager with rotation
- Scope execution roles to least-privilege, no wildcard service permissions
- Enable Lambda data events on production functions and alert on cross-region invocation
- Use code signing for Lambda functions, which prevents unsigned code updates
Wrap
Lambda makes attack and defense both faster. If your team has not run a Lambda-focused pentest, the result will be a long list of overprivileged execution roles and a small number of layers that quietly run in dozens of functions. Start with the layers.
Read more field notes, explore our services, or get in touch at info@bipi.in. Privacy Policy · Terms.