Server-Side Template Injection (SSTI)


Server-Side Template Injection Explained - PwnFunction


If Jinja2 evaluates {{7*7}} to 49 or 7777777, then it is vulnerable to SSTI. The naive idea is to inject {{ import os ; os.system('id') }}, but import is filtered by Jinja2. Remember that everything in Python is an object, hence we can reach the same goal utilizing a chain of gadgets. For example:
Here ''.__class__.__base__.__subclasses__()[139] refers to the class <class 'warnings.catch_warnings'>. The index 139 may vary on different machines so you need to figure it out. Use the following code to print out a lookup table and look for <class 'warnings.catch_warnings'>:
for index, item in enumerate(''.__class__.__base__.__subclasses__()):
print(index, item)
We choose this class since it imports sys. This fact can be verified by viewing CPython source code:
For me, the index is 139, therefore the final payload is:
For Flask, there is a shortcut. Check out the source code of flask.url_for():
Note that this file imports os, hence the payload is:
Takeaway: Never do eval(code + input).