AWS Lambda Execution Role Privilege Escalation: Function Invocation for IAM Abuse
Théorie
Why This Matters
AWS Lambda execution role abuse is one of the most documented privilege escalation paths in cloud penetration testing. In the Rhino Security Labs research on AWS privilege escalation (2018, updated through 2023), Lambda-based escalation is listed as a primary vector: an attacker with lambda:InvokeFunction and iam:PassRole can inject arbitrary code into an existing Lambda function to exfiltrate credentials from its execution role — which frequently holds far broader permissions than the function requires. In real incidents, developers assign AdministratorAccess to Lambda functions "temporarily" for debugging and never remove it. Because the Lambda function appears in no interactive session and generates no console login events, the over-privilege persists unnoticed for months until an attacker discovers and exploits it.
Core Concept
Every AWS Lambda function executes under an execution role — an IAM role that the Lambda service assumes on behalf of the function when it runs. The function code can call any AWS API that the execution role's policies permit. This makes the execution role the critical security boundary for Lambda: the blast radius of a code injection or malicious invocation is exactly equal to the execution role's effective permissions.
Privilege escalation paths involving Lambda:
- lambda:UpdateFunctionCode + execution role with high privilege: An attacker who can update the function's code and then invoke it can run arbitrary commands under the execution role's identity.
- lambda:InvokeFunction on an existing over-privileged function: If the function already performs sensitive actions (writes to S3, reads from Secrets Manager, calls other APIs), an attacker who can invoke it may be able to exfiltrate data or trigger unintended operations.
- iam:PassRole + lambda:CreateFunction: An attacker with these permissions can create a new Lambda function and attach any role they can pass, then invoke the function to assume that role's permissions.
- Environment variable credential injection: If lambda:UpdateFunctionConfiguration is available, an attacker can inject environment variables that override expected configuration or exfiltrate the function's execution role credentials when the function next runs.
Execution role credentials are available inside the function via the standard AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and AWS_SESSION_TOKEN environment variables set automatically by the Lambda service, or via boto3.client() which reads them from the execution environment automatically.
Technical Deep-Dive
# Enumerate all Lambda functions in the region
aws lambda list-functions
--query 'Functions[*].{Name:FunctionName,Runtime:Runtime,Role:Role,Modified:LastModified}'
--output table
# Get full configuration for a specific function — reveals execution role ARN
aws lambda get-function-configuration --function-name TargetFunction
--query '{Role:Role,Runtime:Runtime,Env:Environment.Variables,VPC:VpcConfig}'
# Retrieve the execution role's attached policies
ROLE_NAME=$(aws lambda get-function-configuration --function-name TargetFunction
--query 'Role' --output text | awk -F'/' '{print $NF}')
aws iam list-attached-role-policies --role-name "$ROLE_NAME"
--query 'AttachedPolicies[*].{Name:PolicyName,Arn:PolicyArn}' --output table
aws iam list-role-policies --role-name "$ROLE_NAME"
# Retrieve the inline policy to inspect permissions
aws iam get-role-policy --role-name "$ROLE_NAME" --policy-name InlinePolicyName
--query 'PolicyDocument' --output json | python3 -m json.tool
# Simulate effective permissions of the execution role against high-value actions
aws iam simulate-principal-policy
--policy-source-arn "arn:aws:iam::ACCOUNT_ID:role/${ROLE_NAME}"
--action-names s3:GetObject iam:CreateUser secretsmanager:GetSecretValue
sts:AssumeRole ec2:DescribeInstances
--query 'EvaluationResults[*].{Action:EvalActionName,Decision:EvalDecision}'
--output table
# Invoke function with a payload that returns environment variables
# (demonstrates what an attacker-controlled function could exfiltrate)
aws lambda invoke --function-name TargetFunction
--payload '{"action":"env"}'
--cli-binary-format raw-in-base64-out
/tmp/lambda_response.json
cat /tmp/lambda_response.json
# Malicious Lambda handler payload — demonstrates credential exfiltration
# This is what an attacker injects via UpdateFunctionCode
import os, boto3, json
def handler(event, context):
# Execution role credentials are in the environment automatically
creds = {
"access_key": os.environ.get("AWS_ACCESS_KEY_ID"),
"secret_key": os.environ.get("AWS_SECRET_ACCESS_KEY"),
"session_token": os.environ.get("AWS_SESSION_TOKEN"),
"region": os.environ.get("AWS_REGION"),
}
# In a real attack: POST to attacker-controlled endpoint
# Here we just return them in the response for demonstration
sts = boto3.client("sts")
identity = sts.get_caller_identity()
return {"credentials_obtained": True, "identity": identity["Arn"]}
Security Assessment Methodology
- Enumerate all Lambda functions with
aws lambda list-functions. Note the execution role ARN for each function. Functions usingarn:aws:iam::aws:policy/AdministratorAccessor similar broad managed policies are immediate high-severity findings. - Enumerate execution role permissions. For each function's role, list attached and inline policies. Use
iam simulate-principal-policyto test for dangerous permissions:iam:*,s3:*,secretsmanager:GetSecretValue,sts:AssumeRole,lambda:UpdateFunctionCode. - Check invocation permissions. Retrieve the function's resource-based policy with
aws lambda get-policy --function-name TargetFunction. Determine who can invoke the function —"Principal": "*"or cross-account principals without conditions are additional findings. - Check for environment variable secrets. Retrieve function configuration and inspect
Environment.Variablesfor plaintext API keys, passwords, or connection strings. These are separate from execution role credentials but equally valuable. - Test updateability. Determine whether your assessment principal has
lambda:UpdateFunctionCodeorlambda:UpdateFunctionConfiguration. If yes, and the execution role is over-privileged, document the full escalation chain. - Remediate by applying least-privilege execution roles: each function should have a dedicated role with only the permissions that function's code requires for its specific operations. Enable AWS Lambda resource-based policy conditions to restrict who can invoke each function. Move secrets from environment variables to Secrets Manager with per-function read permissions.
Common Assessment Errors
- Only checking directly attached managed policies. Lambda execution roles often have inline policies granting broad permissions that are invisible when only listing attached managed policies. Always check both
list-attached-role-policiesandlist-role-policies. - Ignoring the invocation path. An over-privileged execution role is only exploitable if an attacker can invoke the function or modify its code. Always assess both the role permissions AND who has
lambda:InvokeFunctionorlambda:UpdateFunctionCode. - Missing Lambda layers. Code deployed via Lambda Layers may contain credentials or business logic that affects what the function can do. Enumerate layers with
aws lambda list-layersand download layer ZIPs for inspection. - Overlooking VPC-attached functions. Lambda functions attached to a VPC can reach internal resources (RDS, ElastiCache) not exposed to the internet. An over-privileged execution role in a VPC-attached function can be used to access internal databases that IAM alone would not expose.
- Not checking for EventBridge triggers. A function may be triggered automatically by scheduled events, S3 events, or API Gateway. An attacker who can write to the triggering source (e.g., an S3 bucket with weak policy) may be able to indirectly invoke the function without direct
lambda:InvokeFunctionpermission.
NICE Framework Alignment
| Code | Knowledge/Skill/Task Statement | How This Card Develops It |
|---|---|---|
| K0053 | Knowledge of security risk management processes | Assessing Lambda execution role risk: the blast radius equals the role's effective permissions, making role design a critical risk control |
| K0167 | Knowledge of system administration, network, and OS hardening techniques | Applying least-privilege design to Lambda execution roles: one dedicated role per function with only the permissions that specific function requires |
| S0073 | Skill in conducting vulnerability scans and recognizing vulnerabilities | Enumerating Lambda functions and simulating execution role permissions to identify privilege escalation paths before attackers do |
| T0144 | Conduct penetration testing as required for new or updated applications | Exploiting Lambda UpdateFunctionCode and over-privileged execution roles during AWS penetration tests to demonstrate privilege escalation impact |
| T0395 | Write code to address security vulnerabilities | Refactoring Lambda IAM roles to least-privilege inline policies and migrating environment variable secrets to Secrets Manager references |
Further Reading
- AWS Lambda Security Best Practices — AWS Documentation (docs.aws.amazon.com/lambda/latest/dg/security-iam)
- AWS IAM Privilege Escalation Methods — Rhino Security Labs, Spencer Gietzen (rhinosecuritylabs.com)
- Serverless Security — Guy Podjarny & Liran Tal, Chapter 6: Function Permissions (O'Reilly Media)
Challenge Lab
Renforcez votre apprentissage avec un défi généré basé sur la compétence de cette carte.