AWS - Lambda Enum

Learn AWS hacking from zero to hero with htARTE (HackTricks AWS Red Team Expert)!

Other ways to support HackTricks:

Lambda

Amazon Web Services (AWS) Lambda is described as a compute service that enables the execution of code without the necessity for server provision or management. It is characterized by its ability to automatically handle resource allocation needed for code execution, ensuring features like high availability, scalability, and security. A significant aspect of Lambda is its pricing model, where charges are based solely on the compute time utilized, eliminating the need for initial investments or long-term obligations.

To call a lambda it's possible to call it as frequently as you wants (with Cloudwatch), expose an URL endpoint and call it, call it via API Gateway or even based on events such as changes to data in a S3 bucket or updates to a DynamoDB table.

The code of a lambda is stored in /var/task.

Lambda Aliases Weights

A Lambda can have several versions. And it can have more than 1 version exposed via aliases. The weights of each of the versions exposed inside and alias will decide which alias receive the invocation (it can be 90%-10% for example). If the code of one of the aliases is vulnerable you can send requests until the vulnerable versions receives the exploit.

Resource Policies

Lambda resource policies allow to give access to other services/accounts to invoke the lambda for example. For example this is the policy to allow anyone to access a lambda exposed via URL:

Or this to allow an API Gateway to invoke it:

Lambda Database Proxies

When there are hundreds of concurrent lambda requests, if each of them need to connect and close a connection to a database, it's just not going to work (lambdas are stateless, cannot maintain connections open). Then, if your Lambda functions interact with RDS Proxy instead of your database instance. It handles the connection pooling necessary for scaling many simultaneous connections created by concurrent Lambda functions. This allows your Lambda applications to reuse existing connections, rather than creating new connections for every function invocation.

Lambda EFS Filesystems

To preserve and even share data Lambdas can access EFS and mount them, so Lambda will be able to read and write from it.

Lambda Layers

A Lambda layer is a .zip file archive that can contain additional code or other content. A layer can contain libraries, a custom runtime, data, or configuration files.

It's possible to include up to five layers per function. When you include a layer in a function, the contents are extracted to the /opt directory in the execution environment.

By default, the layers that you create are private to your AWS account. You can choose to share a layer with other accounts or to make the layer public. If your functions consume a layer that a different account published, your functions can continue to use the layer version after it has been deleted, or after your permission to access the layer is revoked. However, you cannot create a new function or update functions using a deleted layer version.

Functions deployed as a container image do not use layers. Instead, you package your preferred runtime, libraries, and other dependencies into the container image when you build the image.

Lambda Extensions

Lambda extensions enhance functions by integrating with various monitoring, observability, security, and governance tools. These extensions, added via .zip archives using Lambda layers or included in container image deployments, operate in two modes: internal and external.

  • Internal extensions merge with the runtime process, manipulating its startup using language-specific environment variables and wrapper scripts. This customization applies to a range of runtimes, including Java Correto 8 and 11, Node.js 10 and 12, and .NET Core 3.1.

  • External extensions run as separate processes, maintaining operation alignment with the Lambda function's lifecycle. They're compatible with various runtimes like Node.js 10 and 12, Python 3.7 and 3.8, Ruby 2.5 and 2.7, Java Corretto 8 and 11, .NET Core 3.1, and custom runtimes.

Enumeration

aws lambda get-account-settings

# List functions and get extra config info
aws lambda list-functions
aws lambda get-function --function-name <function_name>
aws lambda get-function-configuration --function-name <function_name>
aws lambda list-function-event-invoke-configs --function-name <function_name>
## Check for creds in env vars
aws lambda list-functions | jq '.Functions[].Environment'
## Download & check the source code
aws lambda get-function --function-name "<func_name>" --query 'Code.Location'
wget -O lambda-function.zip <url-from-previous-query>

# Get Lambda URL (if any)
aws lambda list-function-url-configs --function-name <function_name>
aws lambda get-function-url-config --function-name <function_name>

# Get who has permissions to invoke the Lambda
aws lambda get-policy --function-name <function_name>

# Versions and Aliases
aws lambda list-versions-by-function --function-name <func_name>
aws lambda list-aliases --function-name <func_name>

# List layers
aws lambda list-layers
aws lambda list-layer-versions --layer-name <name>
aws lambda get-layer-version --layer-name <name> --version-number <ver>
aws lambda get-layer-version-by-arn --arn <name> #Get external ARNs

# List other metadata
aws lambda list-event-source-mappings
aws lambda list-code-signing-configs
aws lambda list-functions-by-code-signing-config --code-signing-config-arn <arn>

Invoke a lambda

Manual

# Invoke function
aws lambda invoke --function-name FUNCTION_NAME /tmp/out
## Some functions will expect parameters, they will access them with something like:
## target_policys = event['policy_names']
## user_name = event['user_name']
aws lambda invoke --function-name <name> --cli-binary-format raw-in-base64-out --payload '{"policy_names": ["AdministratorAccess], "user_name": "sdf"}' out.txt

Via exposed URL

aws lambda list-function-url-configs --function-name <function_name> #Get lambda URL
aws lambda get-function-url-config   --function-name <function_name> #Get lambda URL

Call Lambda function via URL

Now it's time to find out possible lambda functions to execute:

aws --region us-west-2 --profile level6 lambda list-functions

A lambda function called "Level6" is available. Lets find out how to call it:

aws --region us-west-2 --profile level6 lambda get-policy --function-name Level6

Now, that you know the name and the ID you can get the Name:

aws --profile level6 --region us-west-2 apigateway get-stages --rest-api-id "s33ppypa75"

And finally call the function accessing (notice that the ID, Name and function-name appears in the URL): https://s33ppypa75.execute-api.us-west-2.amazonaws.com/Prod/level6

URL:https://<rest-api-id>.execute-api.<region>.amazonaws.com/<stageName>/<funcName>

Other Triggers

There are a lot of other sources that can trigger a lambda

Privesc

In the following page you can check how to abuse Lambda permissions to escalate privileges:

Unauthenticated Access

Post Exploitation

Persistence

References

Learn AWS hacking from zero to hero with htARTE (HackTricks AWS Red Team Expert)!

Other ways to support HackTricks:

Last updated