Browse CTFs New CTF Sign in

AWS Lambda Execution Role Privilege Escalation: Function Invocation for IAM Abuse

osint_collection Difficulté 1–5 30 min certifiable

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

  1. Enumerate all Lambda functions with aws lambda list-functions. Note the execution role ARN for each function. Functions using arn:aws:iam::aws:policy/AdministratorAccess or similar broad managed policies are immediate high-severity findings.
  2. Enumerate execution role permissions. For each function's role, list attached and inline policies. Use iam simulate-principal-policy to test for dangerous permissions: iam:*, s3:*, secretsmanager:GetSecretValue, sts:AssumeRole, lambda:UpdateFunctionCode.
  3. 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.
  4. Check for environment variable secrets. Retrieve function configuration and inspect Environment.Variables for plaintext API keys, passwords, or connection strings. These are separate from execution role credentials but equally valuable.
  5. Test updateability. Determine whether your assessment principal has lambda:UpdateFunctionCode or lambda:UpdateFunctionConfiguration. If yes, and the execution role is over-privileged, document the full escalation chain.
  6. 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-policies and list-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:InvokeFunction or lambda: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-layers and 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:InvokeFunction permission.

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.