# AWS - Lambda Persistence

{{#include ../../../../banners/hacktricks-training.md}}

## Lambda

For more information check:

{{#ref}}
../../aws-services/aws-lambda-enum.md
{{#endref}}

### Lambda Layer Persistence

It's possible to **introduce/backdoor a layer to execute arbitrary code** when the lambda is executed in a stealthy way:

{{#ref}}
aws-lambda-layers-persistence.md
{{#endref}}

### Lambda Extension Persistence

Abusing Lambda Layers it's also possible to abuse extensions and persist in the lambda but also steal and modify requests.

{{#ref}}
aws-abusing-lambda-extensions.md
{{#endref}}

### Via resource policies

It's possible to grant access to different lambda actions (such as invoke or update code) to external accounts:

<figure><img src="../../../../images/image (255).png" alt=""><figcaption></figcaption></figure>

### Versions, Aliases & Weights

A Lambda can have **different versions** (with different code each version).\
Then, you can create **different aliases with different versions** of the lambda and set different weights to each.\
This way an attacker could create a **backdoored version 1** and a **version 2 with only the legit code** and **only execute the version 1 in 1%** of the requests to remain stealth.

<figure><img src="../../../../images/image (120).png" alt=""><figcaption></figcaption></figure>

### Version Backdoor + API Gateway

1. Lambda の元のコードをコピーする
2. **Create a new version backdooring** the original code (or just with malicious code). Publish and **deploy that version** to $LATEST
1. Lambda に関連する API Gateway を呼び出してコードを実行する
3. **Create a new version with the original code**, Publish and deploy that **version** to $LATEST.
1. This will hide the backdoored code in a previous version
4. Go to the API Gateway and **create a new POST method** (or choose any other method) that will execute the backdoored version of the lambda: `arn:aws:lambda:us-east-1:<acc_id>:function:<func_name>:1`
1. Note the final :1 of the arn **indicating the version of the function** (version 1 will be the backdoored one in this scenario).
5. Select the POST method created and in Actions select **`Deploy API`**
6. Now, when you **call the function via POST your Backdoor** will be invoked

### Cron/Event actuator

The fact that you can make **lambda functions run when something happen or when some time pass** makes lambda a nice and common way to obtain persistence and avoid detection.\
Here you have some ideas to make your **presence in AWS more stealth by creating lambdas**.

- 新しいユーザーが作成されるたびに、lambda が新しいユーザーキーを生成して攻撃者に送信する。
- 新しい role が作成されるたびに、lambda が compromised users に対して assume role 権限を付与する。
- 新しい CloudTrail ログが生成されるたびに、それらを削除／改竄する

### RCE abusing AWS_LAMBDA_EXEC_WRAPPER + Lambda Layers

Abuse the environment variable `AWS_LAMBDA_EXEC_WRAPPER` to execute an attacker-controlled wrapper script before the runtime/handler starts. Deliver the wrapper via a Lambda Layer at `/opt/bin/htwrap`, set `AWS_LAMBDA_EXEC_WRAPPER=/opt/bin/htwrap`, and then invoke the function. The wrapper runs inside the function runtime process, inherits the function execution role, and finally `exec`s the real runtime so the original handler still executes normally.

{{#ref}}
aws-lambda-exec-wrapper-persistence.md
{{#endref}}

### AWS - Lambda Function URL Public Exposure

Abuse Lambda asynchronous destinations together with the Recursion configuration to make a function continually re-invoke itself with no external scheduler (no EventBridge, cron, etc.). By default, Lambda terminates recursive loops, but setting the recursion config to Allow re-enables them. Destinations deliver on the service side for async invokes, so a single seed invoke creates a stealthy, code-free heartbeat/backdoor channel. Optionally throttle with reserved concurrency to keep noise low.

{{#ref}}
aws-lambda-async-self-loop-persistence.md
{{#endref}}

### AWS - Lambda Alias-Scoped Resource Policy Backdoor

Create a hidden Lambda version with attacker logic and scope a resource-based policy to that specific version (or alias) using the `--qualifier` parameter in `lambda add-permission`. Grant only `lambda:InvokeFunction` on `arn:aws:lambda:REGION:ACCT:function:FN:VERSION` to an attacker principal. Normal invocations via the function name or primary alias remain unaffected, while the attacker can directly invoke the backdoored version ARN.

This is stealthier than exposing a Function URL and doesn’t change the primary traffic alias.

{{#ref}}
aws-lambda-alias-version-policy-backdoor.md
{{#endref}}

### Freezing AWS Lambda Runtimes

An attacker who has lambda:InvokeFunction, logs:FilterLogEvents, lambda:PutRuntimeManagementConfig, and lambda:GetRuntimeManagementConfig permissions can modify a function’s runtime management configuration. This attack is especially effective when the goal is to keep a Lambda function on a vulnerable runtime version or to preserve compatibility with malicious layers that might be incompatible with newer runtimes.

The attacker modifies the runtime management configuration to pin the runtime version:
```bash
# Invoke the function to generate runtime logs
aws lambda invoke \
--function-name $TARGET_FN \
--payload '{}' \
--region us-east-1 /tmp/ping.json

sleep 5

# Freeze automatic runtime updates on function update
aws lambda put-runtime-management-config \
--function-name $TARGET_FN \
--update-runtime-on FunctionUpdate \
--region us-east-1
```
適用された構成を確認してください:
```bash
aws lambda get-runtime-management-config \
--function-name $TARGET_FN \
--region us-east-1
```
オプション: 特定のランタイムバージョンに固定する
```bash
# Extract Runtime Version ARN from INIT_START logs
RUNTIME_ARN=$(aws logs filter-log-events \
--log-group-name /aws/lambda/$TARGET_FN \
--filter-pattern "INIT_START" \
--query 'events[0].message' \
--output text | grep -o 'Runtime Version ARN: [^,]*' | cut -d' ' -f4)
```
特定のランタイムバージョンに固定する:
```bash
aws lambda put-runtime-management-config \
--function-name $TARGET_FN \
--update-runtime-on Manual \
--runtime-version-arn $RUNTIME_ARN \
--region us-east-1
```
{{#include ../../../../banners/hacktricks-training.md}}
