# Lambda Function Enumeration

> Techniques for enumerating AWS Lambda functions, extracting configurations, environment variables, permissions, and identifying misconfigurations for potential exploitation.

- **URL:** https://hackindex.io/platforms/aws/enumeration/lambda/lambda-function-enumeration
- **Path:** AWS > Enumeration > Lambda
- **Up:** [Lambda](https://hackindex.io/platforms/aws/enumeration/lambda.md)
- **Published:** 2026-05-24
- **Updated:** 2026-05-24

Lambda functions frequently store credentials in environment variables and run with overpermissioned execution roles. Function code itself often contains hardcoded secrets or internal API endpoints. Start enumeration here before moving to IAM policies. You need at minimum `lambda:ListFunctions` to see functions in the account. Without it, the call returns an access denied error and you get no output. In shared or misconfigured accounts, some users have this permission without realizing it. The runtime and last-modified date tell you which functions are active and which runtimes to target for known vulnerabilities.

- Environment variables with plaintext credentials (DB URLs, API keys, tokens)
- Execution roles with `iam:*`, `s3:*`, or `sts:AssumeRole` on broad resources
- Function URLs with `AuthType: NONE` (publicly invocable, no authentication)
- Downloadable deployment packages containing hardcoded secrets in source code
- Shared layers with connection strings or internal SDK credentials

## List Functions

```bash
aws lambda list-functions --profile $PROFILE --region $REGION --query 'Functions[*].{Name:FunctionName,Runtime:Runtime,Role:Role,Modified:LastModified}' --output table
```

## Get Function Configuration

Includes environment variables, execution role, timeout, memory, and VPC config. The VPC section matters when the function has access to private subnets. A function inside a VPC can reach internal resources not exposed externally. Timeout and memory values indicate what the function does. A 15-minute timeout with high memory suggests batch processing or a heavyweight job. A short timeout points to a lightweight trigger or webhook handler.

```bash
aws lambda get-function-configuration --function-name $FUNCTION_NAME --profile $PROFILE --region $REGION
```

Environment variables are returned in plaintext if you have `lambda:GetFunction` or `lambda:GetFunctionConfiguration`. This is one of the highest-yield checks in Lambda enumeration. Developers treat environment variables as secret storage because they are not visible in the console to casual users. The API returns them without any additional decryption step unless the function uses KMS to encrypt them at the application level. If the output shows a `KMSKeyArn`, the values may appear as ciphertext. Most environments skip that extra layer.

**Extract environment variables**

```bash
aws lambda get-function-configuration --function-name $FUNCTION_NAME --profile $PROFILE --region $REGION | jq '.Environment.Variables'
```

Common findings: `DATABASE_URL`, `API_KEY`, `SECRET_KEY`, `AWS_ACCESS_KEY_ID`, `SLACK_TOKEN`. Any `AWS_ACCESS_KEY_ID` value represents a separate set of AWS credentials. Check whether that key belongs to a user or a role. User keys have long-term validity unless rotated. Add any found credentials to your profile list and enumerate their permissions separately. Third-party API keys are useful for expanding scope or demonstrating impact beyond the AWS environment.

## Download Function Code

Get a pre-signed URL to download the deployment package. The URL is temporary and expires quickly. Download the zip and inspect the source before it expires. For Node.js functions, check `node_modules` for pinned dependency versions with known CVEs. For Python functions, look at `requirements.txt` and any inline imports. The code often reveals internal API routes, other Lambda function names, and the data structures the function processes. Functions that call other services frequently hardcode resource names or account IDs in the code rather than using environment variables.

**Get code URL**

```bash
aws lambda get-function --function-name $FUNCTION_NAME --profile $PROFILE --region $REGION | jq -r '.Code.Location'
```

**Download and grep for secrets**

```bash
URL=$(aws lambda get-function --function-name $FUNCTION_NAME --profile $PROFILE --region $REGION | jq -r '.Code.Location')
curl -s "$URL" -o function.zip
unzip function.zip -d function_code/
grep -r "key\|secret\|password\|token\|credential" function_code/ --include="*.py" --include="*.js" -i
```

## Execution Role

The role ARN is in the function configuration under `Role`. Extract the role name from the ARN: it is the segment after `role/`. Then enumerate both attached and inline policies. Inline policies are often missed and can grant broader access than attached managed policies. Use `list-role-policies` to see inline policies alongside `list-attached-role-policies`.

```bash
aws iam get-role --role-name $ROLE_NAME --profile $PROFILE
aws iam list-attached-role-policies --role-name $ROLE_NAME --profile $PROFILE
```

A Lambda execution role with `iam:*` or `s3:*` on `*` is a direct privilege escalation path. See [IAM PassRole Lambda Escalation](https://hackindex.io/platforms/aws/privilege-escalation/iam/iam-passrole-lambda-ec2-escalation). Also check for `sts:AssumeRole` on other roles. A function that can assume a more privileged role is a stepping stone. Permissions like `ec2:*` or `secretsmanager:GetSecretValue` on `*` are high-value. Even a limited permission like `lambda:UpdateFunctionCode` can be an escalation path if you can modify the function to run arbitrary code under its own role.

## Layers

```bash
aws lambda list-layers --profile $PROFILE --region $REGION
aws lambda get-layer-version --layer-name $LAYER_NAME --version-number 1 --profile $PROFILE --region $REGION
```

Layers can contain shared libraries and configuration, and they are worth downloading if accessible. A layer might hold shared authentication logic, internal SDKs, or configuration files with connection strings. To download, extract the `Content.Location` URL from the layer version response and fetch it the same way as function code. Layers shared across multiple functions are especially valuable: credentials stored in a layer apply to every function that uses it.

## Event Source Mappings

Shows what triggers each function: SQS queues, DynamoDB streams, Kinesis streams, and similar sources. The mapping reveals internal queue and stream names. Use those names to understand the application's data flow. If you have write access to a trigger source such as an SQS queue, you control the input the function receives. This is relevant for input validation bypasses or injecting payloads into the function's processing logic.

```bash
aws lambda list-event-source-mappings --function-name $FUNCTION_NAME --profile $PROFILE --region $REGION
```

## Function URLs

Lambda function URLs expose functions directly over HTTPS without API Gateway. They are less commonly audited than API Gateway endpoints. The URL is stable and does not rotate unless explicitly deleted and recreated. Check the `AuthType` field in the response. `AWS_IAM` requires signed requests, which limits access to callers with valid AWS credentials and the correct permissions.

```bash
aws lambda list-function-url-configs --function-name $FUNCTION_NAME --profile $PROFILE --region $REGION
```

Auth type `NONE` means the function is publicly invocable without any authentication. Anyone with the URL can call the function. The URL appears under `FunctionUrl` in the response. Test whether the function accepts arbitrary payloads or enforces input validation. Functions with no auth and no input validation are common injection targets. Even if the function performs limited actions, it may trigger other services or pass untrusted input downstream.

## Invoke a Function

If you have `lambda:InvokeFunction`, call the function directly with a controlled payload. Use an empty JSON object as the initial payload to observe the default behavior. The response writes to `output.json`. A 200 status means the function ran synchronously. A 202 means it was queued asynchronously. Error output also writes to `output.json` and often reveals internal stack traces, framework versions, and dependency paths.

```bash
aws lambda invoke --function-name $FUNCTION_NAME --payload '{}' output.json --profile $PROFILE --region $REGION
cat output.json
```

Useful for testing RCE paths or triggering functions that perform privileged actions. If the function interacts with other AWS services, invoking it with controlled input may expose those service calls in error output. Functions that write to S3, send emails, or update DynamoDB records can be abused when you control their input. After invoking, check CloudWatch Logs if you have access: log output often contains debug information, internal hostnames, and data the function processed during the call.
