Server-Side Template Injection (SSTI)
Last updated
Last updated
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'>
:
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)
.