HTB{qu35t_f0r_th3_f0rb1dd3n_t3mpl4t35!!}
O desafio nos apresenta a uma tela onde existe um campo passível de (CWE-918) Server-Side Request Forgery (SSRF). Entretanto, o foco principal do desafio não é esse.
Ao analisar o código fonte, temos que:
tmpl, err := template.New("page").Parse(tmplFile)
if err != nil {
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
return
}
Ou seja, a página solicitada é demonstrada na aplicação de forma renderizada (passada pela função Parse
). Assim, podemos tentar executar um (CWE-1336) Server-Side Template Injection (SSTI) para conseguirmos acesso a funções privilegiadas.
Em GO, os templates somente aceitam structs
. Podemos acessar todas as structs
locais utilizando o {{ . }}
.
Para fazer isso, iremos utilizar o Pastebin para criar esse payload. Ao enviar o payload em formato raw
para a aplicação, recebemos a seguinte resposta:
Parece que temos um (CWE-1336) Server-Side Template Injection (SSTI) funcional! Agora, só precisamos explorar o código fonte para tentar encontrar alguma função declarada que possa nos ajudar.
Explorando o código fonte, nos deparamos com uma função bem conveniente. Sendo ela:
func (p RequestData) FetchServerInfo(command string) string {
out, err := exec.Command("sh", "-c", command).Output()
if err != nil {
return ""
}
return string(out)
}
Assim, podemos chamar a função FetchServerInfo
para conseguirmos um (CWE-94) Improper Control of Generation of Code (‘Code Injection’).
Ao criar o payload {{ .FetchServerInfo "ls -la ../" }}
e enviá-lo para a aplicação, podemos obter a seguinte resposta:
Pronto! Agora basta pegar a flag com {{ .FetchServerInfo "cat ../flag0afeb09c5f.txt" }}
.