Jinjatic - Web
Let’s take some time to look at the challenge name for a second:
- Jinjatic
This is pretty obvious, the challenge makes a reference to Jinja which is a Python templating engine.
Because of that, it’ll probably be a SSTI (Server Side Template Injection) vulnerability.
Analyze of the Dockerfile:
The main objective of that challenge is to execute the binary getflag in the root directory /, which allows us to read the flag in the /root/flag.txt file.
Okay, so on the website, we have a form to send an e-mail address of a client, and it should generate an “email model” with a template by passing our email as parameter.
In the following screenshot, the email_template variable is a string, which contains a %s that will take
the email pass as parameter on the website.

Then, with the new string, it’ll render the template.
So clearly, because our email is injecting in the string before the template was rendered, we have a SSTI here.
Okay, just we can try a little injection to check if our SSTI works as expected. As you know for Jinja, the “test” template is usually like that: {{7*7}}:
{{7*7}}@gmail.com, and we got: 49@gmail.com, so it’s working.

So we can try an injection found on HackTricks:
{{ cycler.__init__.__globals__.os.popen('id').read() }}@mail.com
but there’s a catch. The email address is invalid for the backend validation.
Why? Because of their backend check, made with EmailStr class of the pydantic module.
When we look at their documentation, we can read that they’re using the email-validator module. This particular module accept the display name in the email address:

So, I tried to put my payload in the display name of the email address, and it worked:
"{{cycler.__init__.__globals__.os.popen('id').read()}}" <test@mail.com>

Okay, we just need to execute the getflag command now, and we’ll get the flag.
"{{cycler.__init__.__globals__.os.popen('/getflag').read()}}" <test@mail.com>
