Tags: python3 python ssti hacktivityconctf hacktivityconctf2020 template-injection flask jinja2 

Rating:

An in-depth look at Template Shack from the amazing H@cktivityCon. Thanks to every person behind this CTF, I loved playing it with my team!


Description

Web, 150 points

Check out the coolest web templates online! Connect here: http://jh2i.com:50023

Solution

Let's start by opening the web application.

Template Shack

We are given a site selling website templates. As you can probably see, there is a login functionality, but no way of registering. That must be for admins only. By looking at the page's source, we can find an interesting TODO note.

TODO Comment

That confirms that there is an admin section, let's try to access it. I first tried /admin which finally was the right path. The only problem is that we get a 401 unauthorized error code (which is obvious). By checking in the Developer Tools, we can find a JWT cookie named token. We can use jwt.io's awesome JWT debugger to get information from that token.

JWT Debug

JWT - Weak Secret

If somewhat we could change the username value in the payload from "guest" to "admin" we should supposedly get access to the unfinished admin section. I tried some common JWT attacks until I found the working one: cracking a weak secret. By cracking the secret, we can sign any token we want. This property comes from how JWT works. If you want to learn more about it, check jwt.io.

Let's use JohnTheRipper to crack the secret.

echo "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6Imd1ZXN0In0.9SvIFMTsXt2gYNRF9I0ZhRhLQViY-MN7VaUutz9NA9Y" > for_john.hash
john for_john.hash -w=/usr/share/wordlists/rockyou.txt

In a short amount of time (a few milliseconds on my laptop), we get the secret "supersecret". We can now sign an admin token. This can be done easily using, again, jwt.io's JWT debugger.

Signing an Admin Token

Let's now input that in the token's cookie value and we get the access to the admin section. At this point, I thought this was the end, but I couldn't find the flag anywhere. After having a brief conversation with xCthulhu, one of my teammates who had solved this challenge, I was told to go further, and that there was another bug to exploit.

Server-Side Template Injection

By messing around with the admin panel, we can find that there is a custom 404 page (as seen when clicking on Charts or Tables). In Flask web applications using Jinja2's templating language, this can often lead to an SSTI, or Server-Side Template Injection. You can test for this by passing an expression between two sets of brackets (because that is how Jinja2 works). For instance, by trying to reach the page {{ 2+2 }}, the 404 page should display /admin/4 (the expression would be evaluated).

SSTI

Learn more about Flask Jinja2 SSTI here.

After a bit of tinkering, I came up with the following payload to achieve a command injection.

http://jh2i.com:50023/admin/%7B%7B%20''.__class__.__mro__[1].__subclasses__()[405]('ls',%20shell=True,%20stdout=-1).communicate()%20%7D%7D

SSTI to Command Injection (ls)

The flag can be found in admin/flag.txt. Use the previous payload with cat flag.txt instead of ls to read that file.

This challenge, involving 2 types of bugs I hadn't encountered in CTFs that much yet, was really fun to solve. I loved H@cktivityCon, even though I had a bit of difficulty with some of the challenges that seemed less obvious to me. Anyway, thanks a lot to everybody behind it, it was a lot of fun!

Original writeup (https://noxtal.com/writeups/2020/08/02/hacktivitycon-template-shack/).