Testimonial
Writeup for Testimonial (Web) - HackTheBox Cyber Apocalypse CTF (2024) 💜
Last updated
Writeup for Testimonial (Web) - HackTheBox Cyber Apocalypse CTF (2024) 💜
Last updated
As the leader of the Revivalists you are determined to take down the KORP, you and the best of your faction's hackers have set out to deface the official KORP website to send them a message that the revolution is closing in.
We have a Go application with two ports (1337
and 50045
) that allows us to submit a testimonial, along with our name. Initial tests don't yield any results, so we may as well check the source code.
Tip: you can install VSCode extensions for syntax highlighting, I recommend the templ
one for this challenge.
Note, when running the local docker instance, I immediately notice a warning message.
I saw this on another challenge (LockTalk
- python-jwt
) and it also caught my attention. In that case, the JWT package was out-of-date and there was a known vulnerability. Let's see if this challenge is the same 🤞
We are using the v0.2.543 version but it is only 3 months old. The only release since is ~1 week ago so it's highly unlikely to be the intended path. Furthermore, I don't see any patched security issues in the changelog.
Checking the entrypoint.sh
file, the flag filename is randomised and it's moved to the root directory, hinting our goal is RCE.
Let's give the code to ChatGPT for a quick summary.
Application Structure:
RickyService (gRPC Service):
Defines a single RPC method SubmitTestimonial
for submitting testimonials.
TestimonialSubmission Message:
Contains information about a testimonial, including customer
and testimonial
fields.
GenericReply Message:
Represents a generic reply with a message
field.
Server (main.go
and grpc.go
):
Uses Chi router to serve static files from the "public" directory.
Implements a gRPC server with a single service (RickyService
) and a method (SubmitTestimonial
).
Client (client.go
):
Provides a gRPC client for submitting testimonials.
Handlers (home.go
and shared.go
):
Handles HTTP requests, allowing users to submit testimonials via the web interface.
Workflow:
Clients can submit testimonials via the web interface by accessing the home page.
The HandleHomeIndex
function processes the submitted data, sanitizes it, and sends it to the gRPC server using the client.
The gRPC server receives the testimonial, processes it, and returns a generic reply.
Important Notes:
The application uses Protocol Buffers for defining messages and gRPC for communication.
The server serves static files using the Chi router and implements a gRPC server.
The client communicates with the gRPC server to submit testimonials.
The ptypes.proto
file defines the message and service contracts.
Generated Go files (ptypes_grpc.pb.go
and ptypes.pb.go
) provide implementations of the defined messages and service.
What can I take away from this? Probably to investigate gRPC
, Chi router
, and Protocol Buffers
to see if there are any common vulns/attacks. I don't know much about any of those things or golang
, so I analysing the code is painful.
While transferring the code to ChatGPT, one particular function stood out for obvious reasons.
Note: ChatGPT spotted the code but attributed it to the wrong function (HandleHomeIndex
), in a completely different file. You had one job ChatGPT!! I tried to ask about potential vulns but it really did not want to play. Guess we will do this the old way 🧠
One interesting thing is the code indicates that the testimonials we submit are written to public/testimonials/
but every time I check the directory in the browser there is only 1.txt 2.txt 3.txt
.
Eventually I spotted the 0644
perms and got a shell on the local docker instance to confirm files were being written, they just weren't publicly viewable.
There are some good gRPC tools and resources on this repo.
Maybe we can interact with the service on port 50045
directly using grpcurl.
We'll start by listing services.
Unfortunately, lots of commands fail due to not supporting the reflection API.
We can list the services by specifying the proto file.
Next, describe the service.
And method.
Try again to invoke the RPC.
According to the docs:
To use
grpcurl
on servers that do not support reflection, you can use.proto
source files.
In addition to using
-proto
flags to pointgrpcurl
at the relevant proto source file(s), you may also need to supply-import-path
flags to tellgrpcurl
the folders from which dependencies can be imported.
When we check the webpage, we will see our submission! We've essentially bypassed the blacklist filter by submitting the testimonial directly.
Let's confirm that.
It failed to open that file, because it failed to read the filename. Remember:
How about directory traversal? If we input ../../../../test.txt
, will it be written to /
?
We can check the local docker instance.
It is! The next part took me a long time - trying to work out how to gain RCE. I was mostly trying to inject payloads into the page, to no avail. In the end, I used the path traversal vuln to replace index.templ
with a malicious one.
Ask ChatGPT to escape it for me ofc 😁
Reload the page and get the flag filename, then update our command.
Flag: HTB{w34kly_t35t3d_t3mplate5}