Problem

Solution

After starting a challenge instance, we can take a look at this cool website for ourselves:

It’s implied that this website is vulnerable to SSTI, or server side template injection. Websites use template engines to create dynamic content, and SSTI vulnerabilities arise when user-supplied input is supplied to these template engines. Malicious actors may exploit this to inject code into the site.

Before we assume the role of an attacker, we must first identify the template engine in use as this will influence our choice of payload. I found the following diagram from Cobalt to be very helpful:

So let’s start with ${7*7}. I’ll save bandwidth and just tell you it rendered the literal string ${7*7}. Following the diagram, I then tried {{7*7}}, which is shown below.

Note that 7*7 was evaluated! Then for {{7*'7'}}:

Similarly, the input was evaluated. Therefore, this site is in fact vulnerable, and is using either Jinja2 or Twig. Both options are Python libraries, hence our payload will consist of Python.

If we try something like {{request}}, we can access the request object itself:

From here, essentially everything can be accessed via magic methods. In researching Python SSTI, I discovered a great post by OnSecurity that details the different ways to do this. For instance, the following payload executes ls in the same directory as the server:

{{request.application.__globals__.__builtins__.__import__('os').popen('ls').read()}}

And of course we are interested in flag. So we can adapt this payload to run cat flag:

{{request.application.__globals__.__builtins__.__import__('os').popen('cat flag').read()}}