Writeup
Well based on the description alone it seems that there are two parts to this CTF and we are to look through tons of logs (based on the provided ZIP file, UGHHHH).
Getting Flag 1
After unzipping the file, the following information was displayed in notes.md:
# Workplan
Setup monitoring and logs analysis process for PALINDROME.
Compare products (we have 1 beta testing rights, need to source for others)
## Product 1: Meownitoring (Beta Test)
`https://d231g4hz442ywp.cloudfront.net`
1. Any sensitive info in logs / monitoring?
2. How secure is the setup?
3. Usefulness of dashboard? Buggy?
Apprently, the Meownitoring web application is simply an interface to link AWS CloudTrail logs based on an AWS IAM user for a much more presentable dashboard (well it beats the hell out of sieving through tons of JSON data). To configure a user to access its CloudTrail logs, the user has to:
- Register for a new account (signup is hassle-free, and free at the same time.).
- Configure the ARN of an AWS IAM user.
After going through the AWS CloudTrail logs, it seems that the user of interest is this particular IAM user (with its ARN):
arn:aws:iam::637423240666:user/dev
After loading this ARN value to the Meownitoring website, the app fails. However after close inspection of the HTTP traffic, there is a request to the URI ‘/download’ to retrieve a ZIP file:
Copy the URL into your web browser and you should be able to download the ZIP file. Unzip the ZIP file and you should get a series of other logs (more JSON GZ files, but this time from two different regions:
- ap-southeast-1
- us-east-1
Go through the logs and you’ll notice another ARN for another AWS IAM user:
arn:aws:iam::637423240666:role/mewonitoring-lambda-test
Use the Meownitoring web application again to find this, and whaddya know, you’ll see logs ingested by the web application:
And also, after reading through the logs, it was found that the AWS secret access key and AWS access key ID was shown clearly in the application: (debug aws_secret_access_key) is now in the clear. Using the newfound credentials, and after looking through the logs for possible S3 buckets, the following command was used (with the new credentials):
aws s3 ls s3://meownitoringtmpbucket.s3.ap-southeast-1.amazonaws.com/
┌──(kali㉿kali)-[~/Desktop/Cloud/CGCRTS]
└─$ cat flag1.txt
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⣿⡷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⡿⠋⠈⠻⣮⣳⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⣴⣾⡿⠋⠀⠀⠀⠀⠙⣿⣿⣤⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⣶⣿⡿⠟⠛⠉⠀⠀⠀⠀⠀⠀⠀⠈⠛⠛⠿⠿⣿⣷⣶⣤⣄⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣴⣾⡿⠟⠋⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠛⠻⠿⣿⣶⣦⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⣀⣠⣤⣤⣀⡀⠀⠀⣀⣴⣿⡿⠛⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠛⠿⣿⣷⣦⣄⡀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣤⣄⠀⠀
⢀⣤⣾⡿⠟⠛⠛⢿⣿⣶⣾⣿⠟⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠛⠿⣿⣷⣦⣀⣀⣤⣶⣿⡿⠿⢿⣿⡀⠀
⣿⣿⠏⠀⢰⡆⠀⠀⠉⢿⣿⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⠻⢿⡿⠟⠋⠁⠀⠀⢸⣿⠇⠀
⣿⡟⠀⣀⠈⣀⡀⠒⠃⠀⠙⣿⡆⠀⠀⠀⠀⠀⠀⠀⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⠇⠀
⣿⡇⠀⠛⢠⡋⢙⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣾⣿⣿⠄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⠀⠀
⣿⣧⠀⠀⠀⠓⠛⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⠛⠋⠀⠀⢸⣧⣤⣤⣶⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣿⡿⠀⠀
⣿⣿⣤⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠉⠉⠻⣷⣶⣶⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣿⣿⠁⠀⠀
⠈⠛⠻⠿⢿⣿⣷⣶⣦⣤⣄⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣴⣿⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣾⣿⡏⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠉⠙⠛⠻⠿⢿⣿⣷⣶⣦⣤⣄⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⠿⠛⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⢿⣿⡄⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠙⠛⠻⠿⢿⣿⣷⣶⣦⣤⣄⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢿⣿⡄⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠉⠛⠛⠿⠿⣿⣷⣶⣶⣤⣤⣀⡀⠀⠀⠀⢀⣴⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢿⡿⣄
⠀⠀⠉⠉⠛⠛⠿⠿⣿⣷⣶⡿⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⣿⣹
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣀⠀⠀⠀⠀⠀⠀⢸⣧
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢻⣿⣆⠀⠀⠀⠀⠀⠀⢀⣀⣠⣤⣶⣾⣿⣿⣿⣿⣤⣄⣀⡀⠀⠀⠀⣿
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⢿⣻⣷⣶⣾⣿⣿⡿⢯⣛⣛⡋⠁⠀⠀⠉⠙⠛⠛⠿⣿⣿⡷⣶⣿
Here's a partial flag: TISC{m@ny_inf0_frOm_l0gs_
Getting Flag 2
After getting the first flag, we are presented with even MORE notes (notes2.md), and MORE logs (UGHHH):
└─$ cat notes2.md
Item 1: Known issue with logs
Cloudtrail is not enabled prior to some deployments. However, it should have capture most events related to upcoming operations.
Evaluation of Product 1: Meownitoring (Beta Test)
Doesn't seem to be able to process large amount of logs
TODO: read up on confused deputy problem.
Item 2: Kill switch mechanism
Kill switch was introduced after EXERCISE-0x74697363 where operators had to terminate the attack on multiple systems manually, which is ineffective and inefficient.
Objective:
Develop a simple mechanism: upon invoke, terminates all attack
Put platform on "sleep" state?
Rotate the kill switch randomly (i.e., id, stage, route, method), except during designated freeze period.
Upcoming platform freeze: 1 Sep - 30 Oct 2024
TODO: Rotate kill switch before freeze period.
Now, i tried to use the same approach to go through the JSON files and abusing the ‘grep’ command, but this ended up to be so freaking tiring. It seems quite nuts to be unzipping and sieving through tons of JSON log data, so that is when i found the ‘jq’ application (along with the ‘gunzip’ command to unzip the files).
After experimenting through the commands, the following syntax was used to search for output events:
gunzip -c *.gz | jq '.Records[]
When reading through the various records, i noticed that there’s tons of activities related to Amazon Lambda API gateways (and they are of different sorts). So i modified the command above to identify the accessed Amazon Lambda API gateway endpoints (note that if you want to narrow down the logs, just run it within the ‘ap-southeast-1 2024/07/17’ folder ):
gunzip -c *.gz | jq '.Records[] | select ((.eventSource == "apigateway.amazonaws.com") and (.responseElements != null))' | less
So based from the output of this command, we managed to extract quite a number of API IDs:
From this list, we crafted and narrowed down the possible Lambda API URLs:
- https://f7x7yzf9j2.execute-api.ap-southeast-1.amazonaws.com/
- https://kv0g2hke5e.execute-api.ap-southeast-1.amazonaws.com/
- https://s14dfgslg5.execute-api.ap-southeast-1.amazonaws.com/
- https://pxzfkfmjo7.execute-api.ap-southeast-1.amazonaws.com/
From there I just needed to perform a simple GET request using Burp for all these API endpoints, and whaddya know? Only one endpoint will still be accessible as it responds with “Not Found”:
So from here, we determine that we needed to work with this API: https://pxzfkfmjo7.execute-api.ap-southeast-1.amazonaws.com/
In terms of figuring out how to interact with the API, we’ll need to figure out how to communicate with the API gateway and thank you to AWS for the lovely documentation located here: https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-call-api.html
One of the requirements to invoke the REST API is to identify the stage name (as seen in the screenshot above). A quick look into the logs and we can find that the following request reveals the ‘stage name’:
{
"eventVersion": "1.09",
"userIdentity": {
"type": "IAMUser",
"principalId": "AIDAZI2LCYXNLENAY2IQ3",
"arn": "arn:aws:iam::637423240666:user/dev",
"accountId": "637423240666", "accessKeyId": "AKIAZI2LCYXNH4OISNEW", "userName": "dev" },
"eventTime": "2024-07-17T05:56:53Z",
"eventSource": "apigateway.amazonaws.com",
"eventName": "CreateStage",
"awsRegion": "ap-southeast-1",
"sourceIPAddress": "8.29.230.19",
"userAgent": "APN/1.0 HashiCorp/1.0 Terraform/1.3.777 terraform-provider-aws/5.57.0 https://registry.terraform.io/providers/hashicorp/aws aws-sdk-go-v2/1.30.1 os/linux lang/go#1.22.4 md/GOOS#linux md/GOARCH#amd64 api/apigatewayv2#1.22.1",
"requestParameters":
{
**"stageName": "5587y0s9d5aed",**
"autoDeploy": true,
"apiId": "pxzfkfmjo7"
},
...
Even with the stage name, we will still need to know the function name, which can be found in the following log output (shows both function name and HTTP Request type as well):
{
"eventVersion": "1.09",
"userIdentity": {
"type": "IAMUser",
"principalId": "AIDAZI2LCYXNLENAY2IQ3",
"arn": "arn:aws:iam::637423240666:user/dev",
"accountId": "637423240666",
"accessKeyId": "AKIAZI2LCYXNH4OISNEW",
"userName": "dev"
},
"eventTime": "2024-07-17T05:56:53Z",
"eventSource": "apigateway.amazonaws.com",
"eventName": "UpdateRoute",
"awsRegion": "ap-southeast-1",
"sourceIPAddress": "8.29.230.19",
"userAgent": "APN/1.0 HashiCorp/1.0 Terraform/1.3.7 terraform-provider-aws/5.57.0 aws-sdk-go-v2/1.30.1 os/linux lang/go#1.22.4 md/GOOS#linux md/GOARCH#amd64 api/apigatewayv2#1.22.1",
"requestParameters": {
"routeId": "id6oeig",
"routeKey": "POST /68fd47b8bf291eeea36480872f5ce29f0edb",
"apiId": "pxzfkfmjo7"
},
"responseElements": {
"authorizationType": "NONE",
"routeId": "id6oeig",
"apiKeyRequired": false,
"routeKey": "POST /68fd47b8bf291eeea36480872f5ce29f0edb",
"target": "integrations/9wo8sps"
},
"requestID": "e5b49d72-4664-4723-9cd3-6a9a93a4d7f2",
"eventID": "64c0e31e-7de1-4cc6-9136-6d1f0cce05a7",
"readOnly": false,
"eventType": "AwsApiCall",
"managementEvent": true,
"recipientAccountId": "637423240666",
"eventCategory": "Management"
}
...
Based on the following information, we can safely create the following REST API URL, and interacting it with a POST request: https://pxzfkfmjo7.execute-api.ap-southeast-1.amazonaws.com/5587y0s9d5aed/68fd47b8bf291eeea36480872f5ce29f0edb
The following curl command was sent to the server and voila, we get the second half of the flag:
curl --path-as-is -i -s -k -X $'POST' \
-H $'Host: pxzfkfmjo7.execute-api.ap-southeast-1.amazonaws.com' -H $'Sec-Ch-Ua: \"Not;A=Brand\";v=\"24\", \"Chromium\";v=\"128\"' -H $'Sec-Ch-Ua-Mobile: ?0' -H $'Sec-Ch-Ua-Platform: \"Windows\"' -H $'Accept-Language: en-US,en;q=0.9' -H $'Upgrade-Insecure-Requests: 1' -H $'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.6613.120 Safari/537.36' -H $'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7' -H $'Sec-Fetch-Site: none' -H $'Sec-Fetch-Mode: navigate' -H $'Sec-Fetch-User: ?1' -H $'Sec-Fetch-Dest: document' -H $'Accept-Encoding: gzip, deflate, br' -H $'Priority: u=0, i' \
$'https://pxzfkfmjo7.execute-api.ap-southeast-1.amazonaws.com/5587y0s9d5aed/68fd47b8bf291eeea36480872f5ce29f0edb'
Response:
HTTP/2 200 OK
Date: Fri, 20 Sep 2024 19:46:35 GMT
Content-Type: application/json
Content-Length: 47
Apigw-Requestid: ea2cQiZYSQ0EMQg=
{"flag2": "&_me-0-wn1t0r1nNnG\\//[>^n^<]\\//}"}
Final flag:
TISC{m@ny_inf0_frOm_l0gs_&_me-0-wn1t0r1nNnG\\//[>^n^<]\\//}
Thoughts
Personally i believe that if anyone wants to succeed well in this challenge, familiarisation with the AWS platform and its various services (e.g Lambda, IAM, etc). I was pretty lucky to have been exposed to this very early on, just that the tedious part was to go through tons and tons of CloudTrail logs (that were in JSON format). And to be frank, the ‘jq’ command was seriously a godsend, so thank you to whoever had invented this tool <3
But, i think last year challenge was pretty cool as i remember dealing with IAMs and the AWS CodePipeline (which involved exploiting a vulnerability from there). In other words i was expecting more of an AWS pentest exercise for this challenge, but oh wells :) still thankful in terms of upgrading my knowledge on AWS services and more importantly processing CloudTrail logs.