Writeups for solved UMassCTF 2024 web challenges (3/5)
web/Spongebobs Homepage
Welcome to this great website about myself! Hope you enjoy ;) DIRBUSTER or any similar tools are NOT allowed.
There is a #command-injection in the /assets/image path in size query parameter. The size is passed on to the convert-im6.q16 command. When I tried various command injection payloads, it resulted in an error.
During my tries, I wasn’t able to escape from the current command, so I just looked for available arguments. I learned can use -set argument in convert-im6.q16 to set meta tags to the image. This resulted to the following payload: 200 -set Flag "$(cat flag.txt | base64)". Encoding in base64 is not really required for this challenge.
I’ve created a new game called Crabby Clicker! It’s a fun game where you click on a crab to get points. Once you get enough points, you can buy the flag!
We are given a #go server which apparently has bugs in it. We needed to click 100 times by sending requests to the /click endpoint. The bug was the state is not saved accross requests. I think doing in HTTP resets the connection so I tried doing in TCP in pwn and it worked.
packagemainimport("bufio""fmt""net""os""strings""time")typeRequestHandlerstruct{burgersintconnnet.Conn}varGLOBAL_STATERequestHandlerfuncmain(){// Listen on TCP port 8080 on all interfaces.
ln,err:=net.Listen("tcp",":1337")iferr!=nil{fmt.Println("Error listening:",err.Error())return}deferln.Close()fmt.Println("Listening on :1337")GLOBAL_STATE=RequestHandler{burgers:0,conn:nil}for{// Accept a connection.
conn,err:=ln.Accept()iferr!=nil{fmt.Println("Error accepting: ",err.Error())return}// burger to the GLOBAL_STATE from the request handler so we can track between requests
handler:=RequestHandler{burgers:GLOBAL_STATE.burgers,conn:conn}gohandler.handleRequest()}}func(r*RequestHandler)handleRequest(){deferr.conn.Close()reader:=bufio.NewReader(r.conn)for{// Set a deadline for reading. If a second passes without reading any data, a timeout will occur.
r.conn.SetReadDeadline(time.Now().Add(1*time.Second))// Read and parse the request headers
request,err:=readHTTPHeader(reader)iferr!=nil{return}requestLines:=strings.Split(request,"\n")iflen(requestLines)<1{fmt.Println("Invalid request")return}// Parse the request line
requestLine:=strings.Fields(requestLines[0])iflen(requestLine)<3{fmt.Println("Invalid request")return}method:=requestLine[0]uri:=requestLine[1]// Check if the request is a valid GET request
ifmethod!="GET"{r.conn.Write([]byte("HTTP/1.1 405 Method Not Allowed\r\n\r\n"))return}// Handle GET request
ifuri=="/"{r.generateResponse(`
Welcome to Crabby Clicker!
A HTTP based clicker game where you can earn burgers to get the flag.
Make a request to /click to gain a burger.
I use my own custom HTTP server implementation to manage the state of the game.
It's not fully working, I am running into some bugs.
`)}elseifuri=="/click"{// BUG: Weird thing where the state is not updated between requests??
r.burgers++r.generateResponse("burger added")}elseifuri=="/flag"{ifr.burgers>=100{r.generateResponse("fmt.Sprintf("Flag:UMASS{%s}", os.Getenv("FLAG")"))}else{r.generateResponse("Not enough burgers")}}else{r.generateResponse("Not found")}}}func(r*RequestHandler)generateResponse(messagestring){r.conn.Write([]byte(fmt.Sprintf("HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n%s\nburgers: %d\n",message,r.burgers)))}funcreadHTTPHeader(reader*bufio.Reader)(string,error){// Read headers until \r\n\r\n
varrequestLines[]stringfor{line,err:=reader.ReadString('\n')iferr!=nil{return"",err}requestLines=append(requestLines,line)// Check if the current line marks the end of the headers
ifline=="\r\n"{break}}returnstrings.Join(requestLines,""),nil}
Sponbebob’s birthday party invitation. It requires specific headers to enter. When we first view the webpage, it said requires a User-Agent. We can see the requirements/hints in the response as we progress.
Challenges:
CONGRATS, you got invited to my birthday party! To gain your ticket for entrance, you must first prove that your browser is from “Bikini Bottom”!
Good to see you here, mate. Sorry, but you’re too early for the Spongebob Squarepant’s birthday party!
Bravo! You made it just on time! But… I’ve been trying to learn French… can you speak French?
C’est très chouette! Suddenly I really miss my great-grandma (இ﹏இ`。) Can you get me some cookies? I want a cookie with the “flavor” of “chocolate_chip”
So yummy! I now grant you the ticket of entrance to the party, but can you find your way in? .
For challenge 5, The response sets a cookie to Login=base64({"loggedin": false}). Looks like it needs to be set to true